Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
gr.uom.java.xmi.diff.UMLJavadocDiff Maven / Gradle / Ivy
package gr.uom.java.xmi.diff;
import java.text.BreakIterator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.tuple.Pair;
import org.jsoup.Jsoup;
import gr.uom.java.xmi.UMLDocElement;
import gr.uom.java.xmi.UMLJavadoc;
import gr.uom.java.xmi.UMLTagElement;
public class UMLJavadocDiff {
private UMLJavadoc javadocBefore;
private UMLJavadoc javadocAfter;
private List> commonTags;
private List> commonDocElements;
private List> commonNestedTags;
private List deletedTags;
private List addedTags;
private List deletedNestedTags;
private List addedNestedTags;
private List deletedDocElements;
private List addedDocElements;
private boolean manyToManyReformat;
public UMLJavadocDiff(UMLJavadoc javadocBefore, UMLJavadoc javadocAfter) {
this.javadocBefore = javadocBefore;
this.javadocAfter = javadocAfter;
this.commonTags = new ArrayList>();
this.commonNestedTags = new ArrayList>();
this.commonDocElements = new ArrayList>();
this.deletedTags = new ArrayList();
this.addedTags = new ArrayList();
this.deletedNestedTags = new ArrayList();
this.addedNestedTags = new ArrayList();
this.deletedDocElements = new ArrayList();
this.addedDocElements = new ArrayList();
List tagsBefore = javadocBefore.getTags();
List tagsAfter = javadocAfter.getTags();
List deletedTags = new ArrayList(tagsBefore);
List addedTags = new ArrayList(tagsAfter);
if(tagsBefore.size() <= tagsAfter.size()) {
for(UMLTagElement tagBefore : tagsBefore) {
if(tagsAfter.contains(tagBefore)) {
int index = tagsAfter.indexOf(tagBefore);
Pair pair = Pair.of(tagBefore, tagsAfter.get(index));
commonTags.add(pair);
processIdenticalTags(tagBefore, tagsAfter.get(index));
matchNestedTags(tagBefore, tagsAfter.get(index));
deletedTags.remove(tagBefore);
addedTags.remove(tagBefore);
}
}
}
else {
for(UMLTagElement tagAfter : tagsAfter) {
if(tagsBefore.contains(tagAfter)) {
int index = tagsBefore.indexOf(tagAfter);
Pair pair = Pair.of(tagsBefore.get(index), tagAfter);
commonTags.add(pair);
processIdenticalTags(tagsBefore.get(index), tagAfter);
matchNestedTags(tagsBefore.get(index), tagAfter);
deletedTags.remove(tagAfter);
addedTags.remove(tagAfter);
}
}
}
List deletedToBeDeleted = new ArrayList();
List addedToBeDeleted = new ArrayList();
//process first param tags with the same parameter name
for(UMLTagElement tagBefore : deletedTags) {
for(UMLTagElement tagAfter : addedTags) {
if(tagBefore.isParam() && tagAfter.isParam()) {
String paramNameBefore = tagBefore.getParamName();
String paramNameAfter = tagAfter.getParamName();
if(paramNameBefore != null && paramNameAfter != null && paramNameBefore.equals(paramNameAfter)) {
boolean match = processModifiedTags(tagBefore, tagAfter);
if(match) {
deletedToBeDeleted.add(tagBefore);
addedToBeDeleted.add(tagAfter);
Pair pair = Pair.of(tagBefore, tagAfter);
commonTags.add(pair);
matchNestedTags(tagBefore, tagAfter);
break;
}
}
}
else if(tagBefore.isReturn() && tagAfter.isReturn()) {
boolean match = processModifiedTags(tagBefore, tagAfter);
if(match) {
deletedToBeDeleted.add(tagBefore);
addedToBeDeleted.add(tagAfter);
Pair pair = Pair.of(tagBefore, tagAfter);
commonTags.add(pair);
matchNestedTags(tagBefore, tagAfter);
break;
}
}
}
}
deletedTags.removeAll(deletedToBeDeleted);
addedTags.removeAll(addedToBeDeleted);
if(deletedTags.size() <= addedTags.size()) {
for(UMLTagElement tagBefore : deletedTags) {
for(UMLTagElement tagAfter : addedTags) {
boolean match = processModifiedTags(tagBefore, tagAfter);
if(match) {
deletedToBeDeleted.add(tagBefore);
addedToBeDeleted.add(tagAfter);
Pair pair = Pair.of(tagBefore, tagAfter);
commonTags.add(pair);
matchNestedTags(tagBefore, tagAfter);
break;
}
}
}
}
else {
for(UMLTagElement tagAfter : addedTags) {
for(UMLTagElement tagBefore : deletedTags) {
boolean match = processModifiedTags(tagBefore, tagAfter);
if(match) {
deletedToBeDeleted.add(tagBefore);
addedToBeDeleted.add(tagAfter);
Pair pair = Pair.of(tagBefore, tagAfter);
commonTags.add(pair);
matchNestedTags(tagBefore, tagAfter);
break;
}
}
}
}
deletedTags.removeAll(deletedToBeDeleted);
addedTags.removeAll(addedToBeDeleted);
this.deletedTags.addAll(deletedTags);
this.addedTags.addAll(addedTags);
}
private void matchNestedTags(UMLTagElement tagBefore, UMLTagElement tagAfter) {
List nestedTagsBefore = tagBefore.getNestedTags();
List nestedTagsAfter = tagAfter.getNestedTags();
List deletedNestedTags = new ArrayList(nestedTagsBefore);
List addedNestedTags = new ArrayList(nestedTagsAfter);
if(nestedTagsBefore.size() <= nestedTagsAfter.size()) {
for(UMLTagElement nestedTagBefore : nestedTagsBefore) {
if(nestedTagsAfter.contains(nestedTagBefore)) {
List matchingIndices = findAllMatchingIndices(nestedTagsAfter, nestedTagBefore);
for(Integer index : matchingIndices) {
if(!alreadyMatchedNestedTagElement(nestedTagBefore, nestedTagsAfter.get(index))) {
Pair pair = Pair.of(nestedTagBefore, nestedTagsAfter.get(index));
commonNestedTags.add(pair);
processIdenticalTags(nestedTagBefore, nestedTagsAfter.get(index));
deletedNestedTags.remove(nestedTagBefore);
addedNestedTags.remove(nestedTagBefore);
break;
}
}
}
}
}
else {
for(UMLTagElement nestedTagAfter : nestedTagsAfter) {
if(nestedTagsBefore.contains(nestedTagAfter)) {
List matchingIndices = findAllMatchingIndices(nestedTagsBefore, nestedTagAfter);
for(Integer index : matchingIndices) {
if(!alreadyMatchedNestedTagElement(nestedTagsBefore.get(index), nestedTagAfter)) {
Pair pair = Pair.of(nestedTagsBefore.get(index), nestedTagAfter);
commonNestedTags.add(pair);
processIdenticalTags(nestedTagsBefore.get(index), nestedTagAfter);
deletedNestedTags.remove(nestedTagAfter);
addedNestedTags.remove(nestedTagAfter);
break;
}
}
}
}
}
if(deletedNestedTags.size() == addedNestedTags.size()) {
for(int i=0; i 0) {
UMLDocElement fragment1 = deletedNestedTag.getFragments().get(0);
UMLDocElement fragment2 = addedNestedTag.getFragments().get(0);
if(fragment1.getText().startsWith("#") && fragment2.getText().startsWith("#")) {
String text1 = fragment1.getText();
if(text1.contains("(")) {
text1 = text1.substring(0, text1.indexOf("("));
}
String text2 = fragment2.getText();
if(text2.contains("(")) {
text2 = text2.substring(0, text2.indexOf("("));
}
if(text1.contains(text2) || text2.contains(text1)) {
Pair pair = Pair.of(deletedNestedTag, addedNestedTag);
commonNestedTags.add(pair);
}
}
}
}
}
this.deletedNestedTags.addAll(deletedNestedTags);
this.addedNestedTags.addAll(addedNestedTags);
}
private void processIdenticalTags(UMLTagElement tagBefore, UMLTagElement tagAfter) {
List fragmentsBefore = tagBefore.getFragments();
List fragmentsAfter = tagAfter.getFragments();
for(int i=0; i pair = Pair.of(docElementBefore, docElementAfter);
commonDocElements.add(pair);
}
}
private List findAllMatchingIndices(List tags, UMLTagElement docElement) {
List matchingIndices = new ArrayList<>();
for(int i=0; i findAllMatchingIndices(List fragments, UMLDocElement docElement) {
List matchingIndices = new ArrayList<>();
for(int i=0; i fragmentsBefore = tagBefore.getFragments();
List fragmentsAfter = tagAfter.getFragments();
List deletedDocElements = new ArrayList(fragmentsBefore);
List addedDocElements = new ArrayList(fragmentsAfter);
if(fragmentsBefore.size() <= fragmentsAfter.size()) {
int updates = 0;
for(UMLDocElement docElement : fragmentsBefore) {
if(fragmentsAfter.contains(docElement)) {
List matchingIndices = findAllMatchingIndices(fragmentsAfter, docElement);
boolean matchFound = false;
List beforeMatchingIndices = findAllMatchingIndices(fragmentsBefore, docElement);
if(docElement.isHTMLTag() && beforeMatchingIndices.size() < matchingIndices.size()) {
for(Integer index : matchingIndices) {
if(index > 0 && index < fragmentsAfter.size()-1) {
for(Integer beforeIndex : beforeMatchingIndices) {
if(beforeIndex > 0 && beforeIndex < fragmentsBefore.size()-1) {
UMLDocElement before1 = fragmentsBefore.get(beforeIndex-1);
UMLDocElement after1 = fragmentsBefore.get(beforeIndex+1);
UMLDocElement before2 = fragmentsAfter.get(index-1);
UMLDocElement after2 = fragmentsAfter.get(index+1);
if(before1.equals(before2) && after1.equals(after2) && !alreadyMatchedDocElement(docElement, fragmentsAfter.get(index))) {
matchFound = true;
Pair pair = Pair.of(fragmentsBefore.get(beforeIndex), fragmentsAfter.get(index));
commonDocElements.add(pair);
List indices1 = findAllMatchingIndices(deletedDocElements, docElement);
List indices2 = findAllMatchingIndices(addedDocElements, docElement);
int beforeIndexToRemove = beforeMatchingIndices.indexOf(beforeIndex);
if(beforeIndexToRemove >= indices1.size()) {
beforeIndexToRemove = beforeIndexToRemove - updates;
}
deletedDocElements.remove((int)indices1.get(beforeIndexToRemove));
int afterIndexToRemove = matchingIndices.indexOf(index);
if(afterIndexToRemove >= indices2.size()) {
afterIndexToRemove = afterIndexToRemove - updates;
}
addedDocElements.remove((int)indices2.get(afterIndexToRemove));
updates++;
break;
}
}
}
if(matchFound) {
break;
}
}
}
}
if(!matchFound) {
for(Integer index : matchingIndices) {
if(!alreadyMatchedDocElement(docElement, fragmentsAfter.get(index))) {
Pair pair = Pair.of(docElement, fragmentsAfter.get(index));
commonDocElements.add(pair);
deletedDocElements.remove(docElement);
addedDocElements.remove(docElement);
break;
}
}
}
}
}
}
else {
int updates = 0;
for(UMLDocElement docElement : fragmentsAfter) {
if(fragmentsBefore.contains(docElement)) {
List matchingIndices = findAllMatchingIndices(fragmentsBefore, docElement);
boolean matchFound = false;
List afterMatchingIndices = findAllMatchingIndices(fragmentsAfter, docElement);
if(docElement.isHTMLTag() && afterMatchingIndices.size() < matchingIndices.size()) {
for(Integer index : matchingIndices) {
if(index > 0 && index < fragmentsBefore.size()-1) {
for(Integer afterIndex : afterMatchingIndices) {
if(afterIndex > 0 && afterIndex < fragmentsAfter.size()-1) {
UMLDocElement before1 = fragmentsBefore.get(index-1);
UMLDocElement after1 = fragmentsBefore.get(index+1);
UMLDocElement before2 = fragmentsAfter.get(afterIndex-1);
UMLDocElement after2 = fragmentsAfter.get(afterIndex+1);
if(before1.equals(before2) && after1.equals(after2) && !alreadyMatchedDocElement(fragmentsBefore.get(index), docElement)) {
matchFound = true;
Pair pair = Pair.of(fragmentsBefore.get(index), fragmentsAfter.get(afterIndex));
commonDocElements.add(pair);
List indices1 = findAllMatchingIndices(deletedDocElements, docElement);
List indices2 = findAllMatchingIndices(addedDocElements, docElement);
int beforeIndexToRemove = matchingIndices.indexOf(index);
if(beforeIndexToRemove >= indices1.size()) {
beforeIndexToRemove = beforeIndexToRemove - updates;
}
deletedDocElements.remove((int)indices1.get(beforeIndexToRemove));
int afterIndexToRemove = afterMatchingIndices.indexOf(afterIndex);
if(afterIndexToRemove >= indices2.size()) {
afterIndexToRemove = afterIndexToRemove - updates;
}
addedDocElements.remove((int)indices2.get(afterIndexToRemove));
updates++;
break;
}
}
}
if(matchFound) {
break;
}
}
}
}
if(!matchFound) {
for(Integer index : matchingIndices) {
if(!alreadyMatchedDocElement(fragmentsBefore.get(index), docElement)) {
Pair pair = Pair.of(fragmentsBefore.get(index), docElement);
commonDocElements.add(pair);
deletedDocElements.remove(docElement);
addedDocElements.remove(docElement);
break;
}
}
}
}
}
}
if(tagBefore.isParam() && tagAfter.isParam()) {
String paramNameBefore = tagBefore.getParamName();
String paramNameAfter = tagAfter.getParamName();
if(paramNameBefore != null && paramNameAfter != null && !paramNameBefore.equals(paramNameAfter) &&
fragmentsBefore.size() > 1 && fragmentsAfter.size() > 1) {
Pair pair = Pair.of(fragmentsBefore.get(1), fragmentsAfter.get(1));
if(commonDocElements.contains(pair) && fragmentsBefore.get(0).getText().equals(paramNameBefore) && fragmentsAfter.get(0).getText().equals(paramNameAfter)) {
Pair variablePair = Pair.of(fragmentsBefore.get(0), fragmentsAfter.get(0));
commonDocElements.add(variablePair);
deletedDocElements.remove(fragmentsBefore.get(0));
addedDocElements.remove(fragmentsAfter.get(0));
}
}
}
if(deletedDocElements.size() == 0 || addedDocElements.size() == 0) {
this.deletedDocElements.addAll(deletedDocElements);
this.addedDocElements.addAll(addedDocElements);
return commonDocElements.size() > 0 || fragmentsBefore.isEmpty() || fragmentsAfter.isEmpty();
}
//match doc elements differing only in opening/closing quotes
if(deletedDocElements.size() <= addedDocElements.size()) {
for(UMLDocElement deletedDocElement : new ArrayList<>(deletedDocElements)) {
String trimmed1 = deletedDocElement.getText().replaceAll("^\"|\"$", "");
for(UMLDocElement addedDocElement : new ArrayList<>(addedDocElements)) {
String trimmed2 = addedDocElement.getText().replaceAll("^\"|\"$", "");
if(trimmed1.equals(trimmed2) || trimmed1.equals(trimmed2 + ".") || trimmed2.equals(trimmed1 + ".")) {
Pair pair = Pair.of(deletedDocElement, addedDocElement);
commonDocElements.add(pair);
deletedDocElements.remove(deletedDocElement);
addedDocElements.remove(addedDocElement);
}
}
}
}
else {
for(UMLDocElement addedDocElement : new ArrayList<>(addedDocElements)) {
String trimmed2 = addedDocElement.getText().replaceAll("^\"|\"$", "");
for(UMLDocElement deletedDocElement : new ArrayList<>(deletedDocElements)) {
String trimmed1 = deletedDocElement.getText().replaceAll("^\"|\"$", "");
if(trimmed1.equals(trimmed2) || trimmed1.equals(trimmed2 + ".") || trimmed2.equals(trimmed1 + ".")) {
Pair pair = Pair.of(deletedDocElement, addedDocElement);
commonDocElements.add(pair);
deletedDocElements.remove(deletedDocElement);
addedDocElements.remove(addedDocElement);
}
}
}
}
List deletedToBeDeleted = new ArrayList();
List addedToBeDeleted = new ArrayList();
if(deletedDocElements.size() == addedDocElements.size()) {
for(int i=0; i pair = Pair.of(deletedDocElement, addedDocElement);
commonDocElements.add(pair);
deletedToBeDeleted.add(deletedDocElement);
addedToBeDeleted.add(addedDocElement);
}
}
deletedDocElements.removeAll(deletedToBeDeleted);
addedDocElements.removeAll(addedToBeDeleted);
}
//check if all deleted docElements match all added docElements
StringBuilder deletedSB = new StringBuilder();
List deletedTokenSequence = new ArrayList();
Map> deletedTokenSequenceMap = new LinkedHashMap<>();
for(UMLDocElement deletedDocElement : deletedDocElements) {
String text = deletedDocElement.getText();
deletedSB.append(text);
List splitToWords = splitToWords(text);
deletedTokenSequence.addAll(splitToWords);
deletedTokenSequenceMap.put(deletedDocElement, splitToWords);
}
StringBuilder addedSB = new StringBuilder();
List addedTokenSequence = new ArrayList();
Map> addedTokenSequenceMap = new LinkedHashMap<>();
for(UMLDocElement addedDocElement : addedDocElements) {
String text = addedDocElement.getText();
addedSB.append(text);
List splitToWords = splitToWords(text);
addedTokenSequence.addAll(splitToWords);
addedTokenSequenceMap.put(addedDocElement, splitToWords);
}
String deletedWithoutTags = Jsoup.parse(deletedSB.toString()).text();
String addedWithoutTags = Jsoup.parse(addedSB.toString()).text();
if(deletedSB.toString().replaceAll("\\s", "").equals(addedSB.toString().replaceAll("\\s", ""))) {
//make all pair combinations
for(UMLDocElement deletedDocElement : deletedDocElements) {
for(UMLDocElement addedDocElement : addedDocElements) {
Pair pair = Pair.of(deletedDocElement, addedDocElement);
commonDocElements.add(pair);
}
}
if(deletedDocElements.size() >= 1 && addedDocElements.size() >= 1) {
manyToManyReformat = true;
}
return true;
}
else if(deletedWithoutTags.replaceAll("\\s", "").equals(addedWithoutTags.replaceAll("\\s", ""))) {
//make all pair combinations
for(UMLDocElement deletedDocElement : deletedDocElements) {
for(UMLDocElement addedDocElement : addedDocElements) {
Pair pair = Pair.of(deletedDocElement, addedDocElement);
commonDocElements.add(pair);
}
}
if(deletedDocElements.size() >= 1 && addedDocElements.size() >= 1) {
manyToManyReformat = true;
}
return true;
}
else if(normalizedEditDistance(deletedWithoutTags.replaceAll("\\s", ""), addedWithoutTags.replaceAll("\\s", "")) < 0.1) {
//make all pair combinations
for(UMLDocElement deletedDocElement : deletedDocElements) {
for(UMLDocElement addedDocElement : addedDocElements) {
Pair pair = Pair.of(deletedDocElement, addedDocElement);
commonDocElements.add(pair);
}
}
if(deletedDocElements.size() >= 1 && addedDocElements.size() >= 1) {
manyToManyReformat = true;
}
return true;
}
else {
//match doc elements that one contains a subsequence of the other
if(deletedTokenSequence.size() <= addedTokenSequence.size()) {
List longestSubSequence = null;
for(int i=0; i subList = deletedTokenSequence.subList(i,j+1);
if(subList.size() > 2) {
int indexOfSubList = Collections.indexOfSubList(addedTokenSequence, subList);
if(indexOfSubList != -1) {
if(longestSubSequence == null) {
longestSubSequence = subList;
}
else if(subList.containsAll(longestSubSequence) && subList.size() > longestSubSequence.size()) {
longestSubSequence = subList;
}
}
}
}
if(longestSubSequence != null && longestSubSequence.equals(deletedTokenSequence)) {
break;
}
}
if(longestSubSequence != null) {
//make all pair combinations
for(UMLDocElement deletedDocElement : deletedDocElements) {
if(containsAnySubSequence(deletedTokenSequenceMap.get(deletedDocElement), longestSubSequence)) {
for(UMLDocElement addedDocElement : addedDocElements) {
if(containsAnySubSequence(addedTokenSequenceMap.get(addedDocElement), longestSubSequence)) {
if(!alreadyMatchedDocElement(deletedDocElement, addedDocElement)) {
Pair pair = Pair.of(deletedDocElement, addedDocElement);
commonDocElements.add(pair);
deletedToBeDeleted.add(deletedDocElement);
addedToBeDeleted.add(addedDocElement);
}
}
}
}
}
if(deletedDocElements.size() >= 1 && addedDocElements.size() >= 1) {
manyToManyReformat = true;
}
}
}
else {
List longestSubSequence = null;
for(int i=0; i subList = addedTokenSequence.subList(i,j+1);
if(subList.size() > 2) {
int indexOfSubList = Collections.indexOfSubList(deletedTokenSequence, subList);
if(indexOfSubList != -1) {
if(longestSubSequence == null) {
longestSubSequence = subList;
}
else if(subList.containsAll(longestSubSequence) && subList.size() > longestSubSequence.size()) {
longestSubSequence = subList;
}
}
}
}
if(longestSubSequence != null && longestSubSequence.equals(addedTokenSequence)) {
break;
}
}
if(longestSubSequence != null) {
//make all pair combinations
for(UMLDocElement deletedDocElement : deletedDocElements) {
if(containsAnySubSequence(deletedTokenSequenceMap.get(deletedDocElement), longestSubSequence)) {
for(UMLDocElement addedDocElement : addedDocElements) {
if(containsAnySubSequence(addedTokenSequenceMap.get(addedDocElement), longestSubSequence)) {
if(!alreadyMatchedDocElement(deletedDocElement, addedDocElement) ||
(longestSubSequence.containsAll(deletedTokenSequenceMap.get(deletedDocElement)) &&
deletedTokenSequenceMap.get(deletedDocElement).size() > 1)) {
Pair pair = Pair.of(deletedDocElement, addedDocElement);
commonDocElements.add(pair);
deletedToBeDeleted.add(deletedDocElement);
addedToBeDeleted.add(addedDocElement);
}
}
}
}
}
if(deletedDocElements.size() >= 1 && addedDocElements.size() >= 1) {
manyToManyReformat = true;
}
}
}
}
deletedDocElements.removeAll(deletedToBeDeleted);
addedDocElements.removeAll(addedToBeDeleted);
if(deletedDocElements.size() > addedDocElements.size()) {
for(UMLDocElement addedDocElement : addedDocElements) {
String text = addedDocElement.getText();
for(int i=0; i matches = findConcatenatedMatch(deletedDocElements, text, i);
if(matches.size() > 0) {
for(UMLDocElement match : matches) {
Pair pair = Pair.of(match, addedDocElement);
commonDocElements.add(pair);
deletedToBeDeleted.add(match);
}
addedToBeDeleted.add(addedDocElement);
break;
}
}
}
}
else {
for(UMLDocElement deletedDocElement : deletedDocElements) {
String text = deletedDocElement.getText();
for(int i=0; i matches = findConcatenatedMatch(addedDocElements, text, i);
if(matches.size() > 0) {
for(UMLDocElement match : matches) {
Pair pair = Pair.of(deletedDocElement, match);
commonDocElements.add(pair);
addedToBeDeleted.add(match);
}
deletedToBeDeleted.add(deletedDocElement);
break;
}
}
}
}
deletedDocElements.removeAll(deletedToBeDeleted);
addedDocElements.removeAll(addedToBeDeleted);
//match doc elements that one contains the other
if(deletedDocElements.size() <= addedDocElements.size()) {
for(UMLDocElement deletedDocElement : new ArrayList<>(deletedDocElements)) {
if(deletedDocElement.getText().length() > 2) {
for(UMLDocElement addedDocElement : new ArrayList<>(addedDocElements)) {
if(addedDocElement.getText().length() > 2) {
if(deletedDocElement.getText().contains(addedDocElement.getText()) || addedDocElement.getText().contains(deletedDocElement.getText())) {
Pair pair = Pair.of(deletedDocElement, addedDocElement);
commonDocElements.add(pair);
deletedDocElements.remove(deletedDocElement);
addedDocElements.remove(addedDocElement);
}
}
}
}
}
}
else {
for(UMLDocElement addedDocElement : new ArrayList<>(addedDocElements)) {
if(addedDocElement.getText().length() > 2) {
for(UMLDocElement deletedDocElement : new ArrayList<>(deletedDocElements)) {
if(deletedDocElement.getText().length() > 2) {
if(deletedDocElement.getText().contains(addedDocElement.getText()) || addedDocElement.getText().contains(deletedDocElement.getText())) {
Pair pair = Pair.of(deletedDocElement, addedDocElement);
commonDocElements.add(pair);
deletedDocElements.remove(deletedDocElement);
addedDocElements.remove(addedDocElement);
}
}
}
}
}
}
this.deletedDocElements.addAll(deletedDocElements);
this.addedDocElements.addAll(addedDocElements);
if(commonDocElements.size() > commonDocElementsBefore) {
return true;
}
return false;
}
private double normalizedEditDistance(String s1, String s2) {
int distance = StringDistance.editDistance(s1, s2);
double normalized = (double)distance/(double)Math.max(s1.length(), s2.length());
return normalized;
}
private boolean alreadyMatchedNestedTagElement(UMLTagElement deletedTagElement, UMLTagElement addedTagElement) {
for(Pair pair : commonNestedTags) {
if(pair.getLeft() == deletedTagElement) {
return true;
}
if(pair.getRight() == addedTagElement) {
return true;
}
}
return false;
}
private boolean alreadyMatchedDocElement(UMLDocElement deletedDocElement, UMLDocElement addedDocElement) {
for(Pair pair : commonDocElements) {
if(pair.getLeft() == deletedDocElement) {
if(pair.getLeft().getText().contains(pair.getRight().getText()) || pair.getRight().getText().contains(pair.getLeft().getText()))
return true;
}
if(pair.getRight() == addedDocElement) {
if(pair.getLeft().getText().contains(pair.getRight().getText()) || pair.getRight().getText().contains(pair.getLeft().getText()))
return true;
}
}
return false;
}
private List findConcatenatedMatch(List docElements, String text, int startIndex) {
StringBuilder concatText = new StringBuilder();
for(int i=startIndex; i(docElements.subList(startIndex, i+1));
}
}
return Collections.emptyList();
}
private boolean containsAnySubSequence(List list, List longestSubSequence) {
if(list.size() > 1 && Collections.indexOfSubList(longestSubSequence, list) != -1)
return true;
for(int i=longestSubSequence.size(); i>1; i--) {
List subList = longestSubSequence.subList(0,i);
int index = Collections.indexOfSubList(list, subList);
if(index != -1 && (subList.size() > 1 || (subList.size() == 1 && Character.isUpperCase(subList.get(0).charAt(0))))) {
return true;
}
}
for(int i=0; i subList = longestSubSequence.subList(i,longestSubSequence.size());
int index = Collections.indexOfSubList(list, subList);
if(index != -1 && (subList.size() > 1 || (subList.size() == 1 && Character.isUpperCase(subList.get(0).charAt(0))))) {
return true;
}
}
return false;
}
private List splitToWords(String sentence) {
ArrayList words = new ArrayList();
BreakIterator boundary = BreakIterator.getWordInstance();
boundary.setText(sentence);
int start = boundary.first();
for (int end = boundary.next();
end != BreakIterator.DONE;
start = end, end = boundary.next()) {
String word = sentence.substring(start,end);
if(!word.isBlank())
words.add(word);
}
return words;
}
public UMLJavadoc getJavadocBefore() {
return javadocBefore;
}
public UMLJavadoc getJavadocAfter() {
return javadocAfter;
}
public List> getCommonTags() {
return commonTags;
}
public List> getCommonDocElements() {
return commonDocElements;
}
public List getDeletedTags() {
return deletedTags;
}
public List getAddedTags() {
return addedTags;
}
public List getDeletedDocElements() {
return deletedDocElements;
}
public List getAddedDocElements() {
return addedDocElements;
}
public List> getCommonNestedTags() {
return commonNestedTags;
}
public List getDeletedNestedTags() {
return deletedNestedTags;
}
public List getAddedNestedTags() {
return addedNestedTags;
}
public boolean isManyToManyReformat() {
return manyToManyReformat;
}
}