All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.nedap.archie.diff.NodeIdLCS Maven / Gradle / Ivy

Go to download

tools that operate on the archie reference models and archetype object model

The newest version!
package com.nedap.archie.diff;

import com.nedap.archie.aom.utils.AOMUtils;
import com.nedap.archie.aom.utils.CodeRedefinitionStatus;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Calculates the Longest common subsequence along two sets of node ids. Useful for sibling order diffing
 *
 * Or perhaps diffing in general with a few modifications?
 */
public class NodeIdLCS {


    private List lcs;
    //mapping from node id in child to parent. Used when id4 is replaced by id4.1 without cloning
    private Map nodeIdReplacements = new HashMap<>();

    public NodeIdLCS(List parent, List child, int childSpecializationDepth) {
        calculateReplacements(parent, child, childSpecializationDepth);
        lcs = longestCommonSubsequence(parent, child);
    }

    public List longestCommonSubsequence(final List parent, final List child) {

        // Quick return
        if (parent == null || child == null) {
            throw new IllegalArgumentException("Inputs must not be null");
        }
        List longestCommonSubString = new ArrayList<>(Math.max(parent.size(), child.size()));

        int[][] lcsLengthArray = longestCommonSubstringLengthArray(parent, child);
        int i = parent.size() - 1;
        int j = child.size() - 1;
        int k = lcsLengthArray[parent.size()][child.size()] - 1;
        while (k >= 0) {
            if (equals(parent.get(i), child.get(j))) {
                longestCommonSubString.add(parent.get(i));
                i = i - 1;
                j = j - 1;
                k = k - 1;
            } else if (lcsLengthArray[i + 1][j] < lcsLengthArray[i][j + 1]) {
                i = i - 1;
            } else {
                j = j - 1;
            }
        }
        Collections.reverse(longestCommonSubString);
        return longestCommonSubString;
    }

    private void calculateReplacements(List parent, List child, int childSpecializationDepth) {
        for(String nodeId:child) {
            if(AOMUtils.getSpecialisationStatusFromCode(nodeId, childSpecializationDepth) == CodeRedefinitionStatus.REDEFINED) {
                String parentNodeId = AOMUtils.getCodeInNearestParent(nodeId);
                if(!child.contains(parentNodeId)) {
                    //replacement!
                    nodeIdReplacements.put(nodeId, parentNodeId);
                }

            }
        }
    }

    public int[][] longestCommonSubstringLengthArray(final List parent, final List child) {
        int[][] lcsLengthArray = new int[parent.size() + 1][child.size() + 1];
        for (int i=0; i < parent.size(); i++) {
            for (int j=0; j < child.size(); j++) {
                if (i == 0) {
                    lcsLengthArray[i][j] = 0;
                }
                if (j == 0) {
                    lcsLengthArray[i][j] = 0;
                }
                if (equals(parent.get(i), child.get(j))) {
                    lcsLengthArray[i + 1][j + 1] = lcsLengthArray[i][j] + 1;
                } else {
                    lcsLengthArray[i + 1][j + 1] = Math.max(lcsLengthArray[i + 1][j], lcsLengthArray[i][j + 1]);
                }
            }
        }
        return lcsLengthArray;
    }

    public boolean equals(String parent, String child) {
        String replacedChild = nodeIdReplacements.get(child);
        if(replacedChild == null) {
            replacedChild = child;
        }
        //left is always parent, right always child. Might be useful here  for ordering tricks?
        return parent.equals(replacedChild);
    }

    public boolean contains(String childNodeId) {
        String replacedChild = nodeIdReplacements.get(childNodeId);
        if(replacedChild == null) {
            replacedChild = childNodeId;
        }
        return lcs.contains(replacedChild);
    }

    public List getLCS() {
        return lcs;
    }

    public boolean isLast(String nodeId) {
        return equals(lcs.get(lcs.size() - 1), nodeId);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy