public FDifference compareMethods( FDifference diff, MethodDescription leftMethod, MethodDescription rightMethod) { FDifference signDiff = basis.compareValues( "signature", leftMethod.getSignature().toString(), rightMethod.getSignature().toString(), leftMethod); FDifference descrDiff = basis.compareDescriptions( leftMethod.getName(), leftMethod.getSignature().getDescription(), rightMethod.getSignature().getDescription(), leftMethod); if (signDiff != null || descrDiff != null) { if (diff == null && signDiff != null) { diff = new FDifference(FDKind.ChangedElement, FDRating.Conflict); } else if (diff == null) { diff = new FDifference(FDKind.ChangedElement, FDRating.Info); } diff.addDifference(signDiff); diff.addDifference(descrDiff); } return diff; }
protected FDifference compareStepIds( String context, INamedElement left, INamedElement right, FDObject source) { FDifference diff = null; if (left != null && right != null) { if (left.getName() != null & right.getName() != null) { if (left.getName().startsWith("id") && right.getName().startsWith("id")) { logger.debug( "ignoring diff between generated IDs for steps {} and {}", left.getName(), right.getName()); } else if (!left.getName().equals(right.getName())) { logger.info("different step IDs: left={} <> right={}", left, right); diff = new FDifference(FDKind.ChangedElement, FDRating.Warning); diff.setSource(source); diff.setDescription( "The " + context + " has changed from '" + left.getName() + "' in version " + this.getLeftVersion() + " to '" + right.getName() + "' in version " + this.getRightVersion()); logger.debug("compare step IDs diff:\n{}", diff); } } } else { logger.warn("comparing named elements with NULL arguments. left={}, right={}", left, right); } return diff; }
public FDifference compareTypeDescriptions( CodingUnit leftCodingUnit, CodingUnit rightCodingUnit, FDObject source) { FDifference diff = null; TypeDescription leftType = proxy.getTypeDescription(leftCodingUnit.getTypeAPIPath()); TypeDescription rightType = proxy.getTypeDescription(rightCodingUnit.getTypeAPIPath()); if (leftType != null && rightType != null) { FDifference nameDiff = basis.compareNamedElements("type descriptions", leftType, rightType, source); FDifference descDiff = basis.compareDescriptions(leftType, rightType, source); FDifference fqtnDiff = basis.compareValues("FQTN", leftType.getFqtn(), rightType.getFqtn(), source); FDifference methDiff = this.compareMethodDescriptions(leftType, rightType, source); FDifference packDiff = this.comparePackageDescriptions(leftType, rightType, source); if (nameDiff != null || descDiff != null || fqtnDiff != null || methDiff != null || packDiff != null) { diff = new FDifference(FDKind.ChangedElement, FDRating.Warning); diff.setSource(leftCodingUnit); diff.setDescription( "The type description of '" + leftCodingUnit.getName() + "' has changed in version " + this.getRightVersion()); diff.addDifference(nameDiff); diff.addDifference(descDiff); diff.addDifference(fqtnDiff); diff.addDifference(methDiff); diff.addDifference(packDiff); } } return diff; }
private FDifference compareMethodDescriptions( TypeDescription leftType, TypeDescription rightType, FDObject source) { FDifference diff = null; if (leftType.getMethods() != null) { if (rightType.getMethods() != null) { FDifference subDiff = compareMethodLists(leftType.getMethods(), rightType.getMethods(), leftType); if (subDiff != null) { if (diff == null) { diff = new FDifference(FDKind.ChangedElement, subDiff.getRating()); } diff.addDifference(subDiff); } } else { // Deleted methods FDifference delDiff = new FDifference(FDKind.DeletedElement, FDRating.Conflict); delDiff.setSource(leftType); delDiff.setDescription( leftType.getMethods().size() + " were removed from type '" + leftType.getFqtn() + "' in version " + this.getRightVersion()); if (diff == null) { diff = new FDifference(FDKind.ChangedElement, FDRating.Conflict); } diff.addDifference(delDiff); } } else if (rightType.getMethods() != null) { // New methods FDifference addDiff = new FDifference(FDKind.CreatedElement, FDRating.Warning); addDiff.setSource(rightType); addDiff.setDescription( "The type '" + rightType.getFqtn() + "' has " + rightType.getMethods().size() + " new methods in version " + this.getRightVersion()); if (diff == null) { diff = new FDifference(FDKind.ChangedElement, FDRating.Conflict); } diff.addDifference(addDiff); } if (diff != null) { diff.setSource(leftType); diff.setDescription( "The type description of '" + leftType.getFqtn() + "' has changed in version " + this.getRightVersion()); } return diff; }
private FDifference comparePackageDescriptions( TypeDescription leftType, TypeDescription rightType, FDObject source) { FDifference nameDiff = null; FDifference descDiff = null; FDifference deleDiff = null; FDifference creaDiff = null; if (leftType.getPackage() != null) { if (rightType.getPackage() != null) { nameDiff = basis.compareNamedElements( "package description", leftType.getPackage(), rightType.getPackage(), leftType.getPackage()); descDiff = basis.compareDescriptions( leftType.getPackage(), rightType.getPackage(), leftType.getPackage()); } else { // Deleted package deleDiff = new FDifference(FDKind.DeletedElement, FDRating.Conflict); deleDiff.setSource(leftType.getPackage()); deleDiff.setDescription( "The package '" + leftType.getPackage().getName() + "' of type '" + leftType.getFqtn() + "' was removed in version " + this.getRightVersion()); } } else if (rightType.getPackage() != null) { // Created package creaDiff = new FDifference(FDKind.CreatedElement, FDRating.Conflict); creaDiff.setSource(rightType.getPackage()); creaDiff.setDescription( "The package '" + rightType.getPackage().getName() + "' was added to the type '" + leftType.getFqtn() + "' in version " + this.getRightVersion()); } FDifference diff = null; if (nameDiff != null || descDiff != null || deleDiff != null || creaDiff != null) { diff = new FDifference(FDKind.ChangedElement, FDRating.Conflict); diff.setSource(leftType.getPackage()); diff.setDescription( "The package description has changed in version " + this.getRightVersion()); diff.addDifference(nameDiff); diff.addDifference(descDiff); diff.addDifference(deleDiff); diff.addDifference(creaDiff); } return diff; }
private FDifference compareMethodLists( List<MethodDescription> leftMethods, List<MethodDescription> rightMethods, FDObject source) { FDifference diff = null; for (MethodDescription leftMethod : leftMethods) { MethodDescription rightMethod = (MethodDescription) basis.getFromList(rightMethods, leftMethod); if (rightMethod != null) { diff = compareMethods(diff, leftMethod, rightMethod); } else { // Deleted method FDifference delDiff = new FDifference(FDKind.DeletedElement, FDRating.Conflict); delDiff.setSource(leftMethod); delDiff.setDescription( "The method with signature '" + leftMethod.getSignature().toString() + "' was removed in version " + this.getRightVersion()); if (diff == null) { diff = new FDifference(FDKind.ChangedElement, FDRating.Conflict); } diff.addDifference(delDiff); } } for (MethodDescription rightMethod : rightMethods) { MethodDescription leftMethod = (MethodDescription) basis.getFromList(leftMethods, rightMethod); if (leftMethod == null) { // New method FDifference addDiff = new FDifference(FDKind.CreatedElement, FDRating.Warning); addDiff.setSource(rightMethod); addDiff.setDescription( "The method with signature '" + rightMethod.getSignature().toString() + "' was added in version " + this.getRightVersion()); if (diff == null) { diff = new FDifference(FDKind.ChangedElement, FDRating.Conflict); } diff.addDifference(addDiff); } } if (diff != null) { diff.setSource(source); diff.setDescription("Method signatures have changed in version " + this.getRightVersion()); } return diff; }
public FDifference compareProcesses(Process leftProcess, Process rightProcess) { if (logger.isDebugEnabled()) { logger.debug( "compareProcesses() " + leftProcess.getName() + " with " + rightProcess.getName()); } FDifference processDiff = null; if (leftProcess != null && rightProcess != null) { if (leftProcess.getSteps() != null && rightProcess.getSteps() != null) { // Find start step on the left StartStep leftStartStep = null; for (Step step : leftProcess.getSteps()) { if (step instanceof StartStep) { leftStartStep = (StartStep) step; break; } } // Find start step on the right StartStep rightStartStep = null; for (Step step : rightProcess.getSteps()) { if (step instanceof StartStep) { rightStartStep = (StartStep) step; break; } } if (leftStartStep != null && rightStartStep != null) { FDifference nameDiff = this.compareStepIds("start step name", leftStartStep, rightStartStep, leftProcess); processDiff = new FDifference(FDKind.ChangedElement, FDRating.Warning); processDiff.addDifference(nameDiff); processDiff.setDescription( "The process '" + leftProcess.getName() + "' describing the behavior has changed in version " + this.getRightVersion()); // start a simple bi-simulation this.bisimulate(leftStartStep.getNextStep(), rightStartStep.getNextStep(), processDiff); if (processDiff.getSubDiffs().isEmpty()) { // There were no underlying diffs found so this one is obsolete processDiff = null; } } else if (leftStartStep != null) { // right start step not found processDiff = new FDifference(FDKind.DeletedElement, FDRating.Warning); processDiff.setDescription( "The process's start step was deleted in version " + this.getRightVersion()); } else if (rightStartStep != null) { // left start step not found processDiff = new FDifference(FDKind.CreatedElement, FDRating.Warning); processDiff.setDescription( "The process's start step was added in version " + this.getRightVersion()); } } else { processDiff = new FDifference(FDKind.DeletedElement, FDRating.Conflict); processDiff.setSource(leftProcess); processDiff.setDescription("Either the left or the right process has no steps in it."); } } else { logger.error("Could not read process files - no compare possible!"); } if (processDiff != null) { processDiff.setSource(leftProcess); } return processDiff; }
private void bisimulate(Step leftStep, Step rightStep, FDifference parentDiff) { if (logger.isDebugEnabled()) { logger.debug("bisimulate() " + leftStep.getName() + " <-> " + rightStep.getName()); } FDifference stepDiff = null; Step nextLeftStep = null; Step nextRightStep = null; if (leftStep != null && rightStep != null) { // Handle end steps if (leftStep instanceof EndStep) { if (!(rightStep instanceof EndStep)) { // left process ends but right process proceeds stepDiff = new FDifference(FDKind.CreatedElement, FDRating.Conflict); stepDiff.setSource(leftStep); stepDiff.setDescription( "The left process ends with " + leftStep.getPrevStep().getType() + " '" + leftStep.getPrevStep().getName() + "' but there are unmatched process steps in the right process left - starting from " + rightStep.getType() + " '" + rightStep.getName() + "'."); } } else if (rightStep instanceof EndStep) { // the right process ends but the left process proceeds stepDiff = new FDifference(FDKind.DeletedElement, FDRating.Conflict); stepDiff.setSource(leftStep); stepDiff.setDescription( "The right process ends with " + rightStep.getPrevStep().getType() + " '" + rightStep.getPrevStep().getName() + "' but there are unmatched process steps in the left process left - starting from " + leftStep.getType() + " '" + leftStep.getName() + "'."); } else if (match(leftStep, rightStep)) { // matching steps if (leftStep instanceof SubProcess) { // the right step is implicitly of type SubProcess because we had matching steps SubProcess leftSubProcess = (SubProcess) leftStep; SubProcess rightSubProcess = (SubProcess) rightStep; stepDiff = this.compareProcesses( leftSubProcess.getSubProcess(), rightSubProcess.getSubProcess()); } else if (leftStep instanceof HotSpotGroupCall) { HotSpotGroupCall leftHsgc = (HotSpotGroupCall) leftStep; HotSpotGroupCall rightHsgc = (HotSpotGroupCall) rightStep; stepDiff = basis.compareSets( "hot spot group calls", leftHsgc.getHotSpotGroups(), rightHsgc.getHotSpotGroups(), leftHsgc); if (stepDiff != null) { stepDiff.setDescription( "The hot spot group calls of step '" + leftHsgc.getName() + "' were changed in version " + this.getRightVersion()); } } // We had matching steps - go one step further on both sides nextLeftStep = leftStep.getNextStep(); nextRightStep = rightStep.getNextStep(); } else { // No match - see if there was something added or deleted on the right if (findMatch(leftStep, rightStep.getNextStep())) { if (logger.isDebugEnabled()) { logger.debug( "bisimulate() left step '" + leftStep.getName() + "' found later on the right. So the right step " + rightStep.getName() + " was added."); } // There are new elements on the right side until the left step comes stepDiff = new FDifference(FDKind.CreatedElement, FDRating.Conflict); stepDiff.setSource(rightStep); stepDiff.setDescription( "The " + rightStep.getType() + " '" + rightStep.getName() + "' was added in version " + this.getRightVersion()); // Go one step further on right nextLeftStep = leftStep; nextRightStep = rightStep.getNextStep(); } else { if (logger.isDebugEnabled()) { logger.debug( "bisimulate() left step '" + leftStep.getName() + "' not found on right. So this step was removed."); } // The left step was removed because there is no match on the right side stepDiff = new FDifference(FDKind.DeletedElement, FDRating.Conflict); stepDiff.setSource(leftStep); stepDiff.setDescription( "The " + leftStep.getType() + " '" + leftStep.getName() + "' was removed in version " + this.getRightVersion()); // Go one step further on left nextLeftStep = leftStep.getNextStep(); nextRightStep = rightStep; } } } else if (leftStep != null) { // No right step stepDiff = new FDifference(FDKind.DeletedElement, FDRating.Conflict); stepDiff.setSource(leftStep); stepDiff.setDescription( "The right process ends in the middle of the process but the left process proceeds with " + leftStep.getType() + " " + leftStep.getName()); } else if (rightStep != null) { // No left step stepDiff = new FDifference(FDKind.CreatedElement, FDRating.Conflict); stepDiff.setSource(leftStep); stepDiff.setDescription( "The left process ends in the middle of the process but the right process proceeds with " + rightStep.getType() + " " + rightStep.getName()); } parentDiff.addDifference(stepDiff); // Compare the next steps if (nextLeftStep != null && nextRightStep != null) { bisimulate(nextLeftStep, nextRightStep, parentDiff); } }