![JAR search and dependency download from the Maven repository](/logo.png)
com.nedap.archie.diff.NodeIdLCS Maven / Gradle / Ivy
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 - 2025 Weber Informatics LLC | Privacy Policy