Search in sources :

Example 1 with UpdateOperation

use of org.structr.web.diff.UpdateOperation in project structr by structr.

the class Importer method diffNodes.

public static List<InvertibleModificationOperation> diffNodes(final DOMNode sourceNode, final DOMNode modifiedNode) {
    if (sourceNode == null) {
        logger.warn("Source node was null, returning empty change set.");
        return Collections.EMPTY_LIST;
    }
    if (modifiedNode == null) {
        logger.warn("Modified node was null, returning empty change set.");
        return Collections.EMPTY_LIST;
    }
    final List<InvertibleModificationOperation> changeSet = new LinkedList<>();
    final Map<String, DOMNode> indexMappedExistingNodes = new LinkedHashMap<>();
    final Map<String, DOMNode> hashMappedExistingNodes = new LinkedHashMap<>();
    final Map<DOMNode, Integer> depthMappedExistingNodes = new LinkedHashMap<>();
    final Map<String, DOMNode> indexMappedNewNodes = new LinkedHashMap<>();
    final Map<String, DOMNode> hashMappedNewNodes = new LinkedHashMap<>();
    final Map<DOMNode, Integer> depthMappedNewNodes = new LinkedHashMap<>();
    InvertibleModificationOperation.collectNodes(sourceNode, indexMappedExistingNodes, hashMappedExistingNodes, depthMappedExistingNodes);
    InvertibleModificationOperation.collectNodes(modifiedNode, indexMappedNewNodes, hashMappedNewNodes, depthMappedNewNodes);
    // iterate over existing nodes and try to find deleted ones
    for (final Iterator<Map.Entry<String, DOMNode>> it = hashMappedExistingNodes.entrySet().iterator(); it.hasNext(); ) {
        final Map.Entry<String, DOMNode> existingNodeEntry = it.next();
        final DOMNode existingNode = existingNodeEntry.getValue();
        final String existingHash = existingNode.getIdHash();
        // check for deleted nodes ignoring Page nodes
        if (!hashMappedNewNodes.containsKey(existingHash) && !(existingNode instanceof Page)) {
            changeSet.add(new DeleteOperation(hashMappedExistingNodes, existingNode));
        }
    }
    // iterate over new nodes and try to find new ones
    for (final Iterator<Map.Entry<String, DOMNode>> it = indexMappedNewNodes.entrySet().iterator(); it.hasNext(); ) {
        final Map.Entry<String, DOMNode> newNodeEntry = it.next();
        final DOMNode newNode = newNodeEntry.getValue();
        // if newNode is a content element, do not rely on local hash property
        String newHash = newNode.getDataHash();
        if (newHash == null) {
            newHash = newNode.getIdHash();
        }
        // check for deleted nodes ignoring Page nodes
        if (!hashMappedExistingNodes.containsKey(newHash) && !(newNode instanceof Page)) {
            final DOMNode newParent = newNode.getParent();
            changeSet.add(new CreateOperation(hashMappedExistingNodes, getHashOrNull(newParent), getSiblingHashes(newNode), newNode, depthMappedNewNodes.get(newNode)));
        }
    }
    // compare all new nodes with all existing nodes
    for (final Map.Entry<String, DOMNode> newNodeEntry : indexMappedNewNodes.entrySet()) {
        final String newTreeIndex = newNodeEntry.getKey();
        final DOMNode newNode = newNodeEntry.getValue();
        for (final Map.Entry<String, DOMNode> existingNodeEntry : indexMappedExistingNodes.entrySet()) {
            final String existingTreeIndex = existingNodeEntry.getKey();
            final DOMNode existingNode = existingNodeEntry.getValue();
            DOMNode newParent = null;
            int equalityBitmask = 0;
            if (newTreeIndex.equals(existingTreeIndex)) {
                equalityBitmask |= 1;
            }
            if (newNode.getIdHashOrProperty().equals(existingNode.getIdHash())) {
                equalityBitmask |= 2;
            }
            if (newNode.contentEquals(existingNode)) {
                equalityBitmask |= 4;
            }
            switch(equalityBitmask) {
                case // same tree index (1), same node (2), same content (4) => node is completely unmodified
                7:
                    break;
                case // same content (2), same node (4), NOT same tree index => node has moved
                6:
                    newParent = newNode.getParent();
                    changeSet.add(new MoveOperation(hashMappedExistingNodes, getHashOrNull(newParent), getSiblingHashes(newNode), newNode, existingNode));
                    break;
                case // same tree index (1), NOT same node, same content (5) => node was deleted and restored, maybe the identification information was lost
                5:
                    break;
                case // NOT same tree index, NOT same node, same content (4) => different node, content is equal by chance?
                4:
                    break;
                case // same tree index, same node, NOT same content => node was modified but not moved
                3:
                    changeSet.add(new UpdateOperation(hashMappedExistingNodes, existingNode, newNode));
                    break;
                case // NOT same tree index, same node (2), NOT same content => node was moved and changed
                2:
                    newParent = newNode.getParent();
                    changeSet.add(new UpdateOperation(hashMappedExistingNodes, existingNode, newNode));
                    changeSet.add(new MoveOperation(hashMappedExistingNodes, getHashOrNull(newParent), getSiblingHashes(newNode), newNode, existingNode));
                    break;
                case // same tree index (1), NOT same node, NOT same content => ignore
                1:
                    break;
                case // NOT same tree index, NOT same node, NOT same content => ignore
                0:
                    break;
            }
        }
    }
    return changeSet;
}
Also used : InvertibleModificationOperation(org.structr.web.diff.InvertibleModificationOperation) Page(org.structr.web.entity.dom.Page) LinkedList(java.util.LinkedList) LinkedHashMap(java.util.LinkedHashMap) DeleteOperation(org.structr.web.diff.DeleteOperation) CreateOperation(org.structr.web.diff.CreateOperation) MoveOperation(org.structr.web.diff.MoveOperation) UpdateOperation(org.structr.web.diff.UpdateOperation) DOMNode(org.structr.web.entity.dom.DOMNode) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) PropertyMap(org.structr.core.property.PropertyMap)

Aggregations

HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 LinkedList (java.util.LinkedList)1 Map (java.util.Map)1 PropertyMap (org.structr.core.property.PropertyMap)1 CreateOperation (org.structr.web.diff.CreateOperation)1 DeleteOperation (org.structr.web.diff.DeleteOperation)1 InvertibleModificationOperation (org.structr.web.diff.InvertibleModificationOperation)1 MoveOperation (org.structr.web.diff.MoveOperation)1 UpdateOperation (org.structr.web.diff.UpdateOperation)1 DOMNode (org.structr.web.entity.dom.DOMNode)1 Page (org.structr.web.entity.dom.Page)1