boolean compare()

in oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/MapRecord.java [406:536]


    boolean compare(MapRecord before, final NodeStateDiff diff) {
        if (Record.fastEquals(this, before)) {
            return true;
        }

        Segment segment = getSegment();
        int head = segment.readInt(getRecordNumber());
        if (isDiff(head)) {
            int hash = segment.readInt(getRecordNumber(), 4);
            RecordId keyId = segment.readRecordId(getRecordNumber(), 8);
            final String key = reader.readString(keyId);
            final RecordId value = segment.readRecordId(getRecordNumber(), 8, 1);
            MapRecord base = reader.readMap(segment.readRecordId(getRecordNumber(), 8, 2));

            boolean rv = base.compare(before, new DefaultNodeStateDiff() {
                @Override
                public boolean childNodeAdded(String name, NodeState after) {
                    return name.equals(key)
                            || diff.childNodeAdded(name, after);
                }
                @Override
                public boolean childNodeChanged(
                        String name, NodeState before, NodeState after) {
                    return name.equals(key)
                            || diff.childNodeChanged(name, before, after);
                }
                @Override
                public boolean childNodeDeleted(String name, NodeState before) {
                    return diff.childNodeDeleted(name, before);
                }
            });
            if (rv) {
                MapEntry beforeEntry = before.getEntry(key);
                if (beforeEntry == null) {
                    rv = diff.childNodeAdded(
                            key,
                            reader.readNode(value));
                } else if (!value.equals(beforeEntry.getValue())) {
                    rv = diff.childNodeChanged(
                            key,
                            beforeEntry.getNodeState(),
                            reader.readNode(value));
                }
            }
            return rv;
        }

        Segment beforeSegment = before.getSegment();
        int beforeHead = beforeSegment.readInt(before.getRecordNumber());
        if (isDiff(beforeHead)) {
            int hash = beforeSegment.readInt(before.getRecordNumber(), 4);
            RecordId keyId = beforeSegment.readRecordId(before.getRecordNumber(), 8);
            final String key = reader.readString(keyId);
            final RecordId value = beforeSegment.readRecordId(before.getRecordNumber(), 8, 1);
            MapRecord base = reader.readMap(beforeSegment.readRecordId(before.getRecordNumber(), 8, 2));

            boolean rv = this.compare(base, new DefaultNodeStateDiff() {
                @Override
                public boolean childNodeAdded(String name, NodeState after) {
                    return diff.childNodeAdded(name, after);
                }
                @Override
                public boolean childNodeChanged(
                        String name, NodeState before, NodeState after) {
                    return name.equals(key)
                            || diff.childNodeChanged(name, before, after);
                }
                @Override
                public boolean childNodeDeleted(String name, NodeState before) {
                    return name.equals(key)
                            || diff.childNodeDeleted(name, before);
                }
            });
            if (rv) {
                MapEntry afterEntry = this.getEntry(key);
                if (afterEntry == null) {
                    rv = diff.childNodeDeleted(
                            key,
                            reader.readNode(value));
                } else if (!value.equals(afterEntry.getValue())) {
                    rv = diff.childNodeChanged(
                            key,
                            reader.readNode(value),
                            afterEntry.getNodeState());
                }
            }
            return rv;
        }

        if (isBranch(beforeHead) && isBranch(head)) {
            return compareBranch(before, this, diff);
        }

        Iterator<MapEntry> beforeEntries = before.getEntries().iterator();
        Iterator<MapEntry> afterEntries = this.getEntries().iterator();

        MapEntry beforeEntry = nextOrNull(beforeEntries);
        MapEntry afterEntry = nextOrNull(afterEntries);
        while (beforeEntry != null || afterEntry != null) {
            int d = compare(beforeEntry, afterEntry);
            if (d < 0) {
                assert beforeEntry != null;
                if (!diff.childNodeDeleted(
                        beforeEntry.getName(), beforeEntry.getNodeState())) {
                    return false;
                }
                beforeEntry = nextOrNull(beforeEntries);
            } else if (d == 0) {
                assert beforeEntry != null;
                assert afterEntry != null;
                if (!beforeEntry.getValue().equals(afterEntry.getValue())
                        && !diff.childNodeChanged(
                                beforeEntry.getName(),
                                beforeEntry.getNodeState(),
                                afterEntry.getNodeState())) {
                    return false;
                }
                beforeEntry = nextOrNull(beforeEntries);
                afterEntry = nextOrNull(afterEntries);
            } else {
                assert afterEntry != null;
                if (!diff.childNodeAdded(
                        afterEntry.getName(), afterEntry.getNodeState())) {
                    return false;
                }
                afterEntry = nextOrNull(afterEntries);
            }
        }

        return true;
    }