diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/HierarchicalMatchEngineFactoryGenerator.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/HierarchicalMatchEngineFactoryGenerator.java index 93ac1007d9..5310336516 100644 --- a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/HierarchicalMatchEngineFactoryGenerator.java +++ b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/HierarchicalMatchEngineFactoryGenerator.java @@ -12,7 +12,7 @@ import org.splevo.jamopp.diffing.match.JaMoPPEqualityStrategy; import org.splevo.jamopp.diffing.match.JaMoPPIgnoreStrategy; import org.splevo.jamopp.diffing.scope.PackageIgnoreChecker; -import org.splevo.jamopp.diffing.similarity.SimilarityChecker; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityChecker; import com.google.common.cache.CacheBuilder; @@ -32,7 +32,7 @@ private HierarchicalMatchEngineFactoryGenerator() { * @param key a key to identify the compared models. * @return the generated factory. */ - public static HierarchicalMatchEngineFactory generateMatchEngineFactory(SimilarityChecker simChecker, String key) { + public static HierarchicalMatchEngineFactory generateMatchEngineFactory(ISimilarityChecker simChecker, String key) { EqualityHelperExtensionProvider.Descriptor.Registry descRegistryImpl = EqualityHelperExtensionProviderDescriptorRegistryImpl.createStandaloneInstance(); descRegistryImpl.put(key, new SimilarityCheckerBasedEqualityHelperExtensionProviderDescriptor(simChecker)); diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/JavaMatchEngineFactoryGenerator.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/JavaMatchEngineFactoryGenerator.java index 97d59aae81..00014c26db 100644 --- a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/JavaMatchEngineFactoryGenerator.java +++ b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/JavaMatchEngineFactoryGenerator.java @@ -1,7 +1,9 @@ package cipm.consistency.commitintegration.diff.util; import org.splevo.diffing.match.HierarchicalMatchEngineFactory; -import org.splevo.jamopp.diffing.similarity.SimilarityChecker; +import org.splevo.jamopp.diffing.similarity.JavaSimilarityChecker; +import org.splevo.jamopp.diffing.similarity.JavaSimilarityToolboxBuilder; +import org.splevo.jamopp.diffing.similarity.base.MapSimilarityToolboxFactory; /** * A generator for HierarchicalMatchEngineFactories specific to Java models. @@ -18,6 +20,15 @@ private JavaMatchEngineFactoryGenerator() { * @return the generated factory. */ public static HierarchicalMatchEngineFactory generateMatchEngineFactory() { - return HierarchicalMatchEngineFactoryGenerator.generateMatchEngineFactory(new SimilarityChecker(), "javaxmi"); + var builder = new JavaSimilarityToolboxBuilder(); + builder.setSimilarityToolboxFactory(new MapSimilarityToolboxFactory()); + + var toolbox = builder.instantiate() + .buildNewSimilaritySwitchHandler() + .buildNormalizationHandlers() + .buildComparisonHandlers() + .build(); + + return HierarchicalMatchEngineFactoryGenerator.generateMatchEngineFactory(new JavaSimilarityChecker(toolbox), "javaxmi"); } } diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/SimilarityCheckerBasedEqualityHelperExtensionProviderDescriptor.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/SimilarityCheckerBasedEqualityHelperExtensionProviderDescriptor.java index c2eb53710e..be42434561 100644 --- a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/SimilarityCheckerBasedEqualityHelperExtensionProviderDescriptor.java +++ b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/SimilarityCheckerBasedEqualityHelperExtensionProviderDescriptor.java @@ -5,7 +5,7 @@ import org.eclipse.emf.compare.match.eobject.EqualityHelperExtensionProvider; import org.eclipse.emf.compare.utils.IEqualityHelper; import org.eclipse.emf.ecore.EObject; -import org.splevo.jamopp.diffing.similarity.SimilarityChecker; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityChecker; /** * A descriptor for the provider of a EqualityHelperExtension which is based on the SimilarityChecker. @@ -14,9 +14,9 @@ */ public class SimilarityCheckerBasedEqualityHelperExtensionProviderDescriptor implements EqualityHelperExtensionProvider.Descriptor { - private SimilarityChecker checker; + private ISimilarityChecker checker; - public SimilarityCheckerBasedEqualityHelperExtensionProviderDescriptor(SimilarityChecker check) { + public SimilarityCheckerBasedEqualityHelperExtensionProviderDescriptor(ISimilarityChecker check) { checker = check; } diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/IPCMRepositorySimilaritySwitch.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/IPCMRepositorySimilaritySwitch.java new file mode 100644 index 0000000000..42703c42c5 --- /dev/null +++ b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/IPCMRepositorySimilaritySwitch.java @@ -0,0 +1,13 @@ +package cipm.consistency.commitintegration.diff.util.pcm; + +import org.splevo.jamopp.diffing.similarity.base.ecore.IComposedSimilaritySwitch; + +/** + * An interface for switches that can be used to compute the similarity of + * Palladio Component Model (PCM) repositories. + * + * @author atora + */ +public interface IPCMRepositorySimilaritySwitch extends IComposedSimilaritySwitch { + +} diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositoryIDBasedSimilarityChecker.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositoryIDBasedSimilarityChecker.java deleted file mode 100644 index 3487e84f16..0000000000 --- a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositoryIDBasedSimilarityChecker.java +++ /dev/null @@ -1,26 +0,0 @@ -package cipm.consistency.commitintegration.diff.util.pcm; - -import org.eclipse.emf.ecore.EObject; - -import de.uka.ipd.sdq.identifier.Identifier; - -/** - * A SimiliarityChecker for PCM Repository models which includes the IDs of elements in the comparison. - * - * @author Martin Armbruster - */ -public class PCMRepositoryIDBasedSimilarityChecker extends PCMRepositorySimilarityChecker { - @Override - protected Boolean checkSimilarityForResolvedAndSameType(EObject element1, EObject element2, - boolean checkStatementPosition) { - if (element1 instanceof Identifier) { - if (element2 instanceof Identifier) { - Identifier id1 = (Identifier) element1; - Identifier id2 = (Identifier) element2; - return id1.getId().equals(id2.getId()); - } - return Boolean.FALSE; - } - return super.checkSimilarityForResolvedAndSameType(element1, element2, checkStatementPosition); - } -} diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositoryMatchEngineFactoryGenerator.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositoryMatchEngineFactoryGenerator.java index aaefb22438..f046b0e9fe 100644 --- a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositoryMatchEngineFactoryGenerator.java +++ b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositoryMatchEngineFactoryGenerator.java @@ -1,6 +1,7 @@ package cipm.consistency.commitintegration.diff.util.pcm; import org.splevo.diffing.match.HierarchicalMatchEngineFactory; +import org.splevo.jamopp.diffing.similarity.base.MapSimilarityToolboxFactory; import cipm.consistency.commitintegration.diff.util.HierarchicalMatchEngineFactoryGenerator; @@ -21,7 +22,14 @@ private PCMRepositoryMatchEngineFactoryGenerator() { * @return the generated factory. */ public static HierarchicalMatchEngineFactory generateMatchEngineFactory() { - return HierarchicalMatchEngineFactoryGenerator.generateMatchEngineFactory(new PCMRepositorySimilarityChecker(), + var builder = new PCMRepositorySimilarityToolboxBuilder(); + builder.setSimilarityToolboxFactory(new MapSimilarityToolboxFactory()); + + var toolbox = builder.instantiate() + .buildComparisonPairs() + .build(); + + return HierarchicalMatchEngineFactoryGenerator.generateMatchEngineFactory(new PCMRepositorySimilarityChecker(toolbox), "repository"); } @@ -32,7 +40,14 @@ public static HierarchicalMatchEngineFactory generateMatchEngineFactory() { * @return the generated factory. */ public static HierarchicalMatchEngineFactory generateIDBasedMatchEngineFactory() { + var builder = new PCMRepositorySimilarityToolboxBuilder(); + builder.setSimilarityToolboxFactory(new MapSimilarityToolboxFactory()); + + var toolbox = builder.instantiate() + .buildIDBasedComparisonPairs() + .build(); + return HierarchicalMatchEngineFactoryGenerator - .generateMatchEngineFactory(new PCMRepositoryIDBasedSimilarityChecker(), "repository"); + .generateMatchEngineFactory(new PCMRepositorySimilarityChecker(toolbox), "repository"); } } diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositorySimilarityChecker.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositorySimilarityChecker.java index 60e5d5686c..a6b22d8755 100644 --- a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositorySimilarityChecker.java +++ b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositorySimilarityChecker.java @@ -1,257 +1,28 @@ package cipm.consistency.commitintegration.diff.util.pcm; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.util.ComposedSwitch; -import org.palladiosimulator.pcm.repository.BasicComponent; -import org.palladiosimulator.pcm.repository.CollectionDataType; -import org.palladiosimulator.pcm.repository.CompositeComponent; -import org.palladiosimulator.pcm.repository.CompositeDataType; -import org.palladiosimulator.pcm.repository.InnerDeclaration; -import org.palladiosimulator.pcm.repository.OperationInterface; -import org.palladiosimulator.pcm.repository.OperationProvidedRole; -import org.palladiosimulator.pcm.repository.OperationRequiredRole; -import org.palladiosimulator.pcm.repository.OperationSignature; -import org.palladiosimulator.pcm.repository.Parameter; -import org.palladiosimulator.pcm.repository.PrimitiveDataType; -import org.palladiosimulator.pcm.repository.Repository; -import org.palladiosimulator.pcm.repository.util.RepositorySwitch; -import org.palladiosimulator.pcm.seff.AbstractAction; -import org.palladiosimulator.pcm.seff.AbstractBranchTransition; -import org.palladiosimulator.pcm.seff.BranchAction; -import org.palladiosimulator.pcm.seff.CollectionIteratorAction; -import org.palladiosimulator.pcm.seff.ExternalCallAction; -import org.palladiosimulator.pcm.seff.ResourceDemandingBehaviour; -import org.palladiosimulator.pcm.seff.ResourceDemandingSEFF; -import org.palladiosimulator.pcm.seff.util.SeffSwitch; -import org.splevo.jamopp.diffing.similarity.SimilarityChecker; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityToolbox; +import org.splevo.jamopp.diffing.similarity.base.ecore.AbstractComposedSwitchSimilarityChecker; + +import cipm.consistency.commitintegration.diff.util.pcm.requests.NewPCMRepositorySimilaritySwitchRequest; /** * A SimilarityChecker for PCM repository models. * * @author Martin Armbruster */ -public class PCMRepositorySimilarityChecker extends SimilarityChecker { +public class PCMRepositorySimilarityChecker extends AbstractComposedSwitchSimilarityChecker { + public PCMRepositorySimilarityChecker(ISimilarityToolbox st) { + super(st); + } + @Override - protected Boolean checkSimilarityForResolvedAndSameType(EObject element1, EObject element2, - boolean checkStatementPosition) { - return new PCMRepositorySimilaritySwitch(element1).doSwitch(element2); + protected PCMRepositorySimilarityComparer createSimilarityComparer(ISimilarityToolbox st) { + return new PCMRepositorySimilarityComparer(st); } - class PCMRepositorySimilaritySwitch extends ComposedSwitch { - private EObject compareElement; - - PCMRepositorySimilaritySwitch(EObject compareElement) { - this.compareElement = compareElement; - this.addSwitch(new SimilarityRepositorySwitch()); - this.addSwitch(new SimilaritySeffSwitch()); - } - - class SimilarityRepositorySwitch extends RepositorySwitch { - @Override - public Boolean caseRepository(Repository repo1) { - Repository repo2 = (Repository) compareElement; - - if (!repo1.getEntityName().equals(repo2.getEntityName())) { - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - - @Override - public Boolean caseOperationInterface(OperationInterface opInterface1) { - OperationInterface opInterface2 = (OperationInterface) compareElement; - - if (!opInterface1.getEntityName().equals(opInterface2.getEntityName())) { - return Boolean.FALSE; - } - - return PCMRepositorySimilarityChecker.this.areSimilar( - opInterface1.getParentInterfaces__Interface(), - opInterface2.getParentInterfaces__Interface()); - } - - @Override - public Boolean caseOperationSignature(OperationSignature sign1) { - OperationSignature sign2 = (OperationSignature) compareElement; - - if (!sign1.getEntityName().equals(sign2.getEntityName())) { - return Boolean.FALSE; - } - - var result = PCMRepositorySimilarityChecker.this.areSimilar( - sign1.getParameters__OperationSignature(), - sign2.getParameters__OperationSignature()); - - if (!result) { - return Boolean.FALSE; - } - - return PCMRepositorySimilarityChecker.this.isSimilar(sign1.getReturnType__OperationSignature(), - sign2.getReturnType__OperationSignature()); - } - - @Override - public Boolean caseParameter(Parameter param1) { - Parameter param2 = (Parameter) compareElement; - - if (!param1.getParameterName().equals(param2.getParameterName())) { - return Boolean.FALSE; - } - - return PCMRepositorySimilarityChecker.this.isSimilar(param1.getDataType__Parameter(), - param2.getDataType__Parameter()); - } - - @Override - public Boolean casePrimitiveDataType(PrimitiveDataType type1) { - PrimitiveDataType type2 = (PrimitiveDataType) compareElement; - return type1.getType() == type2.getType(); - } - - @Override - public Boolean caseCollectionDataType(CollectionDataType type1) { - CollectionDataType type2 = (CollectionDataType) compareElement; - - if (!type1.getEntityName().equals(type2.getEntityName())) { - return Boolean.FALSE; - } - - return PCMRepositorySimilarityChecker.this.isSimilar(type1.getInnerType_CollectionDataType(), - type2.getInnerType_CollectionDataType()); - } - - @Override - public Boolean caseCompositeDataType(CompositeDataType type1) { - CompositeDataType type2 = (CompositeDataType) compareElement; - - if (!type1.getEntityName().equals(type2.getEntityName())) { - return Boolean.FALSE; - } - - return PCMRepositorySimilarityChecker.this.areSimilar(type1.getParentType_CompositeDataType(), - type2.getParentType_CompositeDataType()); - } - - @Override - public Boolean caseInnerDeclaration(InnerDeclaration decl1) { - InnerDeclaration decl2 = (InnerDeclaration) compareElement; - - if (!decl1.getEntityName().equals(decl2.getEntityName())) { - return Boolean.FALSE; - } - - return PCMRepositorySimilarityChecker.this.isSimilar(decl1.getDatatype_InnerDeclaration(), - decl2.getDatatype_InnerDeclaration()); - } - - @Override - public Boolean caseBasicComponent(BasicComponent com1) { - BasicComponent com2 = (BasicComponent) compareElement; - - return com1.getEntityName().equals(com2.getEntityName()); - } - - @Override - public Boolean caseOperationProvidedRole(OperationProvidedRole opRole1) { - OperationProvidedRole opRole2 = (OperationProvidedRole) compareElement; - - return PCMRepositorySimilarityChecker.this.isSimilar( - opRole1.getProvidedInterface__OperationProvidedRole(), - opRole2.getProvidedInterface__OperationProvidedRole()); - } - - @Override - public Boolean caseOperationRequiredRole(OperationRequiredRole reqRole1) { - OperationRequiredRole reqRole2 = (OperationRequiredRole) compareElement; - - return PCMRepositorySimilarityChecker.this.isSimilar( - reqRole1.getRequiredInterface__OperationRequiredRole(), - reqRole2.getRequiredInterface__OperationRequiredRole()); - } - - @Override - public Boolean caseCompositeComponent(CompositeComponent com1) { - CompositeComponent com2 = (CompositeComponent) compareElement; - - return com1.getEntityName().equals(com2.getEntityName()); - } - } - - class SimilaritySeffSwitch extends SeffSwitch { - private Boolean checkPositionInContainer(AbstractAction action1, AbstractAction action2) { - ResourceDemandingBehaviour parent1 = (ResourceDemandingBehaviour) action1.eContainer(); - ResourceDemandingBehaviour parent2 = (ResourceDemandingBehaviour) action2.eContainer(); - - return parent1.getSteps_Behaviour().indexOf(action1) - == parent2.getSteps_Behaviour().indexOf(action2); - } - - @Override - public Boolean caseAbstractAction(AbstractAction action1) { - AbstractAction action2 = (AbstractAction) compareElement; - return checkPositionInContainer(action1, action2); - } - - @Override - public Boolean caseResourceDemandingBehaviour(ResourceDemandingBehaviour behav1) { - ResourceDemandingBehaviour behav2 = (ResourceDemandingBehaviour) compareElement; - return PCMRepositorySimilarityChecker.this.areSimilar(behav1.getSteps_Behaviour(), behav2.getSteps_Behaviour()); - } - - @Override - public Boolean caseResourceDemandingSEFF(ResourceDemandingSEFF seff1) { - ResourceDemandingSEFF seff2 = (ResourceDemandingSEFF) compareElement; - - return PCMRepositorySimilarityChecker.this.isSimilar(seff1.getDescribedService__SEFF(), - seff2.getDescribedService__SEFF()); - } - - @Override - public Boolean caseCollectionIteratorAction(CollectionIteratorAction action1) { - CollectionIteratorAction action2 = (CollectionIteratorAction) compareElement; - - var result = PCMRepositorySimilarityChecker.this.isSimilar( - action1.getParameter_CollectionIteratorAction(), - action2.getParameter_CollectionIteratorAction()); - - if (!result) { - return Boolean.FALSE; - } - - return checkPositionInContainer(action1, action2); - } - - @Override - public Boolean caseAbstractBranchTransition(AbstractBranchTransition transition1) { - AbstractBranchTransition transition2 = (AbstractBranchTransition) compareElement; - - BranchAction parent1 = (BranchAction) transition1.eContainer(); - BranchAction parent2 = (BranchAction) transition2.eContainer(); - - return parent1.getBranches_Branch().indexOf(transition1) == parent2.getBranches_Branch() - .indexOf(transition2); - } - - @Override - public Boolean caseExternalCallAction(ExternalCallAction action1) { - ExternalCallAction action2 = (ExternalCallAction) compareElement; - - var result = PCMRepositorySimilarityChecker.this.isSimilar( - action1.getCalledService_ExternalService(), - action2.getCalledService_ExternalService()); - - if (!result) { - return Boolean.FALSE; - } - - return checkPositionInContainer(action1, action2); - } - } - - @Override - public Boolean defaultCase(EObject obj) { - return null; - } + @Override + protected ISimilarityRequest makeDefaultSwitchRequest() { + return new NewPCMRepositorySimilaritySwitchRequest(true); } } diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositorySimilarityComparer.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositorySimilarityComparer.java new file mode 100644 index 0000000000..e19825f8eb --- /dev/null +++ b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositorySimilarityComparer.java @@ -0,0 +1,23 @@ +package cipm.consistency.commitintegration.diff.util.pcm; + +import org.splevo.jamopp.diffing.similarity.base.ecore.AbstractComposedSimilaritySwitchComparer; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityToolbox; + +/** + * Concrete implementation of {@link AbstractComposedSimilaritySwitchComparer} + * for for comparing Palladio Component Model (PCM) repositories. + * + * @author atora + */ +public class PCMRepositorySimilarityComparer extends AbstractComposedSimilaritySwitchComparer { + /** + * Constructs an instance with a given {@link ISimilarityToolbox}. + * + * @param st The {@link ISimilarityToolbox}, to which all incoming + * {@link ISimilarityRequest} instances should be delegated to. + */ + public PCMRepositorySimilarityComparer(ISimilarityToolbox st) { + super(st); + } +} diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositorySimilaritySwitch.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositorySimilaritySwitch.java new file mode 100644 index 0000000000..8f70179a5a --- /dev/null +++ b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositorySimilaritySwitch.java @@ -0,0 +1,66 @@ +package cipm.consistency.commitintegration.diff.util.pcm; + +import java.util.Collection; + +import org.eclipse.emf.ecore.util.Switch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; +import org.splevo.jamopp.diffing.similarity.base.ecore.AbstractComposedSimilaritySwitch; + +import cipm.consistency.commitintegration.diff.util.pcm.switches.SimilarityRepositorySwitch; +import cipm.consistency.commitintegration.diff.util.pcm.switches.SimilaritySeffSwitch; + +/** + * Concrete implementation of {@link AbstractComposedSimilaritySwitch} for + * computing the similarity of Palladio Component Model (PCM) repositories. + * + * @author atora + */ +public class PCMRepositorySimilaritySwitch extends AbstractComposedSimilaritySwitch + implements IPCMRepositorySimilaritySwitch { + /** + * Constructs an instance with the given request handler and the flag. Adds + * default inner switches to the constructed instance. + * + * @param srh The request handler, to which all incoming + * {@link ISimilarityRequest} instances will be + * delegated. + * @param checkStatementPosition The flag, which denotes whether this switch + * should take positions of statements while + * comparing. + */ + public PCMRepositorySimilaritySwitch(ISimilarityRequestHandler srh, boolean checkStatementPosition) { + super(srh); + + this.addSwitch(new SimilarityRepositorySwitch(this, checkStatementPosition)); + this.addSwitch(new SimilaritySeffSwitch(this, checkStatementPosition)); + } + + /** + * Constructs an instance with the given {@link ISimilarityRequestHandler}. + * + * @param srh The {@link ISimilarityRequestHandler}, to which incoming + * {@link ISimilarityRequest} instances will be delegated. + */ + protected PCMRepositorySimilaritySwitch(ISimilarityRequestHandler srh) { + super(srh); + } + + /** + * Variation of + * {@link #PCMRepositorySimilaritySwitch(ISimilarityRequestHandler)} that + * constructs an instance with the given switches. + */ + protected PCMRepositorySimilaritySwitch(ISimilarityRequestHandler srh, Collection> switches) { + super(srh, switches); + } + + /** + * Variation of + * {@link #PCMRepositorySimilaritySwitch(ISimilarityRequestHandler)} that + * constructs an instance with the given switches. + */ + protected PCMRepositorySimilaritySwitch(ISimilarityRequestHandler srh, Switch[] switches) { + super(srh, switches); + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositorySimilarityToolboxBuilder.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositorySimilarityToolboxBuilder.java new file mode 100644 index 0000000000..f6a10e0114 --- /dev/null +++ b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/PCMRepositorySimilarityToolboxBuilder.java @@ -0,0 +1,81 @@ +package cipm.consistency.commitintegration.diff.util.pcm; + +import org.splevo.jamopp.diffing.similarity.base.AbstractSimilarityToolboxBuilder; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; +import org.splevo.jamopp.diffing.similarity.base.ecore.MultipleSimilarityCheckHandler; +import org.splevo.jamopp.diffing.similarity.base.ecore.MultipleSimilarityCheckRequest; +import org.splevo.jamopp.diffing.similarity.base.ecore.SingleSimilarityCheckHandler; +import org.splevo.jamopp.diffing.similarity.base.ecore.SingleSimilarityCheckRequest; + +import cipm.consistency.commitintegration.diff.util.pcm.handlers.IDBasedSingleSimilarityCheckHandler; +import cipm.consistency.commitintegration.diff.util.pcm.handlers.NewPCMRepositorySimilaritySwitchHandler; +import cipm.consistency.commitintegration.diff.util.pcm.requests.NewPCMRepositorySimilaritySwitchRequest; + +/** + * Concrete implementation of {@link AbstractSimilarityToolboxBuilder} for + * constructing {@link ISimilarityToolbox} instances for computing similarity of + * Palladio Component Model (PCM) repositories. + * + * @author atora + */ +public class PCMRepositorySimilarityToolboxBuilder extends AbstractSimilarityToolboxBuilder { + @Override + public PCMRepositorySimilarityToolboxBuilder instantiate() { + return (PCMRepositorySimilarityToolboxBuilder) super.instantiate(); + } + + @Override + public PCMRepositorySimilarityToolboxBuilder buildRequestHandlerPair(Class req, + ISimilarityRequestHandler srh) { + return (PCMRepositorySimilarityToolboxBuilder) super.buildRequestHandlerPair(req, srh); + } + + /** + * Adds the handlers required to handle similarity checking related + * {@link ISimilarityRequest} instances.
+ *
+ * Pairs added by this method will override those added by + * {@link #buildIDBasedComparisonPairs()} + * + * @return this + */ + public PCMRepositorySimilarityToolboxBuilder buildComparisonPairs() { + this.buildRequestHandlerPair(SingleSimilarityCheckRequest.class, new SingleSimilarityCheckHandler()); + this.buildRequestHandlerPair(MultipleSimilarityCheckRequest.class, + new MultipleSimilarityCheckHandler(this.getCurrentToolbox())); + + return this; + } + + /** + * Adds the handlers required to handle ID based similarity checking related + * {@link ISimilarityRequest} instances.
+ *
+ * Pairs added by this method will override those added by + * {@link #buildComparisonPairs()} + * + * @return this + */ + public PCMRepositorySimilarityToolboxBuilder buildIDBasedComparisonPairs() { + this.buildRequestHandlerPair(SingleSimilarityCheckRequest.class, new IDBasedSingleSimilarityCheckHandler()); + this.buildRequestHandlerPair(MultipleSimilarityCheckRequest.class, + new MultipleSimilarityCheckHandler(this.getCurrentToolbox())); + + return this; + } + + /** + * Adds the handler needed to handle {@link ISimilarityRequest} instances, which + * request new similarity switch instances. + * + * @return this + * @see {@link IPCMRepositorySimilaritySwitch} + */ + public PCMRepositorySimilarityToolboxBuilder buildNewPCMRepositorySimilaritySwitch() { + this.buildRequestHandlerPair(NewPCMRepositorySimilaritySwitchRequest.class, + new NewPCMRepositorySimilaritySwitchHandler(this.getCurrentToolbox())); + + return this; + } +} diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/handlers/IDBasedSingleSimilarityCheckHandler.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/handlers/IDBasedSingleSimilarityCheckHandler.java new file mode 100644 index 0000000000..87772efc14 --- /dev/null +++ b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/handlers/IDBasedSingleSimilarityCheckHandler.java @@ -0,0 +1,40 @@ +package cipm.consistency.commitintegration.diff.util.pcm.handlers; + +import org.eclipse.emf.ecore.EObject; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ecore.SingleSimilarityCheckHandler; +import org.splevo.jamopp.diffing.similarity.base.ecore.SingleSimilarityCheckRequest; + +import de.uka.ipd.sdq.identifier.Identifier; + +/** + * A {@link SingleSimilarityCheckHandler} sub-class that handles + * {@link SingleSimilarityCheckRequest} instances. + * + * @author atora + */ +public class IDBasedSingleSimilarityCheckHandler extends SingleSimilarityCheckHandler { + /** + * {@inheritDoc}
+ *
+ * Takes the IDs of the elements from {@code req} into account. + */ + @Override + public Object handleSimilarityRequest(ISimilarityRequest req) { + SingleSimilarityCheckRequest castedR = (SingleSimilarityCheckRequest) req; + Object[] params = (Object[]) castedR.getParams(); + EObject element1 = (EObject) params[0]; + EObject element2 = (EObject) params[1]; + + if (element1 instanceof Identifier) { + if (element2 instanceof Identifier) { + Identifier id1 = (Identifier) element1; + Identifier id2 = (Identifier) element2; + return id1.getId().equals(id2.getId()); + } + return Boolean.FALSE; + } + + return super.handleSimilarityRequest(req); + } +} diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/handlers/NewPCMRepositorySimilaritySwitchHandler.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/handlers/NewPCMRepositorySimilaritySwitchHandler.java new file mode 100644 index 0000000000..e43f434872 --- /dev/null +++ b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/handlers/NewPCMRepositorySimilaritySwitchHandler.java @@ -0,0 +1,51 @@ +package cipm.consistency.commitintegration.diff.util.pcm.handlers; + +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +import cipm.consistency.commitintegration.diff.util.pcm.PCMRepositorySimilaritySwitch; +import cipm.consistency.commitintegration.diff.util.pcm.requests.NewPCMRepositorySimilaritySwitchRequest; + +/** + * An {@link ISimilarityRequestHandler} that processes incoming + * {@link NewPCMRepositorySimilaritySwitchRequest} instances. + * + * @author atora + */ +public class NewPCMRepositorySimilaritySwitchHandler implements ISimilarityRequestHandler { + /** + * The {@link ISimilarityRequestHandler}, which will be passed onto the + * similarity switches created in + * {@link #handleSimilarityRequest(ISimilarityRequest)}. + */ + private ISimilarityRequestHandler srh; + + /** + * Constructs an instance with the given {@link ISimilarityRequestHandler}. + * + * @param srh The {@link ISimilarityRequestHandler}, which will be passed onto + * the similarity switches created in + * {@link #handleSimilarityRequest(ISimilarityRequest)}. + */ + public NewPCMRepositorySimilaritySwitchHandler(ISimilarityRequestHandler srh) { + this.srh = srh; + } + + /** + * {@inheritDoc}
+ *
+ * Constructs a new {@link PCMRepositorySimilaritySwitch} (with its + * {@link #srh}) and returns it. + */ + @Override + public Object handleSimilarityRequest(ISimilarityRequest req) { + NewPCMRepositorySimilaritySwitchRequest castedR = (NewPCMRepositorySimilaritySwitchRequest) req; + Boolean csp = (Boolean) castedR.getParams(); + return new PCMRepositorySimilaritySwitch(this.srh, csp); + } + + @Override + public boolean canHandleSimilarityRequest(Class reqClass) { + return reqClass.equals(NewPCMRepositorySimilaritySwitchRequest.class); + } +} diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/requests/NewPCMRepositorySimilaritySwitchRequest.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/requests/NewPCMRepositorySimilaritySwitchRequest.java new file mode 100644 index 0000000000..dc115cea6a --- /dev/null +++ b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/requests/NewPCMRepositorySimilaritySwitchRequest.java @@ -0,0 +1,35 @@ +package cipm.consistency.commitintegration.diff.util.pcm.requests; + +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; + +/** + * An {@link ISimilarityRequest}, which contains a flag that denotes, whether + * the new similarity switch created by processing this request should care + * about positions of statements while computing similarity. + * + * @author atora + */ +public class NewPCMRepositorySimilaritySwitchRequest implements ISimilarityRequest { + /** + * The flag that denotes, whether the resulting new similarity switch should + * care about positions of statements while computing similarity. + */ + private boolean checkStatementPosition; + + /** + * Constructs an instance with the given parameter. + * + * @param checkStatementPosition The flag that denotes, whether the resulting + * new similarity switch should care about + * positions of statements while computing + * similarity. + */ + public NewPCMRepositorySimilaritySwitchRequest(boolean checkStatementPosition) { + this.checkStatementPosition = checkStatementPosition; + } + + @Override + public Object getParams() { + return this.checkStatementPosition; + } +} diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/switches/IPCMInnerSwitch.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/switches/IPCMInnerSwitch.java new file mode 100644 index 0000000000..e14418cb89 --- /dev/null +++ b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/switches/IPCMInnerSwitch.java @@ -0,0 +1,17 @@ +package cipm.consistency.commitintegration.diff.util.pcm.switches; + +import org.splevo.jamopp.diffing.similarity.base.ecore.IInnerSwitch; + +/** + * An interface that contains default methods, which create and send + * {@link ISimilarityRequest} instances to {@link ISimilarityRequestHandler} + * instances that are supposed to handle them.
+ *
+ * These methods can be used to spare code duplication in inner switches, which + * need them. + * + * @author atora + */ +public interface IPCMInnerSwitch extends IInnerSwitch { + +} diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/switches/IPCMPositionInnerSwitch.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/switches/IPCMPositionInnerSwitch.java new file mode 100644 index 0000000000..246e9f72f2 --- /dev/null +++ b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/switches/IPCMPositionInnerSwitch.java @@ -0,0 +1,27 @@ +package cipm.consistency.commitintegration.diff.util.pcm.switches; + +import org.splevo.jamopp.diffing.similarity.base.ecore.IPositionInnerSwitch; + +import cipm.consistency.commitintegration.diff.util.pcm.IPCMRepositorySimilaritySwitch; +import cipm.consistency.commitintegration.diff.util.pcm.requests.NewPCMRepositorySimilaritySwitchRequest; + +/** + * An interface that bundles and complements {@link IPCMInnerSwitch} and + * {@link IPositionInnerSwitch} interfaces. Contains methods, which are specific + * to computing similarity in the context of Palladio Component Model (PCM) + * repositories. + * + * @author atora + */ +public interface IPCMPositionInnerSwitch extends IPCMInnerSwitch, IPositionInnerSwitch { + /** + * Sends out a {@link NewPCMRepositorySimilaritySwitchRequest} and returns the + * result. + * + * @see {@link #handleSimilarityRequest(org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest)} + */ + public default IPCMRepositorySimilaritySwitch requestNewSwitch(boolean checkStatementPosition) { + return (IPCMRepositorySimilaritySwitch) this + .handleSimilarityRequest(new NewPCMRepositorySimilaritySwitchRequest(checkStatementPosition)); + } +} diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/switches/SimilarityRepositorySwitch.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/switches/SimilarityRepositorySwitch.java new file mode 100644 index 0000000000..c004833d5e --- /dev/null +++ b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/switches/SimilarityRepositorySwitch.java @@ -0,0 +1,176 @@ +package cipm.consistency.commitintegration.diff.util.pcm.switches; + +import org.palladiosimulator.pcm.repository.BasicComponent; +import org.palladiosimulator.pcm.repository.CollectionDataType; +import org.palladiosimulator.pcm.repository.CompositeComponent; +import org.palladiosimulator.pcm.repository.CompositeDataType; +import org.palladiosimulator.pcm.repository.InnerDeclaration; +import org.palladiosimulator.pcm.repository.OperationInterface; +import org.palladiosimulator.pcm.repository.OperationProvidedRole; +import org.palladiosimulator.pcm.repository.OperationRequiredRole; +import org.palladiosimulator.pcm.repository.OperationSignature; +import org.palladiosimulator.pcm.repository.Parameter; +import org.palladiosimulator.pcm.repository.PrimitiveDataType; +import org.palladiosimulator.pcm.repository.Repository; +import org.palladiosimulator.pcm.repository.util.RepositorySwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; +import org.splevo.jamopp.diffing.similarity.base.ecore.IComposedSwitchAdapter; + +import cipm.consistency.commitintegration.diff.util.pcm.IPCMRepositorySimilaritySwitch; + +public class SimilarityRepositorySwitch extends RepositorySwitch implements IPCMPositionInnerSwitch { + private IPCMRepositorySimilaritySwitch similaritySwitch; + private boolean checkStatementPosition; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public IComposedSwitchAdapter getContainingSwitch() { + return this.similaritySwitch; + } + + @Override + public boolean shouldCheckStatementPosition() { + return this.checkStatementPosition; + } + + public SimilarityRepositorySwitch( + IPCMRepositorySimilaritySwitch similaritySwitch, + boolean checkStatementPosition) { + this.similaritySwitch = similaritySwitch; + this.checkStatementPosition = checkStatementPosition; + } + + @Override + public Boolean caseRepository(Repository repo1) { + Repository repo2 = (Repository) this.getCompareElement(); + + if (!repo1.getEntityName().equals(repo2.getEntityName())) { + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + + @Override + public Boolean caseOperationInterface(OperationInterface opInterface1) { + OperationInterface opInterface2 = (OperationInterface) this.getCompareElement(); + + if (!opInterface1.getEntityName().equals(opInterface2.getEntityName())) { + return Boolean.FALSE; + } + + return this.areSimilar( + opInterface1.getParentInterfaces__Interface(), + opInterface2.getParentInterfaces__Interface()); + } + + @Override + public Boolean caseOperationSignature(OperationSignature sign1) { + OperationSignature sign2 = (OperationSignature) this.getCompareElement(); + + if (!sign1.getEntityName().equals(sign2.getEntityName())) { + return Boolean.FALSE; + } + + var result = this.areSimilar( + sign1.getParameters__OperationSignature(), + sign2.getParameters__OperationSignature()); + + if (!result) { + return Boolean.FALSE; + } + + return this.isSimilar(sign1.getReturnType__OperationSignature(), + sign2.getReturnType__OperationSignature()); + } + + @Override + public Boolean caseParameter(Parameter param1) { + Parameter param2 = (Parameter) this.getCompareElement(); + + if (!param1.getParameterName().equals(param2.getParameterName())) { + return Boolean.FALSE; + } + + return this.isSimilar(param1.getDataType__Parameter(), + param2.getDataType__Parameter()); + } + + @Override + public Boolean casePrimitiveDataType(PrimitiveDataType type1) { + PrimitiveDataType type2 = (PrimitiveDataType) this.getCompareElement(); + return type1.getType() == type2.getType(); + } + + @Override + public Boolean caseCollectionDataType(CollectionDataType type1) { + CollectionDataType type2 = (CollectionDataType) this.getCompareElement(); + + if (!type1.getEntityName().equals(type2.getEntityName())) { + return Boolean.FALSE; + } + + return this.isSimilar(type1.getInnerType_CollectionDataType(), + type2.getInnerType_CollectionDataType()); + } + + @Override + public Boolean caseCompositeDataType(CompositeDataType type1) { + CompositeDataType type2 = (CompositeDataType) this.getCompareElement(); + + if (!type1.getEntityName().equals(type2.getEntityName())) { + return Boolean.FALSE; + } + + return this.areSimilar(type1.getParentType_CompositeDataType(), + type2.getParentType_CompositeDataType()); + } + + @Override + public Boolean caseInnerDeclaration(InnerDeclaration decl1) { + InnerDeclaration decl2 = (InnerDeclaration) this.getCompareElement(); + + if (!decl1.getEntityName().equals(decl2.getEntityName())) { + return Boolean.FALSE; + } + + return this.isSimilar(decl1.getDatatype_InnerDeclaration(), + decl2.getDatatype_InnerDeclaration()); + } + + @Override + public Boolean caseBasicComponent(BasicComponent com1) { + BasicComponent com2 = (BasicComponent) this.getCompareElement(); + + return com1.getEntityName().equals(com2.getEntityName()); + } + + @Override + public Boolean caseOperationProvidedRole(OperationProvidedRole opRole1) { + OperationProvidedRole opRole2 = (OperationProvidedRole) this.getCompareElement(); + + return this.isSimilar( + opRole1.getProvidedInterface__OperationProvidedRole(), + opRole2.getProvidedInterface__OperationProvidedRole()); + } + + @Override + public Boolean caseOperationRequiredRole(OperationRequiredRole reqRole1) { + OperationRequiredRole reqRole2 = (OperationRequiredRole) this.getCompareElement(); + + return this.isSimilar( + reqRole1.getRequiredInterface__OperationRequiredRole(), + reqRole2.getRequiredInterface__OperationRequiredRole()); + } + + @Override + public Boolean caseCompositeComponent(CompositeComponent com1) { + CompositeComponent com2 = (CompositeComponent) this.getCompareElement(); + + return com1.getEntityName().equals(com2.getEntityName()); + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/switches/SimilaritySeffSwitch.java b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/switches/SimilaritySeffSwitch.java new file mode 100644 index 0000000000..67b946e198 --- /dev/null +++ b/commit-based-cipm/bundles/fi/cipm.consistency.commitintegration.diff.util/src/cipm/consistency/commitintegration/diff/util/pcm/switches/SimilaritySeffSwitch.java @@ -0,0 +1,110 @@ +package cipm.consistency.commitintegration.diff.util.pcm.switches; + +import org.palladiosimulator.pcm.seff.AbstractAction; +import org.palladiosimulator.pcm.seff.AbstractBranchTransition; +import org.palladiosimulator.pcm.seff.BranchAction; +import org.palladiosimulator.pcm.seff.CollectionIteratorAction; +import org.palladiosimulator.pcm.seff.ExternalCallAction; +import org.palladiosimulator.pcm.seff.ResourceDemandingBehaviour; +import org.palladiosimulator.pcm.seff.ResourceDemandingSEFF; +import org.palladiosimulator.pcm.seff.util.SeffSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; +import org.splevo.jamopp.diffing.similarity.base.ecore.IComposedSwitchAdapter; + +import cipm.consistency.commitintegration.diff.util.pcm.IPCMRepositorySimilaritySwitch; + +public class SimilaritySeffSwitch extends SeffSwitch implements IPCMPositionInnerSwitch { + private IPCMRepositorySimilaritySwitch similaritySwitch; + private boolean checkStatementPosition; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public IComposedSwitchAdapter getContainingSwitch() { + return this.similaritySwitch; + } + + @Override + public boolean shouldCheckStatementPosition() { + return this.checkStatementPosition; + } + + public SimilaritySeffSwitch( + IPCMRepositorySimilaritySwitch similaritySwitch, + boolean checkStatementPosition) { + this.similaritySwitch = similaritySwitch; + this.checkStatementPosition = checkStatementPosition; + } + + private Boolean checkPositionInContainer(AbstractAction action1, AbstractAction action2) { + ResourceDemandingBehaviour parent1 = (ResourceDemandingBehaviour) action1.eContainer(); + ResourceDemandingBehaviour parent2 = (ResourceDemandingBehaviour) action2.eContainer(); + + return parent1.getSteps_Behaviour().indexOf(action1) + == parent2.getSteps_Behaviour().indexOf(action2); + } + + @Override + public Boolean caseAbstractAction(AbstractAction action1) { + AbstractAction action2 = (AbstractAction) getCompareElement(); + return checkPositionInContainer(action1, action2); + } + + @Override + public Boolean caseResourceDemandingBehaviour(ResourceDemandingBehaviour behav1) { + ResourceDemandingBehaviour behav2 = (ResourceDemandingBehaviour) getCompareElement(); + return areSimilar(behav1.getSteps_Behaviour(), behav2.getSteps_Behaviour()); + } + + @Override + public Boolean caseResourceDemandingSEFF(ResourceDemandingSEFF seff1) { + ResourceDemandingSEFF seff2 = (ResourceDemandingSEFF) getCompareElement(); + + return isSimilar(seff1.getDescribedService__SEFF(), + seff2.getDescribedService__SEFF()); + } + + @Override + public Boolean caseCollectionIteratorAction(CollectionIteratorAction action1) { + CollectionIteratorAction action2 = (CollectionIteratorAction) getCompareElement(); + + var result = isSimilar( + action1.getParameter_CollectionIteratorAction(), + action2.getParameter_CollectionIteratorAction()); + + if (!result) { + return Boolean.FALSE; + } + + return checkPositionInContainer(action1, action2); + } + + @Override + public Boolean caseAbstractBranchTransition(AbstractBranchTransition transition1) { + AbstractBranchTransition transition2 = (AbstractBranchTransition) getCompareElement(); + + BranchAction parent1 = (BranchAction) transition1.eContainer(); + BranchAction parent2 = (BranchAction) transition2.eContainer(); + + return parent1.getBranches_Branch().indexOf(transition1) == parent2.getBranches_Branch() + .indexOf(transition2); + } + + @Override + public Boolean caseExternalCallAction(ExternalCallAction action1) { + ExternalCallAction action2 = (ExternalCallAction) getCompareElement(); + + var result = isSimilar( + action1.getCalledService_ExternalService(), + action2.getCalledService_ExternalService()); + + if (!result) { + return Boolean.FALSE; + } + + return checkPositionInContainer(action1, action2); + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.diffing/src/org/splevo/diffing/util/NormalizationUtil.java b/commit-based-cipm/bundles/fi/org.splevo.diffing/src/org/splevo/diffing/util/NormalizationUtil.java index 9d76db89b2..97e2cf598b 100644 --- a/commit-based-cipm/bundles/fi/org.splevo.diffing/src/org/splevo/diffing/util/NormalizationUtil.java +++ b/commit-based-cipm/bundles/fi/org.splevo.diffing/src/org/splevo/diffing/util/NormalizationUtil.java @@ -64,7 +64,7 @@ public static String normalize(String original, Map normalizati * The list of normalizations to apply. * @return The normalized name space string. */ - public static String normalizeNamespace(String namespace, LinkedHashMap normalizations) { + public static String normalizeNamespace(String namespace, Map normalizations) { namespace = Strings.nullToEmpty(namespace); for (Pattern pattern : normalizations.keySet()) { diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/META-INF/MANIFEST.MF b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/META-INF/MANIFEST.MF index 88e5314ed3..4c2532b922 100644 --- a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/META-INF/MANIFEST.MF +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/META-INF/MANIFEST.MF @@ -31,6 +31,11 @@ Export-Package: org.splevo.jamopp.diffing, org.splevo.jamopp.diffing.postprocessor, org.splevo.jamopp.diffing.scope, org.splevo.jamopp.diffing.similarity, + org.splevo.jamopp.diffing.similarity.base, + org.splevo.jamopp.diffing.similarity.base.ecore, + org.splevo.jamopp.diffing.similarity.switches, + org.splevo.jamopp.diffing.similarity.handlers, + org.splevo.jamopp.diffing.similarity.requests, org.splevo.jamopp.diffing.util Bundle-ActivationPolicy: lazy Automatic-Module-Name: org.splevo.jamopp.diffing diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/JaMoPPDiffer.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/JaMoPPDiffer.java index 6d8ad5bd2d..35b3ddb311 100644 --- a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/JaMoPPDiffer.java +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/JaMoPPDiffer.java @@ -63,7 +63,10 @@ import org.splevo.jamopp.diffing.postprocessor.JaMoPPPostProcessor; import org.splevo.jamopp.diffing.scope.JavaModelMatchScope; import org.splevo.jamopp.diffing.scope.PackageIgnoreChecker; -import org.splevo.jamopp.diffing.similarity.SimilarityChecker; +import org.splevo.jamopp.diffing.similarity.JavaSimilarityChecker; +import org.splevo.jamopp.diffing.similarity.JavaSimilarityToolboxBuilder; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityChecker; +import org.splevo.jamopp.diffing.similarity.base.MapSimilarityToolboxFactory; import org.splevo.jamopp.extraction.JaMoPPSoftwareModelExtractor; import com.google.common.cache.CacheBuilder; @@ -405,7 +408,7 @@ private boolean isSingleSideRootMatch(Match rootMatch) { private IMatchEngine.Factory.Registry initMatchEngine(PackageIgnoreChecker packageIgnoreChecker, Map diffingOptions) { - SimilarityChecker similarityChecker = initSimilarityChecker(diffingOptions); + ISimilarityChecker similarityChecker = initSimilarityChecker(diffingOptions); IEqualityHelper equalityHelper = initEqualityHelper(similarityChecker); EqualityStrategy equalityStrategy = new JaMoPPEqualityStrategy(similarityChecker); IgnoreStrategy ignoreStrategy = new JaMoPPIgnoreStrategy(packageIgnoreChecker); @@ -428,7 +431,7 @@ private IMatchEngine.Factory.Registry initMatchEngine(PackageIgnoreChecker packa * The map of configurations. * @return The prepared checker. */ - private SimilarityChecker initSimilarityChecker(Map diffingOptions) { + private ISimilarityChecker initSimilarityChecker(Map diffingOptions) { String configString = diffingOptions.get(OPTION_JAVA_CLASSIFIER_NORMALIZATION); LinkedHashMap classifierNorms = NormalizationUtil.loadRemoveNormalizations(configString, null); LinkedHashMap compUnitNorms = NormalizationUtil @@ -437,7 +440,16 @@ private SimilarityChecker initSimilarityChecker(Map diffingOptio String configStringPackage = diffingOptions.get(OPTION_JAVA_PACKAGE_NORMALIZATION); LinkedHashMap packageNorms = NormalizationUtil.loadReplaceNormalizations(configStringPackage); - return new SimilarityChecker(classifierNorms, compUnitNorms, packageNorms); + var builder = new JavaSimilarityToolboxBuilder(); + builder.setSimilarityToolboxFactory(new MapSimilarityToolboxFactory()); + + var toolbox = builder.instantiate() + .buildNewSimilaritySwitchHandler() + .buildNormalizationHandlers(classifierNorms, compUnitNorms, packageNorms) + .buildComparisonHandlers() + .build(); + + return new JavaSimilarityChecker(toolbox); } /** @@ -447,7 +459,7 @@ private SimilarityChecker initSimilarityChecker(Map diffingOptio * The similarity checker to use. * @return The prepared equality helper. */ - private IEqualityHelper initEqualityHelper(SimilarityChecker similarityChecker) { + private IEqualityHelper initEqualityHelper(ISimilarityChecker similarityChecker) { final LoadingCache cache = initEqualityCache(); IEqualityHelper equalityHelper = new JaMoPPEqualityHelper(cache, similarityChecker); return equalityHelper; diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/match/JaMoPPEqualityHelper.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/match/JaMoPPEqualityHelper.java index f684932dd0..d4e46a28f2 100644 --- a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/match/JaMoPPEqualityHelper.java +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/match/JaMoPPEqualityHelper.java @@ -13,7 +13,7 @@ import org.eclipse.emf.compare.utils.EqualityHelper; import org.eclipse.emf.ecore.EObject; -import org.splevo.jamopp.diffing.similarity.SimilarityChecker; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityChecker; import com.google.common.cache.LoadingCache; @@ -23,7 +23,7 @@ public class JaMoPPEqualityHelper extends EqualityHelper { /** A similarity checker for internal similarity comparisons. */ - private SimilarityChecker similarityChecker = null; + private ISimilarityChecker similarityChecker = null; /** * Constructor to initialize the required cache. @@ -34,7 +34,7 @@ public class JaMoPPEqualityHelper extends EqualityHelper { * The similarity checker to be used. */ public JaMoPPEqualityHelper(LoadingCache uriCache, - SimilarityChecker similarityChecker) { + ISimilarityChecker similarityChecker) { super(uriCache); this.similarityChecker = similarityChecker; } diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/match/JaMoPPEqualityStrategy.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/match/JaMoPPEqualityStrategy.java index 468076aa68..9760aaaa37 100644 --- a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/match/JaMoPPEqualityStrategy.java +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/match/JaMoPPEqualityStrategy.java @@ -13,7 +13,7 @@ import org.eclipse.emf.ecore.EObject; import org.splevo.diffing.match.HierarchicalMatchEngine.EqualityStrategy; -import org.splevo.jamopp.diffing.similarity.SimilarityChecker; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityChecker; /** * JaMoPP java model specific equality strategy based on the similarity checker strategy. @@ -21,7 +21,7 @@ public class JaMoPPEqualityStrategy implements EqualityStrategy { /** The similarity checker to use internally for equality checks. */ - private SimilarityChecker similarityChecker = null; + private ISimilarityChecker similarityChecker = null; /** * Constructor to set the required dependencies. @@ -29,7 +29,7 @@ public class JaMoPPEqualityStrategy implements EqualityStrategy { * @param similarityChecker * The similarity checker to proof equality. */ - public JaMoPPEqualityStrategy(SimilarityChecker similarityChecker) { + public JaMoPPEqualityStrategy(ISimilarityChecker similarityChecker) { this.similarityChecker = similarityChecker; } diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/IJavaSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/IJavaSimilaritySwitch.java new file mode 100644 index 0000000000..cee4ae6d17 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/IJavaSimilaritySwitch.java @@ -0,0 +1,13 @@ +package org.splevo.jamopp.diffing.similarity; + +import org.splevo.jamopp.diffing.similarity.base.ecore.IComposedSimilaritySwitch; + +/** + * An interface for switches that can be used to compute the similarity of Java + * model elements. + * + * @author atora + */ +public interface IJavaSimilaritySwitch extends IComposedSimilaritySwitch { + +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/ILoggableJavaSwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/ILoggableJavaSwitch.java new file mode 100644 index 0000000000..e6a800e299 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/ILoggableJavaSwitch.java @@ -0,0 +1,82 @@ +package org.splevo.jamopp.diffing.similarity; + +import org.apache.log4j.Logger; +import org.apache.log4j.Level; + +import com.google.common.base.Strings; + +/** + * An interface to help log the switch classes without having to duplicate + * similar log message structures.
+ *
+ * Log messages' level is set to {@code Priority.INFO} to avoid flooding the + * console and causing memory issues. + * + * @author atora + */ +public interface ILoggableJavaSwitch { + /** + * @return The logger associated with the concrete implementor. + */ + public default Logger getLogger() { + return Logger.getLogger(this.getLoggerName()); + } + + /** + * Can be overridden in implementors to group log messages better. + * + * @return The logger's name, which can be accessed by {@link #getLogger()}. + */ + public default String getLoggerName() { + return this.getLoggerPrefix() + this.getClass().getSimpleName(); + } + + /** + * Can be overridden in implementors to group log messages better. + * + * @return The prefix of the logger's name, which can be accessed by + * {@link #getLogger()}. + */ + public default String getLoggerPrefix() { + return "javaswitch."; + } + + /** + * The version of {@link #logComparison(String, String, String)} for Object. + */ + public default void logComparison(Object subject1, Object subject2, String subjectDesc) { + String s1 = subject1 != null ? subject1.toString() : null; + String s2 = subject2 != null ? subject2.toString() : null; + + this.logComparison(s1, s2, subjectDesc); + } + + /** + * Logs the comparison of the both subjects. + */ + public default void logComparison(String subject1, String subject2, String subjectDesc) { + this.logMessage("Comparing " + subjectDesc + "s (1 vs 2): " + Strings.nullToEmpty(subject1) + " vs " + + Strings.nullToEmpty(subject2)); + } + + /** + * Logs a boolean result with the given subject description. + */ + public default void logResult(boolean result, String subjectDesc) { + this.logMessage("Result of comparing " + subjectDesc + "s: " + result); + } + + /** + * Logs the given message. + */ + public default void logMessage(String msg) { + this.logMessage(msg, Level.INFO); + } + + /** + * Logs the given message at the given level. + */ + public default void logMessage(String msg, Level level) { + this.getLogger().log(level, msg); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/ILoggableSwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/ILoggableSwitch.java new file mode 100644 index 0000000000..6cd35a1871 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/ILoggableSwitch.java @@ -0,0 +1,42 @@ +package org.splevo.jamopp.diffing.similarity; + +import org.apache.log4j.Logger; +import org.apache.log4j.Level; + +import com.google.common.base.Strings; + +/** + * An interface to help log the switch classes without having to duplicate + * similar log message structures. + *

+ * Log messages' level is set to {@code Priority.INFO} to avoid flooding the console + * and causing memory issues. + * + * @author atora + */ +public interface ILoggableSwitch { + public default Logger getLogger() { + return Logger.getLogger(this.getClass().getSimpleName()); + } + + public default void logComparison(String subject1, String subject2, String subjectDesc) { + this.logMessage("Comparing " + subjectDesc + "s (1 vs 2): " + + Strings.nullToEmpty(subject1) + " vs " + Strings.nullToEmpty(subject2)); + } + + public default void logResult(boolean result, String subjectDesc) { + this.logMessage("Result of comparing " + subjectDesc + "s: " + result); + } + + public default void logMessage(String msg) { + this.logMessage(msg, Level.INFO); + } + + public default void logMessage(String msg, Level p) { + this.getLogger().log(p, msg); + } + + public default void logMessage(String msg, String subjectDesc) { + this.logMessage(msg + " (while comparing" + subjectDesc + ")"); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/JavaSimilarityChecker.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/JavaSimilarityChecker.java new file mode 100644 index 0000000000..9d4b38cb95 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/JavaSimilarityChecker.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2014 + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Benjamin Klatt - initial API and implementation and/or initial documentation + * Martin Armbruster - enable change of default behavior for statement position check. + *******************************************************************************/ +package org.splevo.jamopp.diffing.similarity; + +import org.apache.log4j.Logger; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityToolbox; +import org.splevo.jamopp.diffing.similarity.base.ecore.AbstractComposedSwitchSimilarityChecker; +import org.splevo.jamopp.diffing.similarity.requests.NewSimilaritySwitchRequest; + +/** + * Checker for the similarity of two elements specific for the java application + * model. + * + * TODO: Check caching for this similarity checker. Would require to pass this + * to the similarity switch as well! + * + */ +public class JavaSimilarityChecker extends AbstractComposedSwitchSimilarityChecker { + + /** The logger for this class. */ + @SuppressWarnings("unused") + private Logger logger = Logger.getLogger(JavaSimilarityChecker.class); + + /** + * Constructs an instance with the given parameter. + * + * @param st {@link ISimilarityToolbox} to which all incoming + * {@link ISimilarityRequest} instances will be delegated to. + */ + public JavaSimilarityChecker(ISimilarityToolbox st) { + super(st); + } + + @Override + protected JavaSimilarityComparer createSimilarityComparer(ISimilarityToolbox st) { + return new JavaSimilarityComparer(st); + } + + @Override + protected ISimilarityRequest makeDefaultSwitchRequest() { + return new NewSimilaritySwitchRequest(true); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/JavaSimilarityComparer.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/JavaSimilarityComparer.java new file mode 100644 index 0000000000..0b89dd5a0e --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/JavaSimilarityComparer.java @@ -0,0 +1,23 @@ +package org.splevo.jamopp.diffing.similarity; + +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityToolbox; +import org.splevo.jamopp.diffing.similarity.base.ecore.AbstractComposedSimilaritySwitchComparer; + +/** + * Concrete implementation of {@link AbstractComposedSimilaritySwitchComparer} + * for comparing Java elements. + * + * @author atora + */ +public class JavaSimilarityComparer extends AbstractComposedSimilaritySwitchComparer { + /** + * Constructs an instance with the given parameter. + * + * @param st {@link ISimilarityToolbox} to which all incoming + * {@link ISimilarityRequest} instances will be delegated to. + */ + public JavaSimilarityComparer(ISimilarityToolbox st) { + super(st); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/JavaSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/JavaSimilaritySwitch.java new file mode 100644 index 0000000000..8664c56575 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/JavaSimilaritySwitch.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * Copyright (c) 2014 + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Benjamin Klatt - initial API and implementation and/or initial documentation + * Martin Armbruster - extension for expanded JaMoPP + *******************************************************************************/ +package org.splevo.jamopp.diffing.similarity; + +import java.util.Collection; + +import org.eclipse.emf.ecore.util.Switch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; +import org.splevo.jamopp.diffing.similarity.base.ecore.AbstractComposedSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.AnnotationsSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.ArraysSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.ClassifiersSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.CommonsSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.ContainersSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.ExpressionsSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.GenericsSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.ImportsSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.InstantiationsSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.LayoutSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.LiteralsSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.MembersSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.ModifiersSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.ModulesSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.OperatorsSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.ParametersSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.ReferencesSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.StatementsSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.TypesSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.switches.VariablesSimilaritySwitch; + +/** + * Internal switch class to prove element similarity. + * + *

+ * The similarity case methods do not need to check for null values. It is + * assumed that the calling class does a null value check for the elements to + * compare in advanced, such as done by the SimilarityChecker class. + *

+ * + *

+ * Check strategy:
+ * First all "not-similar"-criteria are checked. If none hits, true will be + * returned. + *

+ */ +public class JavaSimilaritySwitch extends AbstractComposedSimilaritySwitch implements IJavaSimilaritySwitch { + /** + * Constructs an instance with the given request handler and the flag. Adds + * default inner switches to the constructed instance. + * + * @param srh The request handler, to which all incoming + * {@link ISimilarityRequest} instances will be + * delegated. + * @param checkStatementPosition The flag, which denotes whether this switch + * should take positions of statements while + * comparing. + */ + public JavaSimilaritySwitch(ISimilarityRequestHandler srh, boolean checkStatementPosition) { + super(srh); + + addSwitch(new AnnotationsSimilaritySwitch(this, checkStatementPosition)); + addSwitch(new ArraysSimilaritySwitch()); + addSwitch(new ClassifiersSimilaritySwitch(this, checkStatementPosition)); + addSwitch(new CommonsSimilaritySwitch(this, checkStatementPosition)); + addSwitch(new ContainersSimilaritySwitch(this, checkStatementPosition)); + addSwitch(new ExpressionsSimilaritySwitch(this, checkStatementPosition)); + addSwitch(new GenericsSimilaritySwitch(this, checkStatementPosition)); + addSwitch(new ImportsSimilaritySwitch(this, checkStatementPosition)); + addSwitch(new InstantiationsSimilaritySwitch(this, checkStatementPosition)); + addSwitch(new LiteralsSimilaritySwitch(this)); + addSwitch(new MembersSimilaritySwitch(this, checkStatementPosition)); + addSwitch(new ModifiersSimilaritySwitch()); + addSwitch(new OperatorsSimilaritySwitch()); + addSwitch(new ParametersSimilaritySwitch(this)); + addSwitch(new ReferencesSimilaritySwitch(this, checkStatementPosition)); + addSwitch(new StatementsSimilaritySwitch(this, checkStatementPosition)); + addSwitch(new TypesSimilaritySwitch(this, checkStatementPosition)); + addSwitch(new VariablesSimilaritySwitch(this)); + addSwitch(new LayoutSimilaritySwitch()); + addSwitch(new ModulesSimilaritySwitch(this, checkStatementPosition)); + } + + /** + * Variation of + * {@link #JavaSimilaritySwitch(ISimilarityRequestHandler, boolean)} that + * constructs an instance without any inner switches. + * + * @see {@link AbstractComposedSimilaritySwitch} + * @see {@link IInnerSwitch} + */ + protected JavaSimilaritySwitch(ISimilarityRequestHandler srh) { + super(srh); + } + + /** + * Variation of + * {@link #JavaSimilaritySwitch(ISimilarityRequestHandler, boolean)} that + * constructs an instance with the given switches. + * + * @see {@link AbstractComposedSimilaritySwitch} + * @see {@link IInnerSwitch} + */ + protected JavaSimilaritySwitch(ISimilarityRequestHandler srh, Collection> switches) { + super(srh, switches); + } + + /** + * Variation of + * {@link #JavaSimilaritySwitch(ISimilarityRequestHandler, boolean)} that + * constructs an instance with the given switches. + * + * @see {@link AbstractComposedSimilaritySwitch} + * @see {@link IInnerSwitch} + */ + protected JavaSimilaritySwitch(ISimilarityRequestHandler srh, Switch[] switches) { + super(srh, switches); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/JavaSimilarityToolboxBuilder.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/JavaSimilarityToolboxBuilder.java new file mode 100644 index 0000000000..cd454f1bab --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/JavaSimilarityToolboxBuilder.java @@ -0,0 +1,114 @@ +package org.splevo.jamopp.diffing.similarity; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.regex.Pattern; + +import org.splevo.jamopp.diffing.similarity.base.AbstractSimilarityToolboxBuilder; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; +import org.splevo.jamopp.diffing.similarity.base.ecore.MultipleSimilarityCheckHandler; +import org.splevo.jamopp.diffing.similarity.base.ecore.MultipleSimilarityCheckRequest; +import org.splevo.jamopp.diffing.similarity.base.ecore.SingleSimilarityCheckHandler; +import org.splevo.jamopp.diffing.similarity.base.ecore.SingleSimilarityCheckRequest; +import org.splevo.jamopp.diffing.similarity.handlers.ClassifierNormalizationHandler; +import org.splevo.jamopp.diffing.similarity.handlers.CompilationUnitNormalizationHandler; +import org.splevo.jamopp.diffing.similarity.handlers.NamespaceCheckHandler; +import org.splevo.jamopp.diffing.similarity.handlers.NamespaceNormalizationHandler; +import org.splevo.jamopp.diffing.similarity.handlers.NewSimilaritySwitchHandler; +import org.splevo.jamopp.diffing.similarity.handlers.PackageNormalizationHandler; +import org.splevo.jamopp.diffing.similarity.requests.ClassifierNormalizationRequest; +import org.splevo.jamopp.diffing.similarity.requests.NamespaceCheckRequest; +import org.splevo.jamopp.diffing.similarity.requests.CompilationUnitNormalizationRequest; +import org.splevo.jamopp.diffing.similarity.requests.NamespaceNormalizationRequest; +import org.splevo.jamopp.diffing.similarity.requests.NewSimilaritySwitchRequest; +import org.splevo.jamopp.diffing.similarity.requests.PackageNormalizationRequest; + +/** + * Concrete implementation of {@link AbstractSimilarityToolboxBuilder} for + * constructing {@link ISimilarityToolbox} instances for computing similarity of + * Java model elements. + * + * @author atora + */ +public class JavaSimilarityToolboxBuilder extends AbstractSimilarityToolboxBuilder { + @Override + public JavaSimilarityToolboxBuilder instantiate() { + return (JavaSimilarityToolboxBuilder) super.instantiate(); + } + + @Override + public JavaSimilarityToolboxBuilder buildRequestHandlerPair(Class req, + ISimilarityRequestHandler srh) { + return (JavaSimilarityToolboxBuilder) super.buildRequestHandlerPair(req, srh); + } + + /** + * Adds the handlers needed to handle normalisation related + * {@link ISimilarityRequest} instances. Passes the given parameters to their + * corresponding handlers. + * + * @return this + * @see {@link NormalizationUtil} + */ + public JavaSimilarityToolboxBuilder buildNormalizationHandlers(Map classifierNormalizations, + Map compilationUnitNormalizations, Map packageNormalizations) { + + this.buildRequestHandlerPair(ClassifierNormalizationRequest.class, + new ClassifierNormalizationHandler(classifierNormalizations)); + this.buildRequestHandlerPair(CompilationUnitNormalizationRequest.class, + new CompilationUnitNormalizationHandler(compilationUnitNormalizations)); + this.buildRequestHandlerPair(PackageNormalizationRequest.class, + new PackageNormalizationHandler(packageNormalizations)); + this.buildRequestHandlerPair(NamespaceNormalizationRequest.class, + new NamespaceNormalizationHandler(packageNormalizations)); + + return this; + } + + /** + * Adds the handlers needed to handle normalisation related + * {@link ISimilarityRequest} instances. Does so without any normalisation + * parameters. + * + * @return this + * @see {@link #buildNormalizationHandlers(Map, Map, Map)} + */ + public JavaSimilarityToolboxBuilder buildNormalizationHandlers() { + var classifierNormalizations = new LinkedHashMap(); + var compilationUnitNormalizations = new LinkedHashMap(); + var packageNormalizations = new LinkedHashMap(); + + return this.buildNormalizationHandlers(classifierNormalizations, compilationUnitNormalizations, + packageNormalizations); + } + + /** + * Adds the handlers required to handle similarity checking related + * {@link ISimilarityRequest} instances. + * + * @return this + */ + public JavaSimilarityToolboxBuilder buildComparisonHandlers() { + this.buildRequestHandlerPair(SingleSimilarityCheckRequest.class, new SingleSimilarityCheckHandler()); + this.buildRequestHandlerPair(MultipleSimilarityCheckRequest.class, + new MultipleSimilarityCheckHandler(this.getCurrentToolbox())); + this.buildRequestHandlerPair(NamespaceCheckRequest.class, new NamespaceCheckHandler()); + + return this; + } + + /** + * Adds the handler needed to handle {@link ISimilarityRequest} instances, which + * request new similarity switch instances. + * + * @return this + * @see {@link IJavaSimilaritySwitch} + */ + public JavaSimilarityToolboxBuilder buildNewSimilaritySwitchHandler() { + this.buildRequestHandlerPair(NewSimilaritySwitchRequest.class, + new NewSimilaritySwitchHandler(this.getCurrentToolbox())); + + return this; + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/SimilarityChecker.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/SimilarityChecker.java deleted file mode 100644 index dfcd2d159a..0000000000 --- a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/SimilarityChecker.java +++ /dev/null @@ -1,205 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Benjamin Klatt - initial API and implementation and/or initial documentation - * Martin Armbruster - enable change of default behavior for statement position check. - *******************************************************************************/ -package org.splevo.jamopp.diffing.similarity; - -import java.util.LinkedHashMap; -import java.util.List; -import java.util.regex.Pattern; - -import org.apache.log4j.Logger; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.util.EcoreUtil; - -import com.google.common.collect.Maps; - -/** - * Checker for the similarity of two elements specific for the java application model. - * - * TODO: Check caching for this similarity checker. Would require to pass this to the similarity - * switch as well! - * - */ -public class SimilarityChecker { - - /** The logger for this class. */ - @SuppressWarnings("unused") - private Logger logger = Logger.getLogger(SimilarityChecker.class); - - private LinkedHashMap classifierNormalizations = null; - private LinkedHashMap compilationUnitNormalizations = null; - private LinkedHashMap packageNormalizations = null; - private boolean defaultCheckStatementPositionFlag = true; - - /** - * Constructor to set the required configurations. - * - * @param classifierNormalizations - * A list of patterns replace any match in a classifier name with the defined - * replacement string. - * @param compilationUnitNormalizations - * A list of patterns replace any match in a compilation unit name with the defined - * replacement string. - * @param packageNormalizations - * The normalizations to replace expressions. - */ - public SimilarityChecker(LinkedHashMap classifierNormalizations, - LinkedHashMap compilationUnitNormalizations, LinkedHashMap packageNormalizations) { - this.classifierNormalizations = classifierNormalizations; - this.compilationUnitNormalizations = compilationUnitNormalizations; - this.packageNormalizations = packageNormalizations; - } - - /** - * Default constructor for a similarity checker without any normalization configurations. - */ - public SimilarityChecker() { - this.classifierNormalizations = Maps.newLinkedHashMap(); - this.compilationUnitNormalizations = Maps.newLinkedHashMap(); - this.packageNormalizations = Maps.newLinkedHashMap(); - } - - /** - * Indicates if the SimilarityChecker instance checks the position of statements in its default behavior. - * - * @return true if the statement positions are checked. false otherwise. - */ - public boolean checksStatementPositionOnDefault() { - return this.defaultCheckStatementPositionFlag; - } - - /** - * Controls if the SimilarityChecker checks the position of statements in the default behavior. - * - * @param check true if the statement positions are checked. false otherwise. - */ - public void setCheckStatementPositionOnDefault(boolean check) { - this.defaultCheckStatementPositionFlag = check; - } - - /** - * Check two object lists if they are similar. - * - * The elements is compared pairwise and it is the responsibility of the provided list - * implementations to return them in an appropriate order by calling get(i) with a increasing - * index i. - * - * @param elements1 - * The first list of elements to check. - * @param elements2 - * The second list of elements to check. - * @return TRUE, if they are all similar; FALSE if a different number of elements is submitted or at least one pair of elements is not similar to each other. - */ - public Boolean areSimilar(final List elements1, final List elements2) { - if (elements1.size() != elements2.size()) { - return Boolean.FALSE; - } - for (int i = 0; i < elements1.size(); i++) { - Boolean childSimilarity = isSimilar(elements1.get(i), elements2.get(i)); - if (childSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - } - - return Boolean.TRUE; - } - - /** - * Check two objects if they are similar. - * - * @param element1 - * The first element to check. - * @param element2 - * The second element to check. - * @return TRUE, if they are similar; FALSE if not, NULL if it can't be decided. - */ - public Boolean isSimilar(final EObject element1, final EObject element2) { - return isSimilar(element1, element2, this.defaultCheckStatementPositionFlag); - } - - /** - * Check two objects if they are similar. - * - * @param element1 - * The first element to check. - * @param element2 - * The second element to check. - * @param checkStatementPosition - * Flag if the position of statement elements should be considered or not. - * @return TRUE, if they are similar; FALSE if not, NULL if it can't be decided. - */ - public Boolean isSimilar(EObject element1, EObject element2, boolean checkStatementPosition) { - - // check that either both or none of them is null - if (element1 == element2) { - return Boolean.TRUE; - } - - if (onlyOneIsNull(element1, element2)) { - return Boolean.FALSE; - } - - // if a proxy is present try to resolve it - // the other element is used as a context. - // TODO Clarify why it can happen that one proxy is resolved and the other is not - // further notes available with the issue - // https://sdqbuild.ipd.kit.edu/jira/browse/SPLEVO-279 - if (element2.eIsProxy() && !element1.eIsProxy()) { - element2 = EcoreUtil.resolve(element2, element1); - } else if (element1.eIsProxy() && !element2.eIsProxy()) { - element1 = EcoreUtil.resolve(element1, element2); - } - - // check the elements to be of the same type - if (!element1.getClass().equals(element2.getClass())) { - return Boolean.FALSE; - } - - // check type specific similarity - return this.checkSimilarityForResolvedAndSameType(element1, element2, checkStatementPosition); - } - - /** - * Checks the similarity of two EObjects where both EObjects are resolved and have the same type. - * - * @param element1 the first EObject. - * @param element2 the second EObject. - * @param checkStatementPosition true if the position of statements should be checked. false otherwise. - * If no statements are involved, the flag can be ignored. - * @return true if the EObjects are similar. null if they cannot be compared. false otherwise. - */ - protected Boolean checkSimilarityForResolvedAndSameType(EObject element1, EObject element2, - boolean checkStatementPosition) { - return new SimilaritySwitch(element2, checkStatementPosition, classifierNormalizations, - compilationUnitNormalizations, packageNormalizations).doSwitch(element1); - } - - /** - * Method to check if only one of the provided elements is null. - * - * @param element1 - * The first element. - * @param element2 - * The second element. - * @return True if only one element is null and the other is not. - */ - private Boolean onlyOneIsNull(final EObject element1, final EObject element2) { - Boolean onlyOneIsNull = false; - if (element1 != null && element2 == null) { - onlyOneIsNull = Boolean.TRUE; - } else if (element1 == null && element2 != null) { - onlyOneIsNull = Boolean.TRUE; - } - return onlyOneIsNull; - } - -} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/SimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/SimilaritySwitch.java deleted file mode 100644 index 83b7b6789e..0000000000 --- a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/SimilaritySwitch.java +++ /dev/null @@ -1,1858 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Benjamin Klatt - initial API and implementation and/or initial documentation - * Martin Armbruster - extension for expanded JaMoPP - *******************************************************************************/ -package org.splevo.jamopp.diffing.similarity; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.regex.Pattern; - -import org.apache.log4j.Logger; -import org.eclipse.emf.common.util.EList; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.util.ComposedSwitch; -import org.emftext.commons.layout.util.LayoutSwitch; -import org.emftext.language.java.annotations.AnnotationAttributeSetting; -import org.emftext.language.java.annotations.AnnotationInstance; -import org.emftext.language.java.annotations.util.AnnotationsSwitch; -import org.emftext.language.java.arrays.ArraySelector; -import org.emftext.language.java.arrays.util.ArraysSwitch; -import org.emftext.language.java.classifiers.AnonymousClass; -import org.emftext.language.java.classifiers.Classifier; -import org.emftext.language.java.classifiers.ConcreteClassifier; -import org.emftext.language.java.classifiers.util.ClassifiersSwitch; -import org.emftext.language.java.commons.NamedElement; -import org.emftext.language.java.commons.NamespaceAwareElement; -import org.emftext.language.java.commons.util.CommonsSwitch; -import org.emftext.language.java.containers.CompilationUnit; -import org.emftext.language.java.containers.Package; -import org.emftext.language.java.containers.util.ContainersSwitch; -import org.emftext.language.java.expressions.AdditiveExpression; -import org.emftext.language.java.expressions.AndExpression; -import org.emftext.language.java.expressions.AndExpressionChild; -import org.emftext.language.java.expressions.AssignmentExpression; -import org.emftext.language.java.expressions.AssignmentExpressionChild; -import org.emftext.language.java.expressions.ConditionalAndExpression; -import org.emftext.language.java.expressions.ConditionalAndExpressionChild; -import org.emftext.language.java.expressions.ConditionalOrExpression; -import org.emftext.language.java.expressions.ConditionalOrExpressionChild; -import org.emftext.language.java.expressions.EqualityExpression; -import org.emftext.language.java.expressions.EqualityExpressionChild; -import org.emftext.language.java.expressions.Expression; -import org.emftext.language.java.expressions.InstanceOfExpression; -import org.emftext.language.java.expressions.InstanceOfExpressionChild; -import org.emftext.language.java.expressions.NestedExpression; -import org.emftext.language.java.expressions.RelationExpression; -import org.emftext.language.java.expressions.RelationExpressionChild; -import org.emftext.language.java.expressions.UnaryExpression; -import org.emftext.language.java.expressions.UnaryExpressionChild; -import org.emftext.language.java.expressions.util.ExpressionsSwitch; -import org.emftext.language.java.generics.ExtendsTypeArgument; -import org.emftext.language.java.generics.QualifiedTypeArgument; -import org.emftext.language.java.generics.SuperTypeArgument; -import org.emftext.language.java.generics.TypeParameter; -import org.emftext.language.java.generics.UnknownTypeArgument; -import org.emftext.language.java.generics.util.GenericsSwitch; -import org.emftext.language.java.imports.ClassifierImport; -import org.emftext.language.java.imports.StaticMemberImport; -import org.emftext.language.java.imports.util.ImportsSwitch; -import org.emftext.language.java.instantiations.ExplicitConstructorCall; -import org.emftext.language.java.instantiations.NewConstructorCall; -import org.emftext.language.java.instantiations.util.InstantiationsSwitch; -import org.emftext.language.java.literals.BinaryIntegerLiteral; -import org.emftext.language.java.literals.BinaryLongLiteral; -import org.emftext.language.java.literals.BooleanLiteral; -import org.emftext.language.java.literals.CharacterLiteral; -import org.emftext.language.java.literals.DecimalDoubleLiteral; -import org.emftext.language.java.literals.DecimalFloatLiteral; -import org.emftext.language.java.literals.DecimalIntegerLiteral; -import org.emftext.language.java.literals.DecimalLongLiteral; -import org.emftext.language.java.literals.HexDoubleLiteral; -import org.emftext.language.java.literals.HexFloatLiteral; -import org.emftext.language.java.literals.HexIntegerLiteral; -import org.emftext.language.java.literals.HexLongLiteral; -import org.emftext.language.java.literals.OctalIntegerLiteral; -import org.emftext.language.java.literals.OctalLongLiteral; -import org.emftext.language.java.literals.util.LiteralsSwitch; -import org.emftext.language.java.members.Constructor; -import org.emftext.language.java.members.EnumConstant; -import org.emftext.language.java.members.Member; -import org.emftext.language.java.members.Method; -import org.emftext.language.java.members.util.MembersSwitch; -import org.emftext.language.java.modifiers.util.ModifiersSwitch; -import org.emftext.language.java.modules.AccessProvidingModuleDirective; -import org.emftext.language.java.modules.ModuleReference; -import org.emftext.language.java.modules.ProvidesModuleDirective; -import org.emftext.language.java.modules.RequiresModuleDirective; -import org.emftext.language.java.modules.UsesModuleDirective; -import org.emftext.language.java.modules.util.ModulesSwitch; -import org.emftext.language.java.operators.AssignmentOperator; -import org.emftext.language.java.operators.EqualityOperator; -import org.emftext.language.java.operators.RelationOperator; -import org.emftext.language.java.operators.UnaryOperator; -import org.emftext.language.java.operators.util.OperatorsSwitch; -import org.emftext.language.java.parameters.OrdinaryParameter; -import org.emftext.language.java.parameters.Parameter; -import org.emftext.language.java.parameters.util.ParametersSwitch; -import org.emftext.language.java.references.ElementReference; -import org.emftext.language.java.references.IdentifierReference; -import org.emftext.language.java.references.MethodCall; -import org.emftext.language.java.references.Reference; -import org.emftext.language.java.references.ReferenceableElement; -import org.emftext.language.java.references.StringReference; -import org.emftext.language.java.references.util.ReferencesSwitch; -import org.emftext.language.java.statements.CatchBlock; -import org.emftext.language.java.statements.Conditional; -import org.emftext.language.java.statements.ExpressionStatement; -import org.emftext.language.java.statements.Jump; -import org.emftext.language.java.statements.JumpLabel; -import org.emftext.language.java.statements.LocalVariableStatement; -import org.emftext.language.java.statements.Return; -import org.emftext.language.java.statements.Statement; -import org.emftext.language.java.statements.StatementListContainer; -import org.emftext.language.java.statements.Switch; -import org.emftext.language.java.statements.SynchronizedBlock; -import org.emftext.language.java.statements.Throw; -import org.emftext.language.java.statements.util.StatementsSwitch; -import org.emftext.language.java.types.ClassifierReference; -import org.emftext.language.java.types.InferableType; -import org.emftext.language.java.types.NamespaceClassifierReference; -import org.emftext.language.java.types.PrimitiveType; -import org.emftext.language.java.types.Type; -import org.emftext.language.java.types.TypeReference; -import org.emftext.language.java.types.util.TypesSwitch; -import org.emftext.language.java.variables.AdditionalLocalVariable; -import org.emftext.language.java.variables.Variable; -import org.emftext.language.java.variables.util.VariablesSwitch; -import org.splevo.diffing.util.NormalizationUtil; -import org.splevo.jamopp.diffing.util.JaMoPPModelUtil; -import org.splevo.jamopp.util.JaMoPPElementUtil; - -import com.google.common.base.Strings; - -/** - * Internal switch class to prove element similarity. - * - *

- * The similarity case methods do not need to check for null values. It is assumed that the calling - * class does a null value check for the elements to compare in advanced, such as done by the - * SimilarityChecker class. - *

- * - *

- * Check strategy:
- * First all "not-similar"-criteria are checked. If none hits, true will be returned. - *

- */ -public class SimilaritySwitch extends ComposedSwitch { - - /** The logger for this class. */ - private Logger logger = Logger.getLogger(SimilaritySwitch.class); - - /** The object to compare the switched element with. */ - private EObject compareElement = null; - - /** Internal similarity checker to compare container elements etc. */ - private SimilarityChecker similarityChecker = null; - - /** - * Constructor requiring the element to compare with. - * - * @param compareElement - * The right-side / original element to check the similarity against. - * @param checkStatementPosition - * Flag if the similarity check should consider the position of a statement or not. - * @param classifierNormalizations - * A list of patterns replace any match in a classifier name with the defined - * replacement string. - * @param compilationUnitNormalizations - * A list of patterns replace any match in a compilation unit name with the defined - * replacement string. - * @param packageNormalizations - * A list of package normalization patterns. - */ - public SimilaritySwitch(EObject compareElement, boolean checkStatementPosition, - LinkedHashMap classifierNormalizations, - LinkedHashMap compilationUnitNormalizations, - LinkedHashMap packageNormalizations) { - this.similarityChecker = new SimilarityChecker(classifierNormalizations, compilationUnitNormalizations, - packageNormalizations); - this.similarityChecker.setCheckStatementPositionOnDefault(checkStatementPosition); - this.compareElement = compareElement; - addSwitch(new AnnotationsSimilaritySwitch()); - addSwitch(new ArraysSimilaritySwitch()); - addSwitch(new ClassifiersSimilaritySwitch(classifierNormalizations)); - addSwitch(new CommonsSimilaritySwitch()); - addSwitch(new ContainersSimilaritySwitch(compilationUnitNormalizations, packageNormalizations)); - addSwitch(new ExpressionsSimilaritySwitch()); - addSwitch(new GenericsSimilaritySwitch()); - addSwitch(new ImportsSimilaritySwitch()); - addSwitch(new InstantiationsSimilaritySwitch()); - addSwitch(new LiteralsSimilaritySwitch()); - addSwitch(new MembersSimilaritySwitch()); - addSwitch(new ModifiersSimilaritySwitch()); - addSwitch(new OperatorsSimilaritySwitch()); - addSwitch(new ParametersSimilaritySwitch()); - addSwitch(new ReferencesSimilaritySwitch()); - addSwitch(new StatementsSimilaritySwitch(checkStatementPosition)); - addSwitch(new TypesSimilaritySwitch()); - addSwitch(new VariablesSimilaritySwitch()); - addSwitch(new LayoutSimilaritySwitch()); - addSwitch(new ModulesSimilaritySwitch()); - } - - /** - * Similarity decisions for annotation elements. - */ - private class AnnotationsSimilaritySwitch extends AnnotationsSwitch { - - @Override - public Boolean caseAnnotationInstance(AnnotationInstance instance1) { - AnnotationInstance instance2 = (AnnotationInstance) compareElement; - - Classifier class1 = instance1.getAnnotation(); - Classifier class2 = instance2.getAnnotation(); - Boolean classifierSimilarity = similarityChecker.isSimilar(class1, class2); - if (classifierSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - String namespace1 = instance1.getNamespacesAsString(); - String namespace2 = instance2.getNamespacesAsString(); - if (namespace1 == null) { - return (namespace2 == null); - } else { - return (namespace1.equals(namespace2)); - } - } - - @Override - public Boolean caseAnnotationAttributeSetting(AnnotationAttributeSetting setting1) { - AnnotationAttributeSetting setting2 = (AnnotationAttributeSetting) compareElement; - Boolean similarity = similarityChecker.isSimilar(setting1.getAttribute(), setting2.getAttribute()); - if (similarity == Boolean.FALSE) { - return Boolean.FALSE; - } - return Boolean.TRUE; - } - - @Override - public Boolean defaultCase(EObject object) { - return Boolean.TRUE; - } - } - - /** - * Similarity decision for array elements. - *

- * All array elements are strongly typed. They have no identifying attributes. Their location - * and runtime type are assumed to be checked before this switch is called. So nothing to check - * here. - */ - private class ArraysSimilaritySwitch extends ArraysSwitch { - @Override - public Boolean defaultCase(EObject object) { - return Boolean.TRUE; - } - } - - /** - * Similarity decisions for classifier elements. - */ - private class ClassifiersSimilaritySwitch extends ClassifiersSwitch { - - /** - * A list of patterns replace any match in a classifier name with the defined replacement - * string. - */ - private Map classifierNormalizationPatterns = null; - - /** - * Constructor to set the required configurations. - * - * @param classifierNormalizationPatterns - * A list of patterns replace any match in a classifier name with the defined - * replacement string. - */ - public ClassifiersSimilaritySwitch(Map classifierNormalizationPatterns) { - this.classifierNormalizationPatterns = classifierNormalizationPatterns; - } - - /** - * Concrete classifiers such as classes and interface are identified by their location and - * name. The location is considered implicitly. - * - * @param classifier1 - * the classifier to compare with the compareelement - * @return True or false whether they are similar or not. - */ - @Override - public Boolean caseConcreteClassifier(ConcreteClassifier classifier1) { - - ConcreteClassifier classifier2 = (ConcreteClassifier) compareElement; - - String name1 = NormalizationUtil.normalize(classifier1.getQualifiedName(), classifierNormalizationPatterns); - String name2 = Strings.nullToEmpty(classifier2.getQualifiedName()); - - return (name1.equals(name2)); - } - - /** - * Anonymous classes are considered to be similar. - * - * @param anon the anonymous class to compare with the compare element. - * @return true. - */ - @Override - public Boolean caseAnonymousClass(AnonymousClass anon) { - return Boolean.TRUE; - } - - } - - /** - * Similarity decisions for commons elements. - */ - private class CommonsSimilaritySwitch extends CommonsSwitch { - - /** - * Check named element - * - * Similarity is defined by the names of the elements. - * - * @param element1 - * The method call to compare with the compare element. - * @return True As null always means null. - */ - @Override - public Boolean caseNamedElement(NamedElement element1) { - NamedElement element2 = (NamedElement) compareElement; - - if (element1.getName() == null) { - return (element2.getName() == null); - } - - return (element1.getName().equals(element2.getName())); - } - } - - /** - * Similarity decisions for container elements. - */ - private class ContainersSimilaritySwitch extends ContainersSwitch { - - private LinkedHashMap compilationUnitNormalizations = null; - - private LinkedHashMap packageNormalizations = null; - - /** - * Constructor to set the required configurations. - * - * @param compilationUnitNormalizations - * A list of patterns replace any match in a classifier name with the defined - * replacement string. - * @param packageNormalizations - * A list of package normalization patterns. - */ - public ContainersSimilaritySwitch(LinkedHashMap compilationUnitNormalizations, - LinkedHashMap packageNormalizations) { - this.compilationUnitNormalizations = compilationUnitNormalizations; - this.packageNormalizations = packageNormalizations; - } - - /** - * Check the similarity of two CompilationUnits.
- * Similarity is checked by - *

    - *
  • Comparing their names (including renamings)
  • - *
  • Comparing their namespaces' values (including renamings)
  • - *
- * Note: CompilationUnit names are full qualified. So it is important to apply classifier as - * well as package renaming normalizations to them. - * - * @param unit1 - * The compilation unit to compare with the compareElement. - * @return True/False whether they are similar or not. - */ - @Override - public Boolean caseCompilationUnit(CompilationUnit unit1) { - - CompilationUnit unit2 = (CompilationUnit) compareElement; - - String name1 = NormalizationUtil.normalize(unit1.getName(), compilationUnitNormalizations); - name1 = NormalizationUtil.normalize(name1, packageNormalizations); - String name2 = unit2.getName(); - if (!name1.equals(name2)) { - return Boolean.FALSE; - } - - String namespaceString1 = NormalizationUtil.normalizeNamespace(unit1.getNamespacesAsString(), - packageNormalizations); - String namespaceString2 = Strings.nullToEmpty(unit2.getNamespacesAsString()); - if (!namespaceString1.equals(namespaceString2)) { - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - - /** - * Check package similarity.
- * Similarity is checked by - *
    - *
  • full qualified package path
  • - *
- * - * @param package1 - * The package to compare with the compare element. - * @return True/False if the packages are similar or not. - */ - @Override - public Boolean casePackage(Package package1) { - Package package2 = (Package) compareElement; - - String packagePath1 = JaMoPPModelUtil.buildNamespacePath(package1); - packagePath1 = NormalizationUtil.normalizeNamespace(packagePath1, packageNormalizations); - String packagePath2 = JaMoPPModelUtil.buildNamespacePath(package2); - if (!packagePath1.equals(packagePath2)) { - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - - /** - * Check module similarity.
- * Similarity is checked by - *
    - *
  • module names
  • - *
- * - * @param module1 The module to compare with the compare element. - * @return True/False if the modules are similar or not. - */ - @Override - public Boolean caseModule(org.emftext.language.java.containers.Module module1) { - org.emftext.language.java.containers.Module module2 = - (org.emftext.language.java.containers.Module) compareElement; - if (!module1.getName().equals(module2.getName())) { - return Boolean.FALSE; - } - return Boolean.TRUE; - } - } - - /** - * Similarity decisions for expression elements. - *

- * All expression elements are strong typed with no identifying attributes or non-containment - * references. Their location and runtime types are assumed to be checked before this switch is - * called. - *

- */ - private class ExpressionsSimilaritySwitch extends ExpressionsSwitch { - - @Override - public Boolean caseAssignmentExpression(AssignmentExpression exp1) { - - AssignmentExpression exp2 = (AssignmentExpression) compareElement; - - AssignmentExpressionChild child1 = exp1.getChild(); - AssignmentExpressionChild child2 = exp2.getChild(); - Boolean childSimilarity = similarityChecker.isSimilar(child1, child2); - if (childSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - AssignmentOperator op1 = exp1.getAssignmentOperator(); - AssignmentOperator op2 = exp2.getAssignmentOperator(); - Boolean operatorSimilarity = similarityChecker.isSimilar(op1, op2); - if (operatorSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - Expression value1 = exp1.getValue(); - Expression value2 = exp2.getValue(); - Boolean valueSimilarity = similarityChecker.isSimilar(value1, value2); - if (valueSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - - @Override - public Boolean caseEqualityExpression(EqualityExpression exp1) { - EqualityExpression exp2 = (EqualityExpression) compareElement; - - // check operator equality - EList operators1 = exp1.getEqualityOperators(); - EList operators2 = exp2.getEqualityOperators(); - Boolean operatorSimilarity = similarityChecker.areSimilar(operators1, operators2); - if (operatorSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - // check expression equality - EList children1 = exp1.getChildren(); - EList children2 = exp2.getChildren(); - Boolean childSimilarity = similarityChecker.areSimilar(children1, children2); - if (childSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - - @Override - public Boolean caseRelationExpression(RelationExpression exp1) { - - RelationExpression exp2 = (RelationExpression) compareElement; - - // check operator equality - EList operators1 = exp1.getRelationOperators(); - EList operators2 = exp2.getRelationOperators(); - Boolean operatorSimilarity = similarityChecker.areSimilar(operators1, operators2); - if (operatorSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - // check expression equality - EList children1 = exp1.getChildren(); - EList children2 = exp2.getChildren(); - Boolean childSimilarity = similarityChecker.areSimilar(children1, children2); - if (childSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - - @Override - public Boolean caseAndExpression(AndExpression exp1) { - - AndExpression exp2 = (AndExpression) compareElement; - - // check expression equality - EList children1 = exp1.getChildren(); - EList children2 = exp2.getChildren(); - Boolean childSimilarity = similarityChecker.areSimilar(children1, children2); - if (childSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - - @Override - public Boolean caseUnaryExpression(UnaryExpression exp1) { - - UnaryExpression exp2 = (UnaryExpression) compareElement; - - // check operator equality - EList operators1 = exp1.getOperators(); - EList operators2 = exp2.getOperators(); - Boolean operatorSimilarity = similarityChecker.areSimilar(operators1, operators2); - if (operatorSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - // check expression equality - UnaryExpressionChild child1 = exp1.getChild(); - UnaryExpressionChild child2 = exp2.getChild(); - return similarityChecker.isSimilar(child1, child2); - } - - @Override - public Boolean caseAdditiveExpression(AdditiveExpression exp1) { - - AdditiveExpression exp2 = (AdditiveExpression) compareElement; - - Boolean opSimilarity = similarityChecker.areSimilar(exp1.getAdditiveOperators(), exp2.getAdditiveOperators()); - if (opSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - return similarityChecker.areSimilar(exp1.getChildren(), exp2.getChildren()); - } - - @Override - public Boolean caseInstanceOfExpression(InstanceOfExpression exp1) { - - InstanceOfExpression exp2 = (InstanceOfExpression) compareElement; - - // check type equality - TypeReference typeReference1 = exp1.getTypeReference(); - TypeReference typeReference2 = exp2.getTypeReference(); - Boolean typeSimilarity = similarityChecker.isSimilar(typeReference1, typeReference2); - if (typeSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - // check expression equality - InstanceOfExpressionChild child1 = exp1.getChild(); - InstanceOfExpressionChild child2 = exp2.getChild(); - return similarityChecker.isSimilar(child1, child2); - } - - @Override - public Boolean caseConditionalOrExpression(ConditionalOrExpression exp1) { - - ConditionalOrExpression exp2 = (ConditionalOrExpression) compareElement; - - // check expression equality - EList children1 = exp1.getChildren(); - EList children2 = exp2.getChildren(); - return similarityChecker.areSimilar(children1, children2); - } - - @Override - public Boolean caseConditionalAndExpression(ConditionalAndExpression exp1) { - - ConditionalAndExpression exp2 = (ConditionalAndExpression) compareElement; - - // check expression equality - EList children1 = exp1.getChildren(); - EList children2 = exp2.getChildren(); - return similarityChecker.areSimilar(children1, children2); - } - - @Override - public Boolean caseNestedExpression(NestedExpression exp1) { - - NestedExpression exp2 = (NestedExpression) compareElement; - - // check expression equality - Expression childExp1 = exp1.getExpression(); - Expression childExp2 = exp2.getExpression(); - return similarityChecker.isSimilar(childExp1, childExp2); - } - - @Override - public Boolean defaultCase(EObject object) { - return Boolean.TRUE; - } - } - - /** - * Similarity decisions for the generic elements. - */ - private class GenericsSimilaritySwitch extends GenericsSwitch { - @Override - public Boolean caseQualifiedTypeArgument(QualifiedTypeArgument qta1) { - QualifiedTypeArgument qta2 = (QualifiedTypeArgument) compareElement; - return similarityChecker.isSimilar(qta1.getTypeReference(), qta2.getTypeReference()); - } - - @Override - public Boolean caseSuperTypeArgument(SuperTypeArgument sta1) { - SuperTypeArgument sta2 = (SuperTypeArgument) compareElement; - return similarityChecker.isSimilar(sta1.getSuperType(), sta2.getSuperType()); - } - - @Override - public Boolean caseExtendsTypeArgument(ExtendsTypeArgument eta1) { - ExtendsTypeArgument eta2 = (ExtendsTypeArgument) compareElement; - return similarityChecker.isSimilar(eta1.getExtendType(), eta2.getExtendType()); - } - - @Override - public Boolean caseUnknownTypeArgument(UnknownTypeArgument arg) { - return Boolean.TRUE; - } - - @Override - public Boolean caseTypeParameter(TypeParameter param1) { - TypeParameter param2 = (TypeParameter) compareElement; - - if (!param1.getName().equals(param2.getName())) { - return Boolean.FALSE; - } - - return similarityChecker.areSimilar(param1.getExtendTypes(), param2.getExtendTypes()); - } - } - - /** - * Similarity decisions for the import elements. - */ - private class ImportsSimilaritySwitch extends ImportsSwitch { - - @Override - public Boolean caseClassifierImport(ClassifierImport import1) { - - ClassifierImport import2 = (ClassifierImport) compareElement; - - Boolean similarity = similarityChecker.isSimilar(import1.getClassifier(), import2.getClassifier()); - if (similarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - String namespace1 = Strings.nullToEmpty(import1.getNamespacesAsString()); - String namespace2 = Strings.nullToEmpty(import2.getNamespacesAsString()); - return (namespace1.equals(namespace2)); - } - - @Override - public Boolean caseStaticMemberImport(StaticMemberImport import1) { - - StaticMemberImport import2 = (StaticMemberImport) compareElement; - - if (import1.getStaticMembers().size() != import2.getStaticMembers().size()) { - return Boolean.FALSE; - } - for (int i = 0; i < import1.getStaticMembers().size(); i++) { - ReferenceableElement member1 = import1.getStaticMembers().get(i); - ReferenceableElement member2 = import2.getStaticMembers().get(i); - Boolean similarity = similarityChecker.isSimilar(member1, member2); - if (similarity == Boolean.FALSE) { - return Boolean.FALSE; - } - } - - String namespace1 = Strings.nullToEmpty(import1.getNamespacesAsString()); - String namespace2 = Strings.nullToEmpty(import2.getNamespacesAsString()); - return (namespace1.equals(namespace2)); - } - } - - /** - * Similarity decisions for object instantiation elements. - */ - private class InstantiationsSimilaritySwitch extends InstantiationsSwitch { - - /** - * Check class instance creation similarity.
- * Similarity is checked by - *
    - *
  • instance type similarity
  • - *
  • number of constructor arguments
  • - *
  • types of constructor arguments
  • - *
- * - * @param call1 - * The class instance creation to compare with the compare element. - * @return True/False if the class instance creations are similar or not. - */ - @Override - public Boolean caseExplicitConstructorCall(ExplicitConstructorCall call1) { - - ExplicitConstructorCall call2 = (ExplicitConstructorCall) compareElement; - - // check the class instance types - Boolean typeSimilarity = similarityChecker.isSimilar(call1.getCallTarget(), call2.getCallTarget()); - if (typeSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - // check number of type arguments - EList cic1Args = call1.getArguments(); - EList cic2Args = call2.getArguments(); - if (cic1Args.size() != cic2Args.size()) { - return Boolean.FALSE; - } - - // check the argument similarity - for (int i = 0; i < cic1Args.size(); i++) { - Boolean argumentSimilarity = similarityChecker.isSimilar(cic1Args.get(i), cic2Args.get(i)); - if (argumentSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - } - - return Boolean.TRUE; - } - - @Override - public Boolean caseNewConstructorCall(NewConstructorCall call1) { - NewConstructorCall call2 = (NewConstructorCall) compareElement; - - Type type1 = call1.getTypeReference().getTarget(); - Type type2 = call2.getTypeReference().getTarget(); - Boolean typeSimilarity = similarityChecker.isSimilar(type1, type2); - if (typeSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - EList types1 = call1.getArguments(); - EList types2 = call2.getArguments(); - if (types1.size() != types2.size()) { - return Boolean.FALSE; - } - for (int i = 0; i < types1.size(); i++) { - Expression argType1 = types1.get(i); - Expression argType2 = types2.get(i); - Boolean similarity = similarityChecker.isSimilar(argType1, argType2); - if (similarity == Boolean.FALSE) { - return Boolean.FALSE; - } - } - - return Boolean.TRUE; - } - - @Override - public Boolean defaultCase(EObject object) { - return Boolean.TRUE; - } - } - - /** - * Similarity decisions for literal elements. - */ - private class LiteralsSimilaritySwitch extends LiteralsSwitch { - - @Override - public Boolean caseBooleanLiteral(BooleanLiteral boolean1) { - BooleanLiteral boolean2 = (BooleanLiteral) compareElement; - return (boolean1.isValue() == boolean2.isValue()); - } - - @Override - public Boolean caseCharacterLiteral(CharacterLiteral char1) { - CharacterLiteral char2 = (CharacterLiteral) compareElement; - return char1.getValue().equals(char2.getValue()); - } - - @Override - public Boolean caseDecimalFloatLiteral(DecimalFloatLiteral float1) { - DecimalFloatLiteral float2 = (DecimalFloatLiteral) compareElement; - return compareDouble(float1.getDecimalValue(), float2.getDecimalValue()); - } - - @Override - public Boolean caseHexFloatLiteral(HexFloatLiteral float1) { - HexFloatLiteral float2 = (HexFloatLiteral) compareElement; - return compareDouble(float1.getHexValue(), float2.getHexValue()); - } - - @Override - public Boolean caseDecimalDoubleLiteral(DecimalDoubleLiteral double1) { - DecimalDoubleLiteral double2 = (DecimalDoubleLiteral) compareElement; - return compareDouble(double1.getDecimalValue(), double2.getDecimalValue()); - } - - @Override - public Boolean caseHexDoubleLiteral(HexDoubleLiteral double1) { - HexDoubleLiteral double2 = (HexDoubleLiteral) compareElement; - return compareDouble(double1.getHexValue(), double2.getHexValue()); - } - - private boolean compareDouble(double d1, double d2) { - return d1 == d2 || Double.isNaN(d1) && Double.isNaN(d2); - } - - @Override - public Boolean caseDecimalIntegerLiteral(DecimalIntegerLiteral int1) { - DecimalIntegerLiteral int2 = (DecimalIntegerLiteral) compareElement; - return (int1.getDecimalValue().equals(int2.getDecimalValue())); - } - - @Override - public Boolean caseHexIntegerLiteral(HexIntegerLiteral int1) { - HexIntegerLiteral int2 = (HexIntegerLiteral) compareElement; - return (int1.getHexValue().equals(int2.getHexValue())); - } - - @Override - public Boolean caseOctalIntegerLiteral(OctalIntegerLiteral int1) { - OctalIntegerLiteral int2 = (OctalIntegerLiteral) compareElement; - return (int1.getOctalValue().equals(int2.getOctalValue())); - } - - @Override - public Boolean caseDecimalLongLiteral(DecimalLongLiteral long1) { - DecimalLongLiteral long2 = (DecimalLongLiteral) compareElement; - return (long1.getDecimalValue().equals(long2.getDecimalValue())); - } - - @Override - public Boolean caseHexLongLiteral(HexLongLiteral long1) { - HexLongLiteral long2 = (HexLongLiteral) compareElement; - return (long1.getHexValue().equals(long2.getHexValue())); - } - - @Override - public Boolean caseOctalLongLiteral(OctalLongLiteral long1) { - OctalLongLiteral long2 = (OctalLongLiteral) compareElement; - return (long1.getOctalValue().equals(long2.getOctalValue())); - } - - @Override - public Boolean caseBinaryLongLiteral(BinaryLongLiteral long1) { - BinaryLongLiteral long2 = (BinaryLongLiteral) compareElement; - return long1.getBinaryValue().equals(long2.getBinaryValue()); - } - - @Override - public Boolean caseBinaryIntegerLiteral(BinaryIntegerLiteral int1) { - BinaryIntegerLiteral int2 = (BinaryIntegerLiteral) compareElement; - return int1.getBinaryValue().equals(int2.getBinaryValue()); - } - - /** - * Check null literal similarity.
- * - * Null literals are always assumed to be similar. - * - * @param object - * The literal to compare with the compare element. - * @return True As null always means null. - */ - @Override - public Boolean defaultCase(EObject object) { - return Boolean.TRUE; - } - } - - /** - * Similarity decisions for the member elements. - */ - private class MembersSimilaritySwitch extends MembersSwitch { - - /** - * Check abstract method declaration similarity. Similarity is checked by - *
    - *
  • name
  • - *
  • parameter list size
  • - *
  • parameter types
  • - *
  • name
  • - *
  • container for - *
      - *
    • AbstractTypeDeclaration
    • - *
    • AnonymousClassDeclaration
    • - *
    • Model
    • - *
    - *
  • - *
- * - * The container must be checked to check similarity for referenced methods. - * - * - * @param method1 - * The abstract method declaration to compare with the compare element. - * @return True/False if the abstract method declarations are similar or not. - */ - @Override - public Boolean caseMethod(Method method1) { - - Method method2 = (Method) compareElement; - - // if methods have different names they are not similar. - if (!method1.getName().equals(method2.getName())) { - return Boolean.FALSE; - } - - if (method1.getParameters().size() != method2.getParameters().size()) { - return Boolean.FALSE; - } - - for (int i = 0; i < method1.getParameters().size(); i++) { - Parameter param1 = method1.getParameters().get(i); - Parameter param2 = method2.getParameters().get(i); - Type type1 = param1.getTypeReference().getTarget(); - Type type2 = param2.getTypeReference().getTarget(); - Boolean typeSimilarity = similarityChecker.isSimilar(type1, type2); - if (typeSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - if (param1.getTypeReference().getArrayDimension() != param2.getTypeReference().getArrayDimension()) { - return Boolean.FALSE; - } - } - - /* ************************************** - * methods as members of regular classes - */ - if (method1.getContainingConcreteClassifier() != null) { - ConcreteClassifier type1 = method1.getContainingConcreteClassifier(); - ConcreteClassifier type2 = method2.getContainingConcreteClassifier(); - return similarityChecker.isSimilar(type1, type2); - } - - /* ************************************** - * methods as members of anonymous classes - */ - if (method1.getContainingAnonymousClass() != null) { - AnonymousClass type1 = method1.getContainingAnonymousClass(); - AnonymousClass type2 = method2.getContainingAnonymousClass(); - Boolean typeSimilarity = similarityChecker.isSimilar(type1, type2); - if (typeSimilarity != null) { - return typeSimilarity; - } - } - - logger.warn("MethodDeclaration in unknown container: " + method1.getName() + " : " - + method1.eContainer()); - return super.caseMethod(method1); - } - - /** - * Check constuctor declaration similarity. Similarity is checked by - *
    - *
  • name
  • - *
  • parameter list size
  • - *
  • parameter types
  • - *
  • name
  • - *
  • container for - *
      - *
    • AbstractTypeDeclaration
    • - *
    • AnonymousClassDeclaration
    • - *
    • Model
    • - *
    - *
  • - *
- * - * The container must be checked to check similarity for referenced methods. - * - * - * @param constructor1 - * The abstract method declaration to compare with the compare element. - * @return True/False if the abstract method declarations are similar or not. - */ - @Override - public Boolean caseConstructor(Constructor constructor1) { - - Constructor constructor2 = (Constructor) compareElement; - - // if methods have different names they are not similar. - if (!constructor1.getName().equals(constructor2.getName())) { - return Boolean.FALSE; - } - - EList params1 = constructor1.getParameters(); - EList params2 = constructor2.getParameters(); - Boolean parameterSimilarity = similarityChecker.areSimilar(params1, params2); - if (parameterSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - /* ************************************** - * methods as members of regular classes - */ - if (constructor1.getContainingConcreteClassifier() != null) { - ConcreteClassifier type1 = constructor1.getContainingConcreteClassifier(); - ConcreteClassifier type2 = constructor2.getContainingConcreteClassifier(); - return similarityChecker.isSimilar(type1, type2); - } - - /* ************************************** - * methods as members of anonymous classes - */ - if (constructor1.getContainingAnonymousClass() != null) { - AnonymousClass type1 = constructor1.getContainingAnonymousClass(); - AnonymousClass type2 = constructor2.getContainingAnonymousClass(); - Boolean typeSimilarity = similarityChecker.isSimilar(type1, type2); - if (typeSimilarity != null) { - return typeSimilarity; - } - } - - logger.warn("ConstructorDeclaration in unknown container: " + constructor1.getName() + " : " - + constructor1.eContainer().getClass().getSimpleName()); - return super.caseConstructor(constructor1); - } - - @Override - public Boolean caseEnumConstant(EnumConstant const1) { - EnumConstant const2 = (EnumConstant) compareElement; - String name1 = Strings.nullToEmpty(const1.getName()); - String name2 = Strings.nullToEmpty(const2.getName()); - return (name1.equals(name2)); - } - - @Override - public Boolean caseMember(Member member1) { - Member member2 = (Member) compareElement; - String name1 = Strings.nullToEmpty(member1.getName()); - String name2 = Strings.nullToEmpty(member2.getName()); - return (name1.equals(name2)); - } - } - - /** - * Similarity decisions for modifier elements. - *

- * All modifier elements are strong typed with no identifying attributes or non-containment - * references. Their location and runtime types are assumed to be checked before this switch is - * called. - *

- */ - private class ModifiersSimilaritySwitch extends ModifiersSwitch { - @Override - public Boolean defaultCase(EObject object) { - return Boolean.TRUE; - } - } - - /** - * Similarity decisions for operator elements. - *

- * All operator elements are strong typed with no identifying attributes or non-containment - * references. Their location and runtime types are assumed to be checked before this switch is - * called. - *

- */ - private class OperatorsSimilaritySwitch extends OperatorsSwitch { - @Override - public Boolean defaultCase(EObject object) { - return Boolean.TRUE; - } - } - - /** - * Similarity decisions for parameter elements. - *

- * Parameters are variables and for this named elements. So their names must be checked but no - * more identifying attributes or references exist. - *

- */ - private class ParametersSimilaritySwitch extends ParametersSwitch { - @Override - public Boolean caseParameter(Parameter param1) { - Parameter param2 = (Parameter) compareElement; - String name1 = Strings.nullToEmpty(param1.getName()); - String name2 = Strings.nullToEmpty(param2.getName()); - return (name1.equals(name2)); - } - } - - /** - * Similarity decisions for reference elements. - */ - private class ReferencesSimilaritySwitch extends ReferencesSwitch { - - @Override - public Boolean caseStringReference(StringReference ref1) { - - StringReference ref2 = (StringReference) compareElement; - if (ref1.getValue() == null) { - return (ref2.getValue() == null); - } - - return (ref1.getValue().equals(ref2.getValue())); - } - - @Override - public Boolean caseIdentifierReference(IdentifierReference ref1) { - - IdentifierReference ref2 = (IdentifierReference) compareElement; - ReferenceableElement target1 = ref1.getTarget(); - ReferenceableElement target2 = ref2.getTarget(); - - // target identity similarity - Boolean similarity = similarityChecker.isSimilar(target1, target2); - if (similarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - if (target1 != null) { - // target container similarity - // check this only if the reference target is located - // in another container than the reference itself. - // Otherwise such a situation would lead to endless loops - // e.g. for for "(Iterator i = c.iterator(); i.hasNext(); ) {" - // Attention: The reference could be encapsulated by an expression! - EObject ref1Container = JaMoPPElementUtil.getFirstContainerNotOfGivenType(ref1, Expression.class, - ArraySelector.class); - EObject ref2Container = JaMoPPElementUtil.getFirstContainerNotOfGivenType(ref2, Expression.class, - ArraySelector.class); - EObject target1Container = target1.eContainer(); - EObject target2Container = target2.eContainer(); - if (target1Container != ref1Container && target2Container != ref2Container - && target1Container != ref1 && target2Container != ref2) { - Boolean containerSimilarity = similarityChecker.isSimilar(target1Container, target2Container); - if (containerSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - } - } - - if (ref1.getArraySelectors().size() != ref2.getArraySelectors().size()) { - return Boolean.FALSE; - } - for (int i = 0; i < ref1.getArraySelectors().size(); i++) { - ArraySelector selector1 = ref1.getArraySelectors().get(i); - ArraySelector selector2 = ref2.getArraySelectors().get(i); - Boolean positionSimilarity = similarityChecker.isSimilar(selector1.getPosition(), - selector2.getPosition()); - if (positionSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - } - - Reference next1 = ref1.getNext(); - Reference next2 = ref2.getNext(); - Boolean nextSimilarity = similarityChecker.isSimilar(next1, next2); - if (nextSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - - /** - * Check element reference similarity.
- * - * Is checked by the target (the method called). Everything else are containment references - * checked indirectly. - * - * @param ref1 - * The method call to compare with the compare element. - * @return True As null always means null. - */ - @Override - public Boolean caseElementReference(ElementReference ref1) { - ElementReference ref2 = (ElementReference) compareElement; - - Boolean targetSimilarity = similarityChecker.isSimilar(ref1.getTarget(), ref2.getTarget()); - if (targetSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - - /** - * Proof method call similarity. - * - * Similarity is decided by the method referenced and the arguments passed by. - * - * @param call1 - * The left / modified method call to compare with the original one. - * @return True/False if the method calls are similar or not. - */ - @Override - public Boolean caseMethodCall(MethodCall call1) { - MethodCall call2 = (MethodCall) compareElement; - - Boolean targetSimilarity = similarityChecker.isSimilar(call1.getTarget(), call2.getTarget()); - if (targetSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - if (call1.getArguments().size() != call2.getArguments().size()) { - return Boolean.FALSE; - } - - for (int i = 0; i < call1.getArguments().size(); i++) { - Expression exp1 = call1.getArguments().get(i); - Expression exp2 = call2.getArguments().get(i); - Boolean argSimilarity = similarityChecker.isSimilar(exp1, exp2); - if (argSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - } - - Boolean nextSimilarity = similarityChecker.isSimilar(call1.getNext(), call2.getNext()); - if (nextSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - - @Override - public Boolean defaultCase(EObject object) { - return Boolean.TRUE; - } - } - - /** - * Similarity decisions for the statement elements. - */ - private class StatementsSimilaritySwitch extends StatementsSwitch { - - /** - * Flag if the position of a statement should be considered for similarity or not. - */ - private boolean checkStatementPosition = true; - - /** - * Constructor to set required configurations. - * - * @param checkStatementPosition - * Flag if the position of a statement should be considered for similarity or - * not. - */ - public StatementsSimilaritySwitch(boolean checkStatementPosition) { - this.checkStatementPosition = checkStatementPosition; - } - - /** - * Check expression statement similarity.
- * Similarity is checked by - *
    - *
  • similarity statements expressions
  • - *
- * - * @param statement1 - * The expression statement to compare with the compare element. - * @return True/False if the expression statements are similar or not. - */ - @Override - public Boolean caseExpressionStatement(ExpressionStatement statement1) { - - ExpressionStatement statement2 = (ExpressionStatement) compareElement; - - Expression exp1 = statement1.getExpression(); - Expression exp2 = statement2.getExpression(); - - Boolean expSimilarity = similarityChecker.isSimilar(exp1, exp2); - if (expSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - // check predecessor similarity - if (checkStatementPosition) { - if (differentPredecessor(statement1, statement2) && differentSuccessor(statement1, statement2)) { - return Boolean.FALSE; - } - } - - return Boolean.TRUE; - } - - /** - * Check the similarity of a variable declaration. - * - * The similarity is decided by the declared variables name only. A changed variable type or - * value initialization should lead to a changed statement not a new one. - * - * @param varStmt1 - * The variable to compare with the original / right-side one - * @return True/False if they are similar or not. - */ - @Override - public Boolean caseLocalVariableStatement(LocalVariableStatement varStmt1) { - LocalVariableStatement varStmt2 = (LocalVariableStatement) compareElement; - - Variable var1 = varStmt1.getVariable(); - Variable var2 = varStmt2.getVariable(); - Boolean varSimilarity = similarityChecker.isSimilar(var1, var2); - if (varSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - if (checkStatementPosition) { - varSimilarity = similarityChecker.isSimilar(varStmt1.eContainer(), varStmt2.eContainer(), false); - if (!varSimilarity) { - return Boolean.FALSE; - } - if (differentPredecessor(varStmt1, varStmt2) && differentSuccessor(varStmt1, varStmt2)) { - return Boolean.FALSE; - } - } - - return Boolean.TRUE; - } - - /** - * Check return statement similarity.
- * Similarity is checked by - *
    - *
  • expressions similarity
  • - *
- * - * @param returnStatement1 - * The return statement to compare with the compare element. - * @return True/False if the return statements are similar or not. - */ - @Override - public Boolean caseReturn(Return returnStatement1) { - - Return returnStatement2 = (Return) compareElement; - - Expression exp1 = returnStatement1.getReturnValue(); - Expression exp2 = returnStatement2.getReturnValue(); - - return similarityChecker.isSimilar(exp1, exp2); - } - - /** - * Check synchronized statement similarity.
- * Similarity is checked by - *
    - *
  • expression similarity
  • - *
- * - * @param statement1 - * The synchronized statement to compare with the compare element. - * @return True/False if the synchronized statements are similar or not. - */ - @Override - public Boolean caseSynchronizedBlock(SynchronizedBlock statement1) { - - SynchronizedBlock statement2 = (SynchronizedBlock) compareElement; - - Expression exp1 = statement1.getLockProvider(); - Expression exp2 = statement2.getLockProvider(); - Boolean similarity = similarityChecker.isSimilar(exp1, exp2); - if (similarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - if (checkStatementPosition) { - if (differentPredecessor(statement1, statement2) && differentSuccessor(statement1, statement2)) { - return Boolean.FALSE; - } - } - return Boolean.TRUE; - } - - /** - * Check throw statement similarity.
- * - * Only one throw statement can exist at the same code location. As a result the container - * similarity checked implicitly is enough for this. - * - * @param throwStatement1 - * The throw statement to compare with the compare element. - * @return True/False if the throw statements are similar or not. - */ - @Override - public Boolean caseThrow(Throw throwStatement1) { - return Boolean.TRUE; - } - - @Override - public Boolean caseCatchBlock(CatchBlock catchBlock1) { - - CatchBlock catchBlock2 = (CatchBlock) compareElement; - - OrdinaryParameter catchedException1 = catchBlock1.getParameter(); - OrdinaryParameter catchedException2 = catchBlock2.getParameter(); - - Boolean exceptionSimilarity = similarityChecker.isSimilar(catchedException1, catchedException2); - if (exceptionSimilarity == Boolean.FALSE) { - return exceptionSimilarity; - } - - return Boolean.TRUE; - } - - /** - * Check if two conditional statements are similar. - * - * Similarity is checked by: - *
    - *
  • similarity of the expressions
  • - *
- * - * The then and else statements are not checked as part of the condition statement check - * because this is only about the container if statement similarity. The contained - * statements are checked in a separate step of the compare process if the enclosing - * condition statement matches. - * - * @param conditional1 - * The statement to compare with the compare element. - * @return True/False whether they are similar or not. - */ - @Override - public Boolean caseConditional(Conditional conditional1) { - - Conditional conditional2 = (Conditional) compareElement; - - Expression expression1 = conditional1.getCondition(); - Expression expression2 = conditional2.getCondition(); - Boolean expressionSimilarity = similarityChecker.isSimilar(expression1, expression2); - if (expressionSimilarity == Boolean.FALSE) { - return expressionSimilarity; - } - - return Boolean.TRUE; - } - - @Override - public Boolean caseJump(Jump jump1) { - Jump jump2 = (Jump) compareElement; - - Boolean similarity = similarityChecker.isSimilar(jump1.getTarget(), jump2.getTarget()); - if (similarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - - @Override - public Boolean caseJumpLabel(JumpLabel label1) { - - JumpLabel label2 = (JumpLabel) compareElement; - - String name1 = Strings.nullToEmpty(label1.getName()); - String name2 = Strings.nullToEmpty(label2.getName()); - - return (name1.equals(name2)); - } - - @Override - public Boolean caseSwitch(Switch switch1) { - Switch switch2 = (Switch) compareElement; - - return similarityChecker.isSimilar(switch1.getVariable(), switch2.getVariable()); - } - - @Override - public Boolean defaultCase(EObject object) { - return Boolean.TRUE; - } - - /** - * Decide of two statements differ from each other or not. - * - * @param statement1 - * The first statement to compare - * @param statement2 - * The second statement to compare. - * @return True if they differ, null if not. - */ - private boolean differentPredecessor(Statement statement1, Statement statement2) { - Statement pred1 = getPredecessor(statement1); - Statement pred2 = getPredecessor(statement2); - Boolean similarity = similarityChecker.isSimilar(pred1, pred2, false); - return similarity == Boolean.FALSE; - } - - /** - * Check if two statements have differing successor statements. - * - * @param statement1 - * The first statement to check. - * @param statement2 - * The second statement to check. - * @return True if their successor differ, false if not. - */ - private boolean differentSuccessor(Statement statement1, Statement statement2) { - Statement pred1 = getSuccessor(statement1); - Statement pred2 = getSuccessor(statement2); - Boolean similarity = similarityChecker.isSimilar(pred1, pred2, false); - return similarity == Boolean.FALSE; - } - - /** - * Get the predecessor statement of a statement within the parents container statement list.
- * If a statement is the first, the only one, or the container is not a - * {@link StatementListContainer}, or no predecessor exists, null will be returned. - * - * @param statement - * The statement to get the predecessor for. - * @return The predecessor or null if non exists. - */ - private Statement getPredecessor(Statement statement) { - - int pos = JaMoPPElementUtil.getPositionInContainer(statement); - if (pos > 0) { - StatementListContainer container = (StatementListContainer) statement.eContainer(); - return container.getStatements().get(pos - 1); - } - - return null; - } - - /** - * Get the successor statement of a statement within the parents container statement list.
- * If a statement is the last, the only one, or the container is not a - * {@link StatementListContainer}, no successor exists, null will be returned. - * - * @param statement - * The statement to get the predecessor for. - * @return The predecessor or null if non exists. - */ - private Statement getSuccessor(Statement statement) { - - int pos = JaMoPPElementUtil.getPositionInContainer(statement); - if (pos != -1) { - StatementListContainer container = (StatementListContainer) statement.eContainer(); - if (container.getStatements().size() > pos + 1) { - return container.getStatements().get(pos + 1); - } - } - - return null; - } - } - - /** - * Similarity decisions for elements of the types package. - */ - private class TypesSimilaritySwitch extends TypesSwitch { - - /** - * Check element reference similarity.
- * - * Is checked by the target (the method called). Everything else are containment references - * checked indirectly. - * - * @param ref1 - * The method call to compare with the compare element. - * @return True As null always means null. - */ - @Override - public Boolean caseClassifierReference(ClassifierReference ref1) { - ClassifierReference ref2 = (ClassifierReference) compareElement; - - Boolean targetSimilarity = similarityChecker.isSimilar(ref1.getTarget(), ref2.getTarget()); - if (targetSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - - @Override - public Boolean caseTypeReference(TypeReference ref1) { - - TypeReference ref2 = (TypeReference) compareElement; - - Boolean targetSimilarity = similarityChecker.isSimilar(ref1.getTarget(), ref2.getTarget()); - if (targetSimilarity == Boolean.FALSE) { - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - - @Override - public Boolean caseNamespaceClassifierReference(NamespaceClassifierReference ref1) { - - NamespaceClassifierReference ref2 = (NamespaceClassifierReference) compareElement; - - String namespace1 = Strings.nullToEmpty(ref1.getNamespacesAsString()); - String namespace2 = Strings.nullToEmpty(ref2.getNamespacesAsString()); - if (!namespace1.equals(namespace2)) { - return Boolean.FALSE; - } - - ClassifierReference pureRef1 = ref1.getPureClassifierReference(); - ClassifierReference pureRef2 = ref2.getPureClassifierReference(); - - return similarityChecker.isSimilar(pureRef1, pureRef2); - } - - /** - * Primitive types are always similar as their class similarity is assumed before by the - * outer {@link SimilarityChecker}. - * - * Note: The fall back to the default case is not sufficient here, as the common - * TypeReference case would be used before, leading to a loop. - * - * @param type - * The primitive type object. - * @return TRUE - */ - @Override - public Boolean casePrimitiveType(PrimitiveType type) { - return Boolean.TRUE; - } - - /** - * Inferable types are considered to be similar. - * - * @param type The element to compare with the compare element. - * @return true. - */ - @Override - public Boolean caseInferableType(InferableType type) { - return Boolean.TRUE; - } - - /** - * Primitive type elements are strongly typed and the exact type is already checked by the - * outer {@link SimilarityChecker}.
- * {@inheritDoc} - */ - @Override - public Boolean defaultCase(EObject object) { - return Boolean.TRUE; - } - } - - /** - * Similarity decisions for the variable elements. - */ - private class VariablesSimilaritySwitch extends VariablesSwitch { - - /** - * Check variable declaration similarity.
- * Similarity is checked by - *
    - *
  • variable name
  • - *
  • variable container (name space)
  • - *
- * - * @param var1 - * The variable declaration to compare with the compare element. - * @return True/False if the variable declarations are similar or not. - */ - @Override - public Boolean caseVariable(Variable var1) { - - Variable var2 = (Variable) compareElement; - - // check the variables name equality - if (!var1.getName().equals(var2.getName())) { - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - - @Override - public Boolean caseAdditionalLocalVariable(AdditionalLocalVariable var1) { - AdditionalLocalVariable var2 = (AdditionalLocalVariable) compareElement; - - // check the variables name equality - String name1 = Strings.nullToEmpty(var1.getName()); - String name2 = Strings.nullToEmpty(var2.getName()); - if (!name1.equals(name2)) { - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - } - - /** - * Similarity Decisions for layout information is always true as they are not considered for - * now. - */ - private class LayoutSimilaritySwitch extends LayoutSwitch { - @Override - public Boolean defaultCase(EObject object) { - return Boolean.TRUE; - } - } - - /** - * Similarity Decisions for module elements. - */ - private class ModulesSimilaritySwitch extends ModulesSwitch { - /** - * Check ModuleReference similarity.
- * Similarity is checked by - *
    - *
  • module names
  • - *
- * - * @param modRef1 The module reference to compare with the compare element. - * @return True/False if the module references are similar or not. - */ - @Override - public Boolean caseModuleReference(ModuleReference modRef1) { - ModuleReference modRef2 = (ModuleReference) compareElement; - if (compareNamespacesByPart(modRef1, modRef2)) { - return Boolean.TRUE; - } - return Boolean.FALSE; - } - - /** - * Check similarity for access providing module directives.
- * Similarity is checked by - *
    - *
  • the provided package
  • - *
- * - * @param dir1 The access providing module directive to compare with the compare element. - * @return True/False if the module directives are similar or not. - */ - @Override - public Boolean caseAccessProvidingModuleDirective(AccessProvidingModuleDirective dir1) { - AccessProvidingModuleDirective dir2 = (AccessProvidingModuleDirective) compareElement; - if (!compareNamespacesByPart(dir1, dir2)) { - return Boolean.FALSE; - } - return Boolean.TRUE; - } - - /** - * Check similarity for require module directives.
- * Similarity is checked by - *
    - *
  • required modules
  • - *
- * - * @param dir1 The require module directive to compare with the compare element. - * @return True/False if the module directives are similar or not. - */ - @Override - public Boolean caseRequiresModuleDirective(RequiresModuleDirective dir1) { - RequiresModuleDirective dir2 = (RequiresModuleDirective) compareElement; - return similarityChecker.isSimilar(dir1.getRequiredModule(), dir2.getRequiredModule()); - } - - /** - * Check similarity for provide module directives.
- * Similarity is checked by - *
    - *
  • provided types
  • - *
- * - * @param dir1 The provide module directive to compare with the compare element. - * @return True/False if the module directives are similar or not. - */ - @Override - public Boolean caseProvidesModuleDirective(ProvidesModuleDirective dir1) { - ProvidesModuleDirective dir2 = (ProvidesModuleDirective) compareElement; - return similarityChecker.isSimilar(dir1.getTypeReference(), dir2.getTypeReference()); - } - - /** - * Check similarity for use module directives.
- * Similarity is checked by - *
    - *
  • used types
  • - *
- * - * @param dir1 The use module directive to compare with the compare element. - * @return True/False if the module directives are similar or not. - */ - @Override - public Boolean caseUsesModuleDirective(UsesModuleDirective dir1) { - UsesModuleDirective dir2 = (UsesModuleDirective) compareElement; - return similarityChecker.isSimilar(dir1.getTypeReference(), dir2.getTypeReference()); - } - } - - /** - * Compares the namespaces of two elements by comparing each part of the namespaces. - * - * @param ele1 the first element. - * @param ele2 the second element to compare to the first element. - * @return true if the number of parts of the namespaces and each part in both namespaces are equal. false otherwise. - */ - private boolean compareNamespacesByPart(NamespaceAwareElement ele1, NamespaceAwareElement ele2) { - if (ele1.getNamespaces().size() != ele2.getNamespaces().size()) { - return false; - } - for (int idx = 0; idx < ele1.getNamespaces().size(); idx++) { - if (!ele1.getNamespaces().get(idx).equals(ele2.getNamespaces().get(idx))) { - return false; - } - } - return true; - } - - /** - * The default case for not explicitly handled elements always returns null to identify the open - * decision. - * - * @param object - * The object to compare with the compare element. - * @return null - */ - @Override - public Boolean defaultCase(EObject object) { - return null; - } -} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/AbstractSimilarityChecker.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/AbstractSimilarityChecker.java new file mode 100644 index 0000000000..b1c45afe4b --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/AbstractSimilarityChecker.java @@ -0,0 +1,71 @@ +package org.splevo.jamopp.diffing.similarity.base; + +/** + * An abstract class for similarity checkers to extend. Complements + * {@link ISimilarityChecker} with the integration of + * {@link ISimilarityComparer}.
+ *
+ * Does not implement {@link ISimilarityRequestHandler}, because its concrete + * implementors are thought to serve as facades to the outside. They are thus + * not intended to be used during the similarity checking process, other than a + * call to similarity checking methods, such as + * {@link #isSimilar(Object, Object)}, at the start. + * + * @author atora + */ +public abstract class AbstractSimilarityChecker implements ISimilarityChecker { + /** + * The {@link ISimilarityComparer}, to which incoming {@link ISimilarityRequest} + * instances are to be delegated. + */ + private ISimilarityComparer sc; + + /** + * Constructs an {@link AbstractSimilarityChecker} instance with an + * {@link ISimilarityComparer}, which delegates all incoming + * {@link ISimilarityRequest} to the given parameter. + * + * @param st {@link ISimilarityToolbox} to which all incoming + * {@link ISimilarityRequest} instances will be delegated to. + */ + public AbstractSimilarityChecker(ISimilarityToolbox st) { + this.sc = this.createSimilarityComparer(st); + } + + /** + * Declared as protected only to allow access to the underlying + * {@link ISimilarityComparer} from concrete implementors. + * + * @return {@link ISimilarityToolbox} to which all incoming + * {@link ISimilarityRequest} instances will be delegated to. + */ + protected ISimilarityComparer getSimilarityComparer() { + return this.sc; + } + + /** + * Delegates the incoming {@link ISimilarityRequest} to the underlying + * {@link ISimilarityComparer}.
+ *
+ * Declared as protected only to let concrete implementors delegate incoming + * {@link ISimilarityRequest} instances to their {@link ISimilarityComparer}. + *
+ *
+ * This is necessary, because creating further internal constructs that contain + * similarity checking logic, such as similarity switches, may involve using + * {@link ISimilarityRequestHandler} instances and that in return requires + * delegating {@link ISimilarityRequest} instances. + */ + protected Object handleSimilarityRequest(ISimilarityRequest req) { + return this.getSimilarityComparer().handleSimilarityRequest(req); + } + + /** + * Creates an {@link ISimilarityComparer} with the given + * {@link ISimilarityToolbox}. + * + * @param st The {@link ISimilarityToolbox} that the constructed + * {@link ISimilarityComparer} will use. + */ + protected abstract ISimilarityComparer createSimilarityComparer(ISimilarityToolbox st); +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/AbstractSimilarityComparer.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/AbstractSimilarityComparer.java new file mode 100644 index 0000000000..992135469a --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/AbstractSimilarityComparer.java @@ -0,0 +1,57 @@ +package org.splevo.jamopp.diffing.similarity.base; + +/** + * An abstract class for similarity comparers to extend. Complements + * {@link ISimilarityComparer} with the integration of + * {@link ISimilarityToolbox}.
+ *
+ * Delegates incoming {@link ISimilarityRequest} instances to its + * {@link ISimilarityToolbox}. + * + * @author atora + */ +public abstract class AbstractSimilarityComparer implements ISimilarityComparer { + /** + * The {@link ISimilarityToolbox}, to which all incoming + * {@link ISimilarityRequest} instances should be delegated to. + */ + private ISimilarityToolbox st; + + /** + * Constructs an instance with a given {@link ISimilarityToolbox} + * + * @param st The {@link ISimilarityToolbox}, to which all incoming + * {@link ISimilarityRequest} instances should be delegated to. + */ + public AbstractSimilarityComparer(ISimilarityToolbox st) { + this.st = st; + } + + /** + * @return The {@link ISimilarityToolbox}, to which all incoming + * {@link ISimilarityRequest} instances should be delegated to. + */ + protected ISimilarityToolbox getSimilarityToolbox() { + return this.st; + } + + /** + * {@inheritDoc}
+ *
+ * Here, this method is delegated to {@link #getSimilarityToolbox()}. + */ + @Override + public Object handleSimilarityRequest(ISimilarityRequest req) { + return this.getSimilarityToolbox().handleSimilarityRequest(req); + } + + /** + * {@inheritDoc}
+ *
+ * Here, this method is delegated to {@link #getSimilarityToolbox()}. + */ + @Override + public boolean canHandleSimilarityRequest(Class reqClass) { + return this.getSimilarityToolbox().canHandleSimilarityRequest(reqClass); + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/AbstractSimilarityToolboxBuilder.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/AbstractSimilarityToolboxBuilder.java new file mode 100644 index 0000000000..8bfb4aadff --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/AbstractSimilarityToolboxBuilder.java @@ -0,0 +1,82 @@ +package org.splevo.jamopp.diffing.similarity.base; + +/** + * An abstract class for concrete similarity {@link ISimilarityToolbox} builders + * to extend. Complements {@link ISimilarityToolboxBuilder} with the integration + * of {@link ISimilarityToolboxFactory}. + * + * @author atora + */ +public abstract class AbstractSimilarityToolboxBuilder implements ISimilarityToolboxBuilder { + /** + * The {@link ISimilarityToolboxFactory}, which determines the data structure + * used to store request-handler pairs within the {@link ISimilarityToolbox} + * instances built using this builder. + */ + private ISimilarityToolboxFactory stf; + + /** + * The current version of the {@link ISimilarityToolbox} instance being built. + */ + private ISimilarityToolbox st; + + /** + * Constructs an instance. + */ + public AbstractSimilarityToolboxBuilder() { + super(); + } + + @Override + public void setSimilarityToolboxFactory(ISimilarityToolboxFactory stf) { + this.stf = stf; + } + + /** + * @return The {@link ISimilarityToolboxFactory}, which determines the data + * structure used to store request-handler pairs within the + * {@link ISimilarityToolbox} instances built using this builder. + */ + @Override + public ISimilarityToolboxFactory getToolboxFactory() { + return this.stf; + } + + /** + * Meant to allow concrete implementors the access to the current version of the + * {@link ISimilarityToolbox} under construction. + * + * @return The current version of the {@link ISimilarityToolbox} instance being + * built. + */ + protected ISimilarityToolbox getCurrentToolbox() { + return this.st; + } + + /** + * {@inheritDoc}
+ *
+ * Resets the {@link ISimilarityToolbox} instance currently being built to + * null. + */ + @Override + public ISimilarityToolbox build() { + var result = this.getCurrentToolbox(); + this.st = null; + return result; + } + + @Override + public ISimilarityToolboxBuilder instantiate() { + this.st = this.getToolboxFactory().createSimilarityToolbox(); + return this; + } + + @Override + public ISimilarityToolboxBuilder buildRequestHandlerPair(Class req, + ISimilarityRequestHandler srh) { + this.getCurrentToolbox().addRequestHandlerPair(req, srh); + return this; + } + +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityChecker.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityChecker.java new file mode 100644 index 0000000000..7ffa15af18 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityChecker.java @@ -0,0 +1,45 @@ +package org.splevo.jamopp.diffing.similarity.base; + +import java.util.Collection; + +/** + * An interface for classes that contain the means to compare elements and + * compute their similarity. The classes implementing this interface, the + * similarity checkers, are meant to serve as facades to outside.
+ *
+ * {@link AbstractSimilarityChecker} contains further useful methods for + * similarity checkers. It is therefore recommended to extend + * {@link AbstractSimilarityChecker} for similarity checker classes rather than + * implementing this interface alone. {@link AbstractSimilarityChecker} also + * makes use of {@link ISimilarityComparer}, which can be used to free the + * implementors of {@link ISimilarityChecker} of internal details.
+ *
+ * If the structure defined in {@link AbstractSimilarityChecker} is not to be + * used, this interface can be directly implemented. + * + * @see {@link AbstractSimilarityChecker}, {@link ISimilarityComparer} + * @author atora + */ +public interface ISimilarityChecker { + /** + * Check the similarity of two elements. + * + * @param element1 The first element. + * @param element2 The second element. + * @return TRUE, if they are similar; FALSE if not, NULL if it can't be decided. + */ + public Boolean isSimilar(Object element1, Object element2); + + /** + * Check two lists of elements for similarity.
+ *
+ * The elements are compared pairwise and it is the responsibility of the + * provided list implementations to return them in an appropriate order by + * calling get(i) with a increasing index i. + * + * @return TRUE, if they are all similar; FALSE if a different number of + * elements is submitted or at least one pair of elements is not similar + * to each other. + */ + public Boolean areSimilar(Collection elements1, Collection elements2); +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityComparer.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityComparer.java new file mode 100644 index 0000000000..0e815c8931 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityComparer.java @@ -0,0 +1,33 @@ +package org.splevo.jamopp.diffing.similarity.base; + +/** + * An interface for similarity comparers, which can be used as a layer of + * indirection between {@link ISimilarityChecker} and + * {@link ISimilarityToolbox}. This allows to integrate additional similarity + * checking related constructs without bloating the implementors of + * {@link ISimilarityChecker}.
+ *
+ * {@link AbstractSimilarityComparer} contains further useful methods for + * similarity comparers. It also integrates {@link ISimilarityToolbox} with + * {@link ISimilarityComparer}. It is therefore recommended to extend + * {@link AbstractSimilarityComparer} for similarity comparer classes rather + * than implementing this interface alone.
+ *
+ * Implements {@link ISimilarityRequestHandler} because this increases the + * flexibility of similarity comparers. This is important, as they are thought + * as a layer of indirection. For example, a similarity comparer could be + * implemented to work with multiple {@link ISimilarityToolbox} instances, so + * that {@link ISimilarityToolbox} instances with different purposes can be + * separated. Alternatively, one can choose to implement + * {@link ISimilarityComparer} with means other than {@link ISimilarityToolbox} + * to deal with {@link ISimilarityRequest} instances, although doing so would + * deviate from {@link AbstractSimilarityComparer} and + * {@link AbstractSimilarityChecker}. + * + * @see {@link AbstractSimilarityChecker}, {@link AbstractSimilarityComparer}, + * {@link ISimilarityToolbox} + * @author atora + */ +public interface ISimilarityComparer extends ISimilarityRequestHandler { + +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityRequest.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityRequest.java new file mode 100644 index 0000000000..3db53cf8de --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityRequest.java @@ -0,0 +1,23 @@ +package org.splevo.jamopp.diffing.similarity.base; + +/** + * An interface for encapsulating parameters required by similarity checking + * operations. Similarity requests are intended to be used by their matching + * {@link ISimilarityRequestHandler}.
+ *
+ * It is recommended to not override the return type of {@link #getParams()}, + * especially if the concrete similarity requests are planned to be extended. + * + * @see {@link ISimilarityToolbox}, {@link ISimilarityRequestHandler} + * @author atora + */ +public interface ISimilarityRequest { + /** + * @return All parameters encapsulated by this instance. Unless specified + * otherwise, the return type is an Object array of all parameters + * passed to the constructor of the concrete implementation in the same + * order. If the said constructor only takes one parameter, the return + * type of this method is the type of that parameter in the constructor. + */ + public Object getParams(); +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityRequestHandler.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityRequestHandler.java new file mode 100644 index 0000000000..e9f945177d --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityRequestHandler.java @@ -0,0 +1,44 @@ +package org.splevo.jamopp.diffing.similarity.base; + +/** + * An interface for encapsulating similarity operations, whose implementors take + * {@link ISimilarityRequest} instances and process them. Implementors of this + * interface are meant to be used to extract such operations from other + * classes/interfaces, as well as their relevant parameters, if plausible. Doing + * so keeps other classes/interfaces clear of functionality that does not + * concern them.
+ *
+ * Implementors can contain further {@link ISimilarityRequestHandler} instances, + * such as an {@link ISimilarityToolbox} or request-specific + * {@link ISimilarityRequestHandler} instances, if they have to process requests + * that need further processing. + * + * @author atora + */ +public interface ISimilarityRequestHandler { + /** + * Processes the given {@link ISimilarityRequest} and returns the result.
+ *
+ * It is recommended to not override the return type, especially if the concrete + * {@link ISimilarityRequestHandler} instances are planned to be extended. + * + * @param req The incoming request. + */ + public Object handleSimilarityRequest(ISimilarityRequest req); + + /** + * @param req A given {@link ISimilarityRequest} instance + * + * @return Whether {@code req} can be handled. + */ + public default boolean canHandleSimilarityRequest(ISimilarityRequest req) { + return this.canHandleSimilarityRequest(req.getClass()); + } + + /** + * @param reqClass The class of the {@link ISimilarityRequest} instance + * + * @return Whether instances of {@code reqClass} can be handled. + */ + public boolean canHandleSimilarityRequest(Class reqClass); +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityToolbox.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityToolbox.java new file mode 100644 index 0000000000..342507cd19 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityToolbox.java @@ -0,0 +1,75 @@ +package org.splevo.jamopp.diffing.similarity.base; + +/** + * An interface for classes that contain ({@link ISimilarityRequest} (class), + * {@link ISimilarityRequestHandler} (instance)) pairs (or request-handler + * pairs).
+ *
+ * Since the implementors contain request-handler pairs specified above, they + * themselves can be used as {@link ISimilarityRequestHandler} to handle + * {@link ISimilarityRequest} instances. In such cases, they delegate the + * received {@link ISimilarityRequest} to their matching + * {@link ISimilarityRequestHandler}.
+ *
+ * Implementors of this interface allow adding and removing the said pairs + * dynamically. In doing so, they make dynamic changes to similarity checking + * possible. Additionally, new similarity operations can be integrated without + * modifying the implementors themselves by calling the + * {@link #addRequestHandlerPair(Class, ISimilarityRequestHandler)} method.
+ *
+ * This interface makes no assumptions on the data structure used in its + * concrete implementors to store request-handler pairs. Neither does it + * explicitly specify how incoming {@link ISimilarityRequest} instances are + * internally handled. + * + * @see {@link ISimilarityToolboxBuilder}, {@link ISimilarityToolboxFactory} + * @author atora + */ +public interface ISimilarityToolbox extends ISimilarityRequestHandler { + /** + * Adds a ({@link ISimilarityRequest} (class), {@link ISimilarityRequestHandler} + * (instance)) pair (or request-handler pair).
+ *
+ * Note that the first parameter (reqClass) is the class of the + * {@link ISimilarityRequest} and the second parameter (srh) is an + * {@link ISimilarityRequestHandler} instance. + * + * @param reqClass The class of the {@link ISimilarityRequest} instances, which + * should be processed using the given + * {@link ISimilarityRequestHandler} instance. + * @param srh The {@link ISimilarityRequestHandler} instance, which should + * be used to process the {@link ISimilarityRequest} instances + * of the given class. + */ + public void addRequestHandlerPair(Class reqClass, ISimilarityRequestHandler srh); + + /** + * Removes the pairs added for {@link ISimilarityRequest}. + * + * @param reqClass The class of the {@link ISimilarityRequest} instances + * + * @see {@link #addRequestHandlerPair(Class, ISimilarityRequestHandler)} + */ + public void removeRequestHandlerPair(Class reqClass); + + /** + * Removes all pairs added to this instance. + * + * @see {@link #addRequestHandlerPair(Class, ISimilarityRequestHandler)} + */ + public void clearRequestHandlerPairs(); + + /** + * {@inheritDoc}
+ *
+ * The data structure used in the {@link ISimilarityToolbox} implementation to + * store request-handler pairs can influence the way {@code req} is handled. For + * example, in cases where there is no corresponding handler or if there are + * multiple corresponding handlers. + */ + @Override + public Object handleSimilarityRequest(ISimilarityRequest req); + + @Override + public boolean canHandleSimilarityRequest(Class reqClass); +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityToolboxBuilder.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityToolboxBuilder.java new file mode 100644 index 0000000000..3c94125651 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityToolboxBuilder.java @@ -0,0 +1,86 @@ +package org.splevo.jamopp.diffing.similarity.base; + +/** + * An interface implemented by classes that help build a + * {@link ISimilarityToolbox} dynamically. The implementors use the builder + * pattern and may include further building methods.
+ *
+ * To build a {@link ISimilarityToolbox}: + *
    + *
  1. Set the {@link ISimilarityToolboxFactory} to specify the internal data + * structure that will be used in the end product to store request-handler pairs + * using {@link #setSimilarityToolboxFactory(ISimilarityToolboxFactory)}. + *
  2. Instantiate a {@link ISimilarityToolbox} within the + * {@link ISimilarityToolboxBuilder} using {@link #instantiate()}. + *
  3. Use the provided building methods, such as + * {@link #buildRequestHandlerPair(Class, ISimilarityRequestHandler)}. + *
  4. Return the end product by calling {@link #build()}. + *
+ * Concrete implementors may provide additional building methods, such as those + * that summarise multiple + * {@link #buildRequestHandlerPair(Class, ISimilarityRequestHandler)} calls into + * one method. In such cases, it is recommended to use those methods instead, in + * order to keep the building process tidier. + * + * @author atora + */ +public interface ISimilarityToolboxBuilder { + /** + * Sets the {@link ISimilarityToolboxFactory}, which specifies the internal data + * structure that will be used in the end product to store request-handler + * pairs. Currently used {@link ISimilarityToolboxFactory} can be changed by + * using this method as well.
+ *
+ * Note that changing the {@link ISimilarityToolboxFactory} after calling + * {@link #instantiate()} has no effect on the {@link ISimilarityToolbox} that + * is currently being built. For this change to take effect, + * {@link #instantiate()} can be called to start the building process anew with + * the new {@link ISimilarityToolboxFactory}. + * + * @param stf The new {@link ISimilarityToolboxFactory} that this builder will + * use + */ + public void setSimilarityToolboxFactory(ISimilarityToolboxFactory stf); + + /** + * @return Currently used {@link ISimilarityToolboxFactory}. + */ + public ISimilarityToolboxFactory getToolboxFactory(); + + /** + * Returns the current version of the {@link ISimilarityToolbox} being built. + *
+ *
+ * Depending on the concrete implementation, calling this method may set the + * current version of the {@link ISimilarityToolbox} to null after + * returning. + * + * @return The resulting {@link ISimilarityToolbox}. + */ + public ISimilarityToolbox build(); + + /** + * Creates a {@link ISimilarityToolbox} using the current + * {@link ISimilarityToolboxFactory} within this builder. Can also be used to + * reset the current version of the {@link ISimilarityToolbox}. + * + * @return this + */ + public ISimilarityToolboxBuilder instantiate(); + + /** + * Adds the given request-handler pair (reqClass, srh) to the + * {@link ISimilarityToolbox}. + * + * @param reqClass The class of the {@link ISimilarityRequest} instances, which + * should be processed using the given + * {@link ISimilarityRequestHandler} instance. + * @param srh The {@link ISimilarityRequestHandler} instance, which should + * be used to process the {@link ISimilarityRequest} instances + * of the given class. + * + * @return this + */ + public ISimilarityToolboxBuilder buildRequestHandlerPair(Class reqClass, + ISimilarityRequestHandler srh); +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityToolboxFactory.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityToolboxFactory.java new file mode 100644 index 0000000000..868e74dadb --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ISimilarityToolboxFactory.java @@ -0,0 +1,22 @@ +package org.splevo.jamopp.diffing.similarity.base; + +/** + * An interface for {@link ISimilarityToolbox} factories.
+ *
+ * The purpose of the implementors of this interface is to set the data + * structure that will be used in the {@link ISimilarityToolbox} to contain the + * request-handler pairs added to them.
+ *
+ * It is recommended to use {@link ISimilarityToolboxBuilder} and its + * implementors to build {@link ISimilarityToolbox} instances. + * + * @see {@link ISimilarityToolbox}, {@link ISimilarityToolboxBuilder} + * @author atora + */ +public interface ISimilarityToolboxFactory { + /** + * Constructs and returns an {@link ISimilarityToolbox} instance without any + * pairs. + */ + public ISimilarityToolbox createSimilarityToolbox(); +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/MapSimilarityToolbox.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/MapSimilarityToolbox.java new file mode 100644 index 0000000000..d7f3e487a1 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/MapSimilarityToolbox.java @@ -0,0 +1,70 @@ +package org.splevo.jamopp.diffing.similarity.base; + +import java.util.HashMap; +import java.util.Map; + +/** + * An {@link ISimilarityToolbox} implementor, that uses a {@link Map} to contain + * 1 to 1 mappings between request-handler pairs (see + * {@link ISimilarityToolbox}).
+ *
+ * This means that only one {@link ISimilarityRequestHandler} stored in this + * instance will process incoming {@link ISimilarityRequest}.
+ *
+ * Therefore, if a request is to be handled by further handlers, either the + * delegation to those handlers must be implemented in the initial handler or + * another concrete {@link ISimilarityToolbox} implementation should be used. + * + * @author atora + */ +public class MapSimilarityToolbox implements ISimilarityToolbox { + /** + * The map that contains the request-handler pairs. + */ + private Map, ISimilarityRequestHandler> rhMap; + + /** + * Constructs an instance and initialises the map it uses to store + * request-handler pairs. + */ + public MapSimilarityToolbox() { + this.rhMap = new HashMap, ISimilarityRequestHandler>(); + } + + /** + * {@inheritDoc}
+ *
+ * If there is already a request-handler pair for reqClass, it will be replaced + * by the given pair (reqClass, srh). + */ + @Override + public void addRequestHandlerPair(Class reqClass, ISimilarityRequestHandler srh) { + this.rhMap.put(reqClass, srh); + } + + @Override + public void removeRequestHandlerPair(Class reqClass) { + this.rhMap.remove(reqClass); + } + + @Override + public void clearRequestHandlerPairs() { + this.rhMap.clear(); + } + + /** + * Attempts to handle the given {@link ISimilarityRequest} with a matching + * {@link ISimilarityRequestHandler} and returns the output. + */ + @Override + public Object handleSimilarityRequest(ISimilarityRequest req) { + var handler = this.rhMap.get(req.getClass()); + + return handler != null ? handler.handleSimilarityRequest(req) : null; + } + + @Override + public boolean canHandleSimilarityRequest(Class reqClass) { + return this.rhMap.containsKey(reqClass); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/MapSimilarityToolboxFactory.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/MapSimilarityToolboxFactory.java new file mode 100644 index 0000000000..a6041b5dd8 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/MapSimilarityToolboxFactory.java @@ -0,0 +1,13 @@ +package org.splevo.jamopp.diffing.similarity.base; + +/** + * A factory that creates {@link MapSimilarityToolbox} instances. + * + * @author atora + */ +public class MapSimilarityToolboxFactory implements ISimilarityToolboxFactory { + @Override + public MapSimilarityToolbox createSimilarityToolbox() { + return new MapSimilarityToolbox(); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/AbstractComposedSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/AbstractComposedSimilaritySwitch.java new file mode 100644 index 0000000000..da4c0ec811 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/AbstractComposedSimilaritySwitch.java @@ -0,0 +1,90 @@ +package org.splevo.jamopp.diffing.similarity.base.ecore; + +import java.util.Collection; + +import org.eclipse.emf.ecore.util.Switch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +/** + * An abstract class that complements {@link AbstractComposedSwitchAdapter} with + * an attribute to store an {@link ISimilarityRequestHandler} instance. This + * attribute is then used during similarity checking to delegate + * {@link ISimilarityRequest} instances to their proper + * {@link ISimilarityRequestHandler} instance. + * + * @author atora + */ +public abstract class AbstractComposedSimilaritySwitch extends AbstractComposedSwitchAdapter + implements ISimilarityRequestHandler { + + /** + * The {@link ISimilarityRequestHandler}, to which incoming + * {@link ISimilarityRequest} instances will be delegated. + */ + private ISimilarityRequestHandler srh; + + /** + * Constructs an instance with the given {@link ISimilarityRequestHandler}. + * + * @param srh The {@link ISimilarityRequestHandler}, to which incoming + * {@link ISimilarityRequest} instances will be delegated. + */ + public AbstractComposedSimilaritySwitch(ISimilarityRequestHandler srh) { + super(); + this.srh = srh; + } + + /** + * Variation of + * {@link #AbstractComposedSimilaritySwitch(ISimilarityRequestHandler)} that + * constructs an instance with the given switches. + * + * @see {@link AbstractComposedSwitchAdapter#AbstractComposedSwitchWrapper(Collection)} + */ + protected AbstractComposedSimilaritySwitch(ISimilarityRequestHandler srh, Collection> switches) { + super(switches); + this.srh = srh; + } + + /** + * Variation of + * {@link #AbstractComposedSimilaritySwitch(ISimilarityRequestHandler)} that + * constructs an instance with the given switches. + * + * @see {@link AbstractComposedSwitchAdapter#AbstractComposedSwitchWrapper(Switch[])} + */ + protected AbstractComposedSimilaritySwitch(ISimilarityRequestHandler srh, Switch[] switches) { + super(switches); + this.srh = srh; + } + + /** + * @return The {@link ISimilarityRequestHandler}, to which incoming + * {@link ISimilarityRequest} instances will be delegated. + */ + protected ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.srh; + } + + /** + * {@inheritDoc}
+ *
+ * Here, it delegates the incoming {@link ISimilarityRequest} to + * {@link #getSimilarityRequestHandler()}. + */ + @Override + public Object handleSimilarityRequest(ISimilarityRequest req) { + return this.getSimilarityRequestHandler().handleSimilarityRequest(req); + } + + /** + * {@inheritDoc}
+ *
+ * Here, this method is delegated to {@link #getSimilarityRequestHandler()}. + */ + @Override + public boolean canHandleSimilarityRequest(Class reqClass) { + return this.getSimilarityRequestHandler().canHandleSimilarityRequest(reqClass); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/AbstractComposedSimilaritySwitchComparer.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/AbstractComposedSimilaritySwitchComparer.java new file mode 100644 index 0000000000..746a6d9057 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/AbstractComposedSimilaritySwitchComparer.java @@ -0,0 +1,23 @@ +package org.splevo.jamopp.diffing.similarity.base.ecore; + +import org.splevo.jamopp.diffing.similarity.base.AbstractSimilarityComparer; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityToolbox; + +/** + * An abstract class provided for integrating future {@link EObject} constructs + * that may complement {@link AbstractSimilarityComparer}. + * + * @author atora + */ +public abstract class AbstractComposedSimilaritySwitchComparer extends AbstractSimilarityComparer { + /** + * Constructs an instance with the given {@link ISimilarityToolbox}. + * + * @param st The {@link ISimilarityToolbox}, to which all incoming + * {@link ISimilarityRequest} instances should be delegated to. + */ + public AbstractComposedSimilaritySwitchComparer(ISimilarityToolbox st) { + super(st); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/AbstractComposedSwitchAdapter.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/AbstractComposedSwitchAdapter.java new file mode 100644 index 0000000000..4bc26b9532 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/AbstractComposedSwitchAdapter.java @@ -0,0 +1,73 @@ +package org.splevo.jamopp.diffing.similarity.base.ecore; + +import java.util.Collection; +import java.util.List; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.util.ComposedSwitch; +import org.eclipse.emf.ecore.util.Switch; + +/** + * An abstract class that complements {@link IComposedSwitchAdapter} with an + * attribute to contain the compare element mentioned there. It also provides + * implementations for the methods from {@link IComposedSwitchAdapter}. + * + * @author atora + */ +public abstract class AbstractComposedSwitchAdapter extends ComposedSwitch implements IComposedSwitchAdapter { + /** The object to compare the switched element with. */ + private EObject compareElement = null; + + /** + * @see {@link ComposedSwitch#ComposedSwitch()} + */ + public AbstractComposedSwitchAdapter() { + + } + + /** + * Constructs an instance with the given switches.
+ *
+ * Meant to be used while testing. + */ + protected AbstractComposedSwitchAdapter(Collection> switches) { + super(switches); + } + + /** + * Constructs an instance with the given switches.
+ *
+ * Meant to be used while testing. + */ + protected AbstractComposedSwitchAdapter(Switch[] switches) { + this(List.of(switches)); + } + + /** + * {@inheritDoc} + * + * @return The object to compare the switched element with. + */ + @Override + public EObject getCompareElement() { + return this.compareElement; + } + + @Override + public Boolean compare(EObject eo1, EObject eo2) { + this.compareElement = eo2; + return this.doSwitch(eo1); + } + + /** + * The default case for not explicitly handled elements always returns null to + * identify the open decision. + * + * @param object The object to compare with the compare element. + * @return null + */ + @Override + public Boolean defaultCase(EObject object) { + return null; + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/AbstractComposedSwitchSimilarityChecker.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/AbstractComposedSwitchSimilarityChecker.java new file mode 100644 index 0000000000..ffd0c4a856 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/AbstractComposedSwitchSimilarityChecker.java @@ -0,0 +1,75 @@ +package org.splevo.jamopp.diffing.similarity.base.ecore; + +import java.util.ArrayList; +import java.util.Collection; + +import org.eclipse.emf.ecore.EObject; +import org.splevo.jamopp.diffing.similarity.base.AbstractSimilarityChecker; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityToolbox; + +/** + * A version of {@link AbstractSimilarityChecker}, which is adapted for + * {@link EObject}. + * + * @author atora + */ +public abstract class AbstractComposedSwitchSimilarityChecker extends AbstractSimilarityChecker { + /** + * Constructs an instance with a given {@link ISimilarityToolbox}. + * + * @param st The {@link ISimilarityToolbox}, to which all incoming + * {@link ISimilarityRequest} instances should be delegated to. + */ + public AbstractComposedSwitchSimilarityChecker(ISimilarityToolbox st) { + super(st); + } + + /** + * Creates and returns a new {@link IComposedSwitchAdapter}. + */ + protected IComposedSwitchAdapter createDefaultNewSwitch() { + return (IComposedSwitchAdapter) this.handleSimilarityRequest(this.makeDefaultSwitchRequest()); + } + + @Override + public Boolean isSimilar(Object element1, Object element2) { + return (Boolean) this.handleSimilarityRequest(new SingleSimilarityCheckRequest((EObject) element1, + (EObject) element2, this.createDefaultNewSwitch())); + } + + @SuppressWarnings("unchecked") + @Override + public Boolean areSimilar(Collection elements1, Collection elements2) { + Collection sss = new ArrayList(); + + // Null check to avoid NullPointerExceptions + if (elements1 == elements2) { + return Boolean.TRUE; + } + else if (elements1 == null ^ elements2 == null) { + return Boolean.FALSE; + } + + if (elements1.size() != elements2.size()) { + return Boolean.FALSE; + } + + for (int i = 0; i < elements1.size(); i++) { + sss.add(this.createDefaultNewSwitch()); + } + + return (Boolean) this.handleSimilarityRequest(new MultipleSimilarityCheckRequest( + (Collection) elements1, (Collection) elements2, sss)); + } + + /** + * Used by other methods in this instance and concrete implementors that create + * switches. This method can be overridden in the concrete implementors to + * create different {@link ISimilarityRequest} instances, which can be used to + * create different switches ({@link IComposedSwitchAdapter} instances). + * + * @return A {@link ISimilarityRequest} to create a new switch. + */ + protected abstract ISimilarityRequest makeDefaultSwitchRequest(); +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/IComposedSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/IComposedSimilaritySwitch.java new file mode 100644 index 0000000000..c1875471c3 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/IComposedSimilaritySwitch.java @@ -0,0 +1,13 @@ +package org.splevo.jamopp.diffing.similarity.base.ecore; + +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +/** + * This interface complements {@link IComposedSwitchAdapter} and bundles it with + * {@link ISimilarityRequestHandler}. + * + * @author atora + */ +public interface IComposedSimilaritySwitch extends IComposedSwitchAdapter, ISimilarityRequestHandler { + +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/IComposedSwitchAdapter.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/IComposedSwitchAdapter.java new file mode 100644 index 0000000000..de1f7ed5b8 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/IComposedSwitchAdapter.java @@ -0,0 +1,41 @@ +package org.splevo.jamopp.diffing.similarity.base.ecore; + +import org.eclipse.emf.ecore.EObject; + +/** + * An interface that is meant to be implemented by classes, which extend + * {@link org.eclipse.emf.ecore.util.ComposedSwitch}.
+ *
+ * Adapts its implementors to comply with the ComposedSwitch, which requires an + * {@link EObject} instance that remains constant throughout the entire + * similarity checking process. Unlike ComposedSwitch, the implementors will + * provide the {@link #compare(EObject, EObject)} method, which takes two + * {@link EObject} instances and compares them. Due to ComposedSwitch taking + * only one {@link EObject} instance, the second {@link EObject} instance is + * stored in an attribute inside the implementors and is retrieved with + * {@link #getCompareElement()} when needed. + * + * @see {@link IComposedSimilaritySwitch} + * @author atora + */ +public interface IComposedSwitchAdapter { + /** + * Returns the current compare element, which is the second parameter in + * {@link #compare(EObject, EObject)}. + */ + public EObject getCompareElement(); + + /** + * Compares the given {@link EObject} instances and returns the result. + * + * @param eo1 An {@link EObject} instance, which will be compared with eo2. + * @param eo2 The {@link EObject} instance, which will be the compare element. + * @return + *
    + *
  • True, if given {@link EObject} instances are similar + *
  • False, if they are not similar + *
  • Null, if their similarity cannot be decided + *
+ */ + public Boolean compare(EObject eo1, EObject eo2); +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/IInnerSwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/IInnerSwitch.java new file mode 100644 index 0000000000..c46c23952b --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/IInnerSwitch.java @@ -0,0 +1,55 @@ +package org.splevo.jamopp.diffing.similarity.base.ecore; + +import org.eclipse.emf.ecore.EObject; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +/** + * An interface for the classes to implement, which extend + * {@link org.eclipse.emf.ecore.util.Switch} and are nested in + * {@link org.eclipse.emf.ecore.util.ComposedSwitch}. This interface contains + * getters and delegation methods that are mutual among its implementors. + * + * @author atora + */ +public interface IInnerSwitch extends ISimilarityRequestHandler { + /** + * @return The {@link ISimilarityRequestHandler}, to which all incoming + * {@link ISimilarityRequest} instances will be delegated. + */ + public ISimilarityRequestHandler getSimilarityRequestHandler(); + + /** + * @return The {@link IComposedSwitchAdapter} containing this switch + */ + public IComposedSwitchAdapter getContainingSwitch(); + + /** + * @return The current compare element. + * @see {@link IComposedSwitchAdapter} + */ + public default EObject getCompareElement() { + return this.getContainingSwitch().getCompareElement(); + } + + /** + * {@inheritDoc}
+ *
+ * Here, the incoming requests are delegated to + * {@link #getSimilarityRequestHandler()}. + */ + @Override + public default Object handleSimilarityRequest(ISimilarityRequest req) { + return this.getSimilarityRequestHandler().handleSimilarityRequest(req); + } + + /** + * {@inheritDoc}
+ *
+ * Here, this method is delegated to {@link #getSimilarityRequestHandler()}. + */ + @Override + public default boolean canHandleSimilarityRequest(Class reqClass) { + return this.getSimilarityRequestHandler().canHandleSimilarityRequest(reqClass); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/IPositionInnerSwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/IPositionInnerSwitch.java new file mode 100644 index 0000000000..b7c349878a --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/IPositionInnerSwitch.java @@ -0,0 +1,109 @@ +package org.splevo.jamopp.diffing.similarity.base.ecore; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.emf.ecore.EObject; + +/** + * An interface that extends {@link IInnerSwitch} with methods, which are mutual + * among the implementors of {@link IInnerSwitch} that additionally use a flag + * to check statement positions in {@link EObject} instances they compare. + * + * @author atora + */ +public interface IPositionInnerSwitch extends IInnerSwitch { + /** + * @return Whether this switch should take statement positions in + * {@link EObject} instances it compares into account while comparing + * them. + */ + public boolean shouldCheckStatementPosition(); + + /** + * @return Whether the {@link EObject} instances are similar. + * @see {@link ISimilarityChecker} + */ + public default Boolean isSimilar(EObject eo1, EObject eo2) { + return this.isSimilar(eo1, eo2, this.shouldCheckStatementPosition()); + } + + /** + * @param checkStatementPosition See {@link #shouldCheckStatementPosition()} + * @return Whether the {@link EObject} instances are similar, given the + * checkStatementPosition flag. + * @see {@link ISimilarityChecker} + */ + public default Boolean isSimilar(EObject eo1, EObject eo2, boolean checkStatementPosition) { + return (Boolean) this.handleSimilarityRequest( + new SingleSimilarityCheckRequest(eo1, eo2, this.requestNewSwitch(checkStatementPosition))); + } + + /** + * @return Whether the given lists are pairwise similar, using the given list of + * {@link IComposedSwitchAdapter}. + * @see {@link ISimilarityChecker} + */ + public default Boolean areSimilar(Collection eos1, Collection eos2, + Collection sss) { + return (Boolean) this.handleSimilarityRequest(new MultipleSimilarityCheckRequest(eos1, eos2, sss)); + } + + /** + * A version of {@link #areSimilar(Collection, Collection, Collection)} that + * first constructs new switches with the given csps. + * + * @param csps A collection of checkStatementPosition flags (see + * {@link #isSimilar(EObject, EObject, boolean)}). i-th flag in the + * collection meant to be used for similarity checking i-th elements + * of the given {@link EObject} collections. + * @return Whether the given collections are pairwise similar, using the given + * collection of checkStatementPosition flags. + * + * @see {@link ISimilarityChecker} + */ + public default Boolean areSimilar(Collection eos1, Collection eos2, + List csps) { + + Collection sss = new ArrayList(); + + if (csps == null) + return null; + + csps.forEach((csp) -> sss.add((IComposedSwitchAdapter) this.requestNewSwitch(csp))); + + return this.areSimilar(eos1, eos2, sss); + } + + /** + * @return Whether the given collections are pairwise similar, so whether i-th + * element of both collections are similar for {@code i = 0, 1, ...} + * @see {@link ISimilarityChecker} + */ + public default Boolean areSimilar(Collection eos1, Collection eos2) { + var csps = new ArrayList(); + + if (eos1 == eos2) { + return Boolean.TRUE; + } else if (eos1 == null ^ eos2 == null) { + return Boolean.FALSE; + } + + if (eos1.size() != eos2.size()) { + return Boolean.FALSE; + } + + for (int i = 0; i < eos1.size(); i++) { + csps.add(this.shouldCheckStatementPosition()); + } + + return this.areSimilar(eos1, eos2, csps); + } + + /** + * @param checkStatementPosition See {@link #shouldCheckStatementPosition()} + * @return A new switch with the given checkStatementPosition flag. + */ + public IComposedSwitchAdapter requestNewSwitch(boolean checkStatementPosition); +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/MultipleSimilarityCheckHandler.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/MultipleSimilarityCheckHandler.java new file mode 100644 index 0000000000..ef7ae110e9 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/MultipleSimilarityCheckHandler.java @@ -0,0 +1,99 @@ +package org.splevo.jamopp.diffing.similarity.base.ecore; + +import java.util.Collection; + +import org.eclipse.emf.ecore.EObject; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +/** + * A {@link ISimilarityRequestHandler} that processes + * {@link MultipleSimilarityCheckRequest} instances. + * + * @author atora + */ +public class MultipleSimilarityCheckHandler implements ISimilarityRequestHandler { + /** + * The {@link ISimilarityRequestHandler}, to which + * {@link SingleSimilarityCheckRequest} instances will be delegated. + */ + private ISimilarityRequestHandler srh; + + /** + * Constructs an instance with the given {@link ISimilarityRequestHandler}, + * which is able to handle {@link SingleSimilarityCheckRequest} instances. + * + * @param srh The {@link ISimilarityRequestHandler}, to which + * {@link SingleSimilarityCheckRequest} instances will be delegated. + */ + public MultipleSimilarityCheckHandler(ISimilarityRequestHandler srh) { + this.srh = srh; + } + + /** + * {@inheritDoc}
+ *
+ * Compares the similarity of the {@link EObject} collections from the incoming + * request pairwise. To do so, it uses the switch at index i to compare elements + * at the index i in their respective lists. + * + * @return + *
    + *
  • True (as Boolean), if they are all similar + *
  • False (as Boolean), if a different number of elements is + * submitted or at least one pair of elements is not similar to each + * other + *
  • Null, if sizes of both collections of {@link EObjects} match but + * the amount of provided similarity switches in {@code req} does not + * match their size + *
+ * @see {@link ISimilarityChecker} + */ + @SuppressWarnings("unchecked") + @Override + public Object handleSimilarityRequest(ISimilarityRequest req) { + MultipleSimilarityCheckRequest castedR = (MultipleSimilarityCheckRequest) req; + + Object[] params = (Object[]) castedR.getParams(); + Collection elements1 = (Collection) params[0]; + Collection elements2 = (Collection) params[1]; + Collection sss = (Collection) params[2]; + + // Null check to avoid NullPointerExceptions + if (elements1 == elements2) { + return Boolean.TRUE; + } else if (elements1 == null ^ elements2 == null) { + return Boolean.FALSE; + } + + int size = elements1.size(); + + if (size != elements2.size()) { + return Boolean.FALSE; + } + + if (sss == null || size != sss.size()) { + return null; + } + + var es1 = elements1.toArray(EObject[]::new); + var es2 = elements2.toArray(EObject[]::new); + var ssA = sss.toArray(IComposedSwitchAdapter[]::new); + + for (int i = 0; i < size; i++) { + Boolean childSimilarity = (Boolean) this.srh + .handleSimilarityRequest(new SingleSimilarityCheckRequest(es1[i], es2[i], ssA[i])); + + if (childSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + } + + return Boolean.TRUE; + } + + @Override + public boolean canHandleSimilarityRequest(Class reqClass) { + return reqClass.equals(MultipleSimilarityCheckRequest.class); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/MultipleSimilarityCheckRequest.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/MultipleSimilarityCheckRequest.java new file mode 100644 index 0000000000..7f6a32a6e3 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/MultipleSimilarityCheckRequest.java @@ -0,0 +1,43 @@ +package org.splevo.jamopp.diffing.similarity.base.ecore; + +import java.util.Collection; + +import org.eclipse.emf.ecore.EObject; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; + +/** + * An {@link ISimilarityRequest} for checking the similarity of 2 collections of + * {@link EObject} instances. + * + * @author atora + */ +public class MultipleSimilarityCheckRequest implements ISimilarityRequest { + private Collection elements1; + private Collection elements2; + private Collection sss; + + /** + * Constructs a request that encapsulates 2 {@link EObject} collections and a + * collection of switches. + * + * @param elements1 The first element collection. + * @param elements2 The second element collection. + * @param sss Collection of switches that will be used for comparing the + * elements. i-th switch in the collection will be used in the + * similarity checking of i-th elements from respective + * collections. + * + * @see {@link MultipleSimilarityCheckHandler#handleSimilarityRequest(ISimilarityRequest)} + */ + public MultipleSimilarityCheckRequest(Collection elements1, + Collection elements2, Collection sss) { + this.elements1 = elements1; + this.elements2 = elements2; + this.sss = sss; + } + + @Override + public Object getParams() { + return new Object[] { this.elements1, this.elements2, this.sss }; + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/SingleSimilarityCheckHandler.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/SingleSimilarityCheckHandler.java new file mode 100644 index 0000000000..a534cb54e7 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/SingleSimilarityCheckHandler.java @@ -0,0 +1,100 @@ +package org.splevo.jamopp.diffing.similarity.base.ecore; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +/** + * A {@link ISimilarityRequestHandler} that processes + * {@link SingleSimilarityCheckRequest} instances. + * + * @author atora + */ +public class SingleSimilarityCheckHandler implements ISimilarityRequestHandler { + /** + * Uses the given switch to compute the similarity of the given elements. + * + * @param element1 The first element to check. + * @param element2 The second element to check. + * @param ss The switch that will be used during the similarity checking + * @return TRUE, if they are similar; FALSE if not, NULL if it can't be decided. + */ + public Boolean isSimilar(EObject element1, EObject element2, IComposedSwitchAdapter ss) { + // If no switch is given, similarity cannot be computed + if (ss == null) { + return null; + } + + // check that either both or none of them is null + if (element1 == element2) { + return Boolean.TRUE; + } + + if (onlyOneIsNull(element1, element2)) { + return Boolean.FALSE; + } + + // if a proxy is present try to resolve it + // the other element is used as a context. + // TODO Clarify why it can happen that one proxy is resolved and the other is + // not + // further notes available with the issue + // https://sdqbuild.ipd.kit.edu/jira/browse/SPLEVO-279 + if (element2.eIsProxy() && !element1.eIsProxy()) { + element2 = EcoreUtil.resolve(element2, element1); + } else if (element1.eIsProxy() && !element2.eIsProxy()) { + element1 = EcoreUtil.resolve(element1, element2); + } + + // check the elements to be of the same type + if (!element1.getClass().equals(element2.getClass())) { + return Boolean.FALSE; + } + + // check type specific similarity + return ss.compare(element1, element2); + } + + /** + * Method to check if only one of the provided elements is null. + * + * @param element1 The first element. + * @param element2 The second element. + * @return True if only one element is null and the other is not. + */ + protected Boolean onlyOneIsNull(final EObject element1, final EObject element2) { + Boolean onlyOneIsNull = false; + if (element1 != null && element2 == null) { + onlyOneIsNull = Boolean.TRUE; + } else if (element1 == null && element2 != null) { + onlyOneIsNull = Boolean.TRUE; + } + return onlyOneIsNull; + } + + /** + * {@inheritDoc}
+ *
+ * Check two objects if they are similar. + * + * @param element1 The first element to check. + * @param element2 The second element to check. + * @return TRUE, if they are similar; FALSE if not, NULL if it can't be decided. + */ + @Override + public Object handleSimilarityRequest(ISimilarityRequest req) { + SingleSimilarityCheckRequest castedR = (SingleSimilarityCheckRequest) req; + Object[] params = (Object[]) castedR.getParams(); + EObject elem1 = (EObject) params[0]; + EObject elem2 = (EObject) params[1]; + IComposedSwitchAdapter ss = (IComposedSwitchAdapter) params[2]; + + return this.isSimilar(elem1, elem2, ss); + } + + @Override + public boolean canHandleSimilarityRequest(Class reqClass) { + return reqClass.equals(SingleSimilarityCheckRequest.class); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/SingleSimilarityCheckRequest.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/SingleSimilarityCheckRequest.java new file mode 100644 index 0000000000..8542f767f9 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/SingleSimilarityCheckRequest.java @@ -0,0 +1,34 @@ +package org.splevo.jamopp.diffing.similarity.base.ecore; + +import org.eclipse.emf.ecore.EObject; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; + +/** + * An {@link ISimilarityRequest} for checking the similarity of 2 + * {@link EObject} instances. + * + * @author atora + */ +public class SingleSimilarityCheckRequest implements ISimilarityRequest { + private EObject element1; + private EObject element2; + private IComposedSwitchAdapter ss; + + /** + * @param element1 The first element. + * @param element2 The second element. + * @param ss The switch that will be used to compare the elements above. + * + * @see {@link ISimilarityChecker} + */ + public SingleSimilarityCheckRequest(EObject element1, EObject element2, IComposedSwitchAdapter ss) { + this.element1 = element1; + this.element2 = element2; + this.ss = ss; + } + + @Override + public Object getParams() { + return new Object[] { this.element1, this.element2, this.ss }; + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/package-info.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/package-info.java new file mode 100644 index 0000000000..e2b4a14c36 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/ecore/package-info.java @@ -0,0 +1,45 @@ +/** + * Complements {@link org.splevo.jamopp.diffing.similarity.base} with further + * similarity checking elements for {@link EObject} and EMFtext.
+ *
+ * The way similarity checking works remains mostly the same as in + * {@link org.splevo.jamopp.diffing.similarity.base}. Here, the similarity + * checking logic mostly resides in {@link org.eclipse.emf.ecore.util.Switch} + * implementations, which are nested in a + * {@link org.eclipse.emf.ecore.util.ComposedSwitch}. The + * {@link ISimilarityToolbox} instead provides the means to compute certain + * operations during similarity checking. The use of {@link ISimilarityToolbox} + * (as well as {@link ISimilarityRequest} and {@link ISimilarityRequestHandler}) + * makes extracting parameters regarding normalisation possible, for instance. + *
+ *
+ * {@link AbstractComposedSwitchSimilarityChecker} and + * {@link AbstractComposedSimilaritySwitchComparer} extend their correspondent + * from the {@link org.splevo.jamopp.diffing.similarity.base} package.
+ *
+ * {@link IComposedSwitchAdapter} and {@link AbstractComposedSwitchAdapter} can + * be used to make the switches similar to the {@link ISimilarityChecker} in + * terms of how similarity checking methods are called. Without them, + * {@link ISimilarityChecker} (as well as the elements it uses) would have to be + * replicated for each {@link EObject} nested within the {@link EObject} + * instances, whose similarity is being checked, due to the similarity checking + * process here being hierarchical.
+ *
+ * {@link IInnerSwitch}, along with {@link AbstractComposedSimilaritySwitch}, + * helps integrate {@link ISimilarityRequestHandler} into switches, which allows + * them to delegate certain similarity checking operations to + * {@link ISimilarityRequestHandler} (such as an {@link ISimilarityToolbox}). + * Additionally, it provides the switches with some default methods to spare + * them from declaring the same methods. {@link IPositionInnerSwitch} extends + * {@link IInnerSwitch} with further methods that can be used by switches, which + * may need to compare nested {@link EObject} instances and/or account for the + * positions of statements (in form of {@link EObject} instances).
+ *
+ * The concrete {@link ISimilarityRequest} implementations in this package can + * be used by {@link AbstractComposedSwitchSimilarityChecker} to translate and + * delegate incoming similarity checking method calls. The + * {@link ISimilarityRequestHandler} implementations in this package can be used + * in the underlying {@link ISimilarityToolbox} instance to handle the said + * requests. + */ +package org.splevo.jamopp.diffing.similarity.base.ecore; \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/package-info.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/package-info.java new file mode 100644 index 0000000000..98c88676ca --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/base/package-info.java @@ -0,0 +1,73 @@ +/** + * This package contains interfaces and abstract classes that can be used to + * implement similarity checking. An overview of the similarity checking + * process, as well as the roles of individual elements can be found below.
+ *
+ * The similarity checking process begins with the similarity checker + * {@link ISimilarityChecker}, which serves as a facade to outside. It + * translates the incoming similarity checking calls to similarity checking + * request(s), i.e. {@link ISimilarityRequest}. It then delegates those requests + * to its {@link ISimilarityComparer}, which serves as a layer of indirection + * between {@link ISimilarityChecker} and the similarity checking logic. The + * purpose of {@link ISimilarityComparer} is to keep {@link ISimilarityChecker} + * as clean and simple as possible, since it is supposed to serve as a facade. + * {@link ISimilarityComparer} delegates {@link ISimilarityRequest} instances + * delegated to it to the similarity checking "tools", which can be implemented + * in form of {@link ISimilarityRequestHandler} instances.
+ *
+ * {@link ISimilarityToolbox} contains {@link ISimilarityRequestHandler} + * instances, which are meant to handle the incoming {@link ISimilarityRequest} + * instances. It is responsible for storing and organising + * {@link ISimilarityRequestHandler} instances in a way that the incoming + * {@link ISimilarityRequest} instances can be matched with their corresponding + * {@link ISimilarityRequestHandler} instance(s) and be handled by them. Because + * of this, the {@link ISimilarityToolbox} itself is also a + * {@link ISimilarityRequestHandler}. Likewise, {@link ISimilarityComparer} is + * also a {@link ISimilarityRequestHandler}. Further similarity checking tools + * can be added to {@link ISimilarityToolbox} dynamically in form of + * ({@link ISimilarityRequest} (class), {@link ISimilarityRequestHandler} + * (instance)) pairs (or request-handler pairs). The request-handler pairs can + * also be removed dynamically.
+ *
+ * To build a {@link ISimilarityToolbox} instance, one can use + * {@link ISimilarityToolboxBuilder}. {@link ISimilarityToolboxBuilder} + * encapsulates the means to construct {@link ISimilarityToolbox} instances + * dynamically and it may also provide "standard" building methods to bundle + * certain request-handler pairs to ease the building process. Since there are + * many ways to implement {@link ISimilarityToolbox}, one needs to pass a + * {@link ISimilarityToolboxFactory} to the {@link ISimilarityToolboxBuilder}. + * {@link ISimilarityToolboxFactory} is used to create the initial instance of + * the {@link ISimilarityToolbox}, which can then be filled with either the + * {@link ISimilarityToolboxBuilder} or manually.
+ *
+ * While implementing {@link ISimilarityRequestHandler}, including a reference + * to {@link ISimilarityToolbox} in the concrete implementation will allow it to + * create further {@link ISimilarityRequest} instances and delegate them. Doing + * so allows re-using code and creating chains of requests, which can help + * separate concerns better.
+ *
+ * From a design standpoint, using {@link ISimilarityToolbox} helps centralise + * similarity checking operations and makes them easier to modify. Furthermore, + * dynamic modifications are also made possible with this approach, as + * request-handler pairs can be changed during runtime. Outside parameters that + * are only relevant for certain operations can also be stored within the + * relevant {@link ISimilarityRequestHandler} instances. Doing so frees + * similarity checking mechanisms from storing all such parameters and stops the + * said parameters from getting dragged around (as constructor parameters, + * getter/setter methods, etc.). It is therefore important to extract such + * parameters/variables into {@link ISimilarityRequestHandler} implementors + * whenever plausible. Not abiding this can easily pollute classes implementing + * similarity checking logic with those parameters, even though they have no + * purpose being in them. This in return can bloat the said classes' + * constructors and/or the classes themselves with setter/getter methods for the + * said parameters.
+ *
+ * Although the use of the abstract classes, such as + * {@link AbstractSimilarityChecker}, in future implementations is expected, one + * can choose to directly implement their corresponding interfaces, if the said + * abstract classes and/or the intended architecture are not helpful. In order + * to not lose this flexibility, it is important to hide all future (abstract) + * classes behind interfaces and to only use {@link ISimilarityChecker} from + * outside. + */ +package org.splevo.jamopp.diffing.similarity.base; \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/ClassifierNormalizationHandler.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/ClassifierNormalizationHandler.java new file mode 100644 index 0000000000..a107a45c79 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/ClassifierNormalizationHandler.java @@ -0,0 +1,48 @@ +package org.splevo.jamopp.diffing.similarity.handlers; + +import java.util.Map; +import java.util.regex.Pattern; + +import org.splevo.diffing.util.NormalizationUtil; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; +import org.splevo.jamopp.diffing.similarity.requests.ClassifierNormalizationRequest; + +/** + * An {@link ISimilarityRequestHandler} that processes incoming + * {@link ClassifierNormalizationRequest} instances. + * + * @author atora + */ +public class ClassifierNormalizationHandler implements ISimilarityRequestHandler { + /** + * @see {@link JaMoPPDiffer#initSimilarityChecker(Map)} + */ + private Map classifierNormalizations; + + /** + * Constructs an instance with the given parameter. + * + * @see {@link JaMoPPDiffer#initSimilarityChecker(Map)} + */ + public ClassifierNormalizationHandler(Map classifierNormalizations) { + this.classifierNormalizations = classifierNormalizations; + } + + /** + * {@inheritDoc}
+ *
+ * Performs the requested normalisation and returns the result. + */ + @Override + public Object handleSimilarityRequest(ISimilarityRequest req) { + ClassifierNormalizationRequest castedR = (ClassifierNormalizationRequest) req; + + return NormalizationUtil.normalize((String) castedR.getParams(), this.classifierNormalizations); + } + + @Override + public boolean canHandleSimilarityRequest(Class reqClass) { + return reqClass.equals(ClassifierNormalizationRequest.class); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/CompilationUnitNormalizationHandler.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/CompilationUnitNormalizationHandler.java new file mode 100644 index 0000000000..59bd9f2496 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/CompilationUnitNormalizationHandler.java @@ -0,0 +1,48 @@ +package org.splevo.jamopp.diffing.similarity.handlers; + +import java.util.Map; +import java.util.regex.Pattern; + +import org.splevo.diffing.util.NormalizationUtil; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; +import org.splevo.jamopp.diffing.similarity.requests.CompilationUnitNormalizationRequest; + +/** + * An {@link ISimilarityRequestHandler} that processes incoming + * {@link CompilationUnitNormalizationRequest} instances. + * + * @author atora + */ +public class CompilationUnitNormalizationHandler implements ISimilarityRequestHandler { + /** + * @see {@link JaMoPPDiffer#initSimilarityChecker(Map)} + */ + private Map compilationUnitNormalizations; + + /** + * Constructs an instance with the given parameter. + * + * @see {@link JaMoPPDiffer#initSimilarityChecker(Map)} + */ + public CompilationUnitNormalizationHandler(Map compilationUnitNormalizations) { + this.compilationUnitNormalizations = compilationUnitNormalizations; + } + + /** + * {@inheritDoc}
+ *
+ * Performs the requested normalisation and returns the result. + */ + @Override + public Object handleSimilarityRequest(ISimilarityRequest req) { + CompilationUnitNormalizationRequest castedR = (CompilationUnitNormalizationRequest) req; + + return NormalizationUtil.normalize((String) castedR.getParams(), this.compilationUnitNormalizations); + } + + @Override + public boolean canHandleSimilarityRequest(Class reqClass) { + return reqClass.equals(CompilationUnitNormalizationRequest.class); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/NamespaceCheckHandler.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/NamespaceCheckHandler.java new file mode 100644 index 0000000000..639d9f0c09 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/NamespaceCheckHandler.java @@ -0,0 +1,62 @@ +package org.splevo.jamopp.diffing.similarity.handlers; + +import org.splevo.jamopp.diffing.similarity.requests.NamespaceCheckRequest; +import org.emftext.language.java.commons.NamespaceAwareElement; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +/** + * An {@link ISimilarityRequestHandler} that processes incoming + * {@link NamespaceCheckRequest} instances. + * + * @author atora + */ +public class NamespaceCheckHandler implements ISimilarityRequestHandler { + + /** + * {@inheritDoc}
+ *
+ * Checks the given namespaces for similarity and returns the similarity result. + */ + @Override + public Object handleSimilarityRequest(ISimilarityRequest req) { + NamespaceCheckRequest castedR = (NamespaceCheckRequest) req; + NamespaceAwareElement[] params = (NamespaceAwareElement[]) castedR.getParams(); + + var ele1 = params[0]; + var ele2 = params[1]; + + // Null check to avoid NullPointerExceptions + if (ele1 == ele2) { + return true; + } else if (ele1 == null ^ ele2 == null) { + return false; + } + + var nss1 = ele1.getNamespaces(); + var nss2 = ele2.getNamespaces(); + + // Null check to avoid NullPointerExceptions + if (nss1 == nss2) { + return true; + } else if (nss1 == null ^ nss2 == null) { + return false; + } + + if (nss1.size() != nss2.size()) { + return false; + } + + for (int idx = 0; idx < nss1.size(); idx++) { + if (!nss1.get(idx).equals(nss2.get(idx))) { + return false; + } + } + return true; + } + + @Override + public boolean canHandleSimilarityRequest(Class reqClass) { + return reqClass.equals(NamespaceCheckRequest.class); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/NamespaceNormalizationHandler.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/NamespaceNormalizationHandler.java new file mode 100644 index 0000000000..f99eea8ca6 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/NamespaceNormalizationHandler.java @@ -0,0 +1,48 @@ +package org.splevo.jamopp.diffing.similarity.handlers; + +import java.util.Map; +import java.util.regex.Pattern; + +import org.splevo.diffing.util.NormalizationUtil; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; +import org.splevo.jamopp.diffing.similarity.requests.NamespaceNormalizationRequest; + +/** + * An {@link ISimilarityRequestHandler} that processes incoming + * {@link NamespaceNormalizationRequest} instances. + * + * @author atora + */ +public class NamespaceNormalizationHandler implements ISimilarityRequestHandler { + /** + * @see {@link JaMoPPDiffer#initSimilarityChecker(Map)} + */ + private Map packageNormalizations; + + /** + * Constructs an instance with the given parameter. + * + * @see {@link JaMoPPDiffer#initSimilarityChecker(Map)} + */ + public NamespaceNormalizationHandler(Map packageNormalizations) { + this.packageNormalizations = packageNormalizations; + } + + /** + * {@inheritDoc}
+ *
+ * Performs the requested normalisation and returns the result. + */ + @Override + public Object handleSimilarityRequest(ISimilarityRequest req) { + NamespaceNormalizationRequest castedR = (NamespaceNormalizationRequest) req; + + return NormalizationUtil.normalize((String) castedR.getParams(), this.packageNormalizations); + } + + @Override + public boolean canHandleSimilarityRequest(Class reqClass) { + return reqClass.equals(NamespaceNormalizationRequest.class); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/NewSimilaritySwitchHandler.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/NewSimilaritySwitchHandler.java new file mode 100644 index 0000000000..9f09eeacf1 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/NewSimilaritySwitchHandler.java @@ -0,0 +1,49 @@ +package org.splevo.jamopp.diffing.similarity.handlers; + +import org.splevo.jamopp.diffing.similarity.JavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; +import org.splevo.jamopp.diffing.similarity.requests.NewSimilaritySwitchRequest; + +/** + * An {@link ISimilarityRequestHandler} that processes incoming + * {@link NewSimilaritySwitchRequest} instances. + * + * @author atora + */ +public class NewSimilaritySwitchHandler implements ISimilarityRequestHandler { + /** + * The {@link ISimilarityRequestHandler}, which will be passed onto the + * similarity switch created in + * {@link #handleSimilarityRequest(ISimilarityRequest)}. + */ + private ISimilarityRequestHandler srh; + + /** + * Constructs an instance with the given {@link ISimilarityRequestHandler}. + * + * @param srh The {@link ISimilarityRequestHandler}, which will be passed onto + * the similarity switch created in + * {@link #handleSimilarityRequest(ISimilarityRequest)}. + */ + public NewSimilaritySwitchHandler(ISimilarityRequestHandler srh) { + this.srh = srh; + } + + /** + * {@inheritDoc}
+ *
+ * Constructs a new {@link JavaSimilaritySwitch}. + */ + @Override + public Object handleSimilarityRequest(ISimilarityRequest req) { + NewSimilaritySwitchRequest castedR = (NewSimilaritySwitchRequest) req; + Boolean csp = (Boolean) castedR.getParams(); + return new JavaSimilaritySwitch(this.srh, csp); + } + + @Override + public boolean canHandleSimilarityRequest(Class reqClass) { + return reqClass.equals(NewSimilaritySwitchRequest.class); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/PackageNormalizationHandler.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/PackageNormalizationHandler.java new file mode 100644 index 0000000000..a3ddfc8032 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/handlers/PackageNormalizationHandler.java @@ -0,0 +1,48 @@ +package org.splevo.jamopp.diffing.similarity.handlers; + +import java.util.Map; +import java.util.regex.Pattern; + +import org.splevo.diffing.util.NormalizationUtil; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; +import org.splevo.jamopp.diffing.similarity.requests.PackageNormalizationRequest; + +/** + * An {@link ISimilarityRequestHandler} that processes incoming + * {@link PackageNormalizationRequest} instances. + * + * @author atora + */ +public class PackageNormalizationHandler implements ISimilarityRequestHandler { + /** + * @see {@link JaMoPPDiffer#initSimilarityChecker(Map)} + */ + private Map packageNormalizations; + + /** + * Constructs an instance with the given parameter. + * + * @see {@link JaMoPPDiffer#initSimilarityChecker(Map)} + */ + public PackageNormalizationHandler(Map packageNormalizations) { + this.packageNormalizations = packageNormalizations; + } + + /** + * {@inheritDoc}
+ *
+ * Performs the requested normalisation and returns the result. + */ + @Override + public Object handleSimilarityRequest(ISimilarityRequest req) { + PackageNormalizationRequest castedR = (PackageNormalizationRequest) req; + + return NormalizationUtil.normalize((String) castedR.getParams(), this.packageNormalizations); + } + + @Override + public boolean canHandleSimilarityRequest(Class reqClass) { + return reqClass.equals(PackageNormalizationRequest.class); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/package-info.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/package-info.java index ffe7e8d00a..671572a11b 100644 --- a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/package-info.java +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/package-info.java @@ -1,4 +1,10 @@ /** - * Similarity definitions for the JaMoPP difference analysis. + * Contains similarity checking implementation for Java-Model elements generated + * by JaMoPP. Java-Model elements are stored in form of {@link EObject} + * instances and EMFtext is used for similarity checking.
+ *
+ * + * @see {@link org.splevo.jamopp.diffing.similarity.base}
+ * {@link org.splevo.jamopp.diffing.similarity.base.ecore} */ package org.splevo.jamopp.diffing.similarity; diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/ClassifierNormalizationRequest.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/ClassifierNormalizationRequest.java new file mode 100644 index 0000000000..5b549d77b7 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/ClassifierNormalizationRequest.java @@ -0,0 +1,30 @@ +package org.splevo.jamopp.diffing.similarity.requests; + +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; + +/** + * An {@link ISimilarityRequest}, which contains the qualified name of a + * {@link ConcreteClassifier} instance: {@code conCls.getQualifiedName()}. + * + * @author atora + */ +public class ClassifierNormalizationRequest implements ISimilarityRequest { + /** + * The qualified name of the {@link ConcreteClassifier}. + */ + private String toBeNormalized; + + /** + * Constructs an instance. + * + * @param toBeNormalized The qualified name of the {@link ConcreteClassifier} ({@code conCls.getQualifiedName()}) + */ + public ClassifierNormalizationRequest(String toBeNormalized) { + this.toBeNormalized = toBeNormalized; + } + + @Override + public Object getParams() { + return this.toBeNormalized; + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/CompilationUnitNormalizationRequest.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/CompilationUnitNormalizationRequest.java new file mode 100644 index 0000000000..54792c12d1 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/CompilationUnitNormalizationRequest.java @@ -0,0 +1,31 @@ +package org.splevo.jamopp.diffing.similarity.requests; + +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; + +/** + * An {@link ISimilarityRequest}, which contains the name of a + * {@link CompilationUnit} instance: {@code compUnit.name()}. + * + * @author atora + * + */ +public class CompilationUnitNormalizationRequest implements ISimilarityRequest { + /** + * The name of the {@link CompilationUnit}. + */ + private String toBeNormalized; + + /** + * Constructs an instance. + * + * @param toBeNormalized The name of the {@link CompilationUnit} ({@code compUnit.name()}). + */ + public CompilationUnitNormalizationRequest(String toBeNormalized) { + this.toBeNormalized = toBeNormalized; + } + + @Override + public Object getParams() { + return this.toBeNormalized; + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/NamespaceCheckRequest.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/NamespaceCheckRequest.java new file mode 100644 index 0000000000..e3a689308e --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/NamespaceCheckRequest.java @@ -0,0 +1,31 @@ +package org.splevo.jamopp.diffing.similarity.requests; + +import org.emftext.language.java.commons.NamespaceAwareElement; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; + +/** + * An {@link ISimilarityRequest}, which contains 2 {@link NamespaceAwareElement} + * instances. + * + * @author atora + */ +public class NamespaceCheckRequest implements ISimilarityRequest { + private NamespaceAwareElement ele1; + private NamespaceAwareElement ele2; + + /** + * Constructs an instance with the given parameters. + * + * @param ele1 The first element. + * @param ele2 The second element. + */ + public NamespaceCheckRequest(NamespaceAwareElement ele1, NamespaceAwareElement ele2) { + this.ele1 = ele1; + this.ele2 = ele2; + } + + @Override + public Object getParams() { + return new NamespaceAwareElement[] { this.ele1, this.ele2 }; + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/NamespaceNormalizationRequest.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/NamespaceNormalizationRequest.java new file mode 100644 index 0000000000..3055f4fdeb --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/NamespaceNormalizationRequest.java @@ -0,0 +1,33 @@ +package org.splevo.jamopp.diffing.similarity.requests; + +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; + +/** + * An {@link ISimilarityRequest}, which contains all namespaces of a + * {@link NamespaceAwareElement} instance as String: + * {@code nae.getNamespacesAsString()} + * + * @author atora + * + */ +public class NamespaceNormalizationRequest implements ISimilarityRequest { + /** + * All namespaces of the {@link NamespaceAwareElement} instance as String. + */ + private String toBeNormalized; + + /** + * Constructs an instance with the given parameter. + * + * @param toBeNormalized All namespaces of the {@link NamespaceAwareElement} + * instance as String ({@code nae.getNamespacesAsString()}) + */ + public NamespaceNormalizationRequest(String toBeNormalized) { + this.toBeNormalized = toBeNormalized; + } + + @Override + public Object getParams() { + return this.toBeNormalized; + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/NewSimilaritySwitchRequest.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/NewSimilaritySwitchRequest.java new file mode 100644 index 0000000000..189d80cb46 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/NewSimilaritySwitchRequest.java @@ -0,0 +1,35 @@ +package org.splevo.jamopp.diffing.similarity.requests; + +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; + +/** + * An {@link ISimilarityRequest}, which contains a flag (checkStatementPosition) + * that denotes, whether the new similarity switch created by processing this + * request should care about positions of statements while computing similarity. + * + * @author atora + */ +public class NewSimilaritySwitchRequest implements ISimilarityRequest { + /** + * The flag that denotes, whether the resulting new similarity switch should + * care about positions of statements while computing similarity. + */ + private boolean checkStatementPosition; + + /** + * Constructs an instance with the given parameter. + * + * @param checkStatementPosition The flag that denotes, whether the resulting + * new similarity switch should care about + * positions of statements while computing + * similarity. + */ + public NewSimilaritySwitchRequest(boolean checkStatementPosition) { + this.checkStatementPosition = checkStatementPosition; + } + + @Override + public Object getParams() { + return this.checkStatementPosition; + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/PackageNormalizationRequest.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/PackageNormalizationRequest.java new file mode 100644 index 0000000000..8142fefd4a --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/requests/PackageNormalizationRequest.java @@ -0,0 +1,35 @@ +package org.splevo.jamopp.diffing.similarity.requests; + +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest; + +/** + * An {@link ISimilarityRequest}, which contains the name of a + * {@link CompilationUnit} instance normalised via + * {@link CompilationUnitNormalizationRequest} first. + * + * @author atora + * + */ +public class PackageNormalizationRequest implements ISimilarityRequest { + /** + * The name of the {@link CompilationUnit} instance normalised via + * {@link CompilationUnitNormalizationRequest} first. + */ + private String toBeNormalized; + + /** + * Constructs an instance with the given parameter. + * + * @param toBeNormalized The name of the {@link CompilationUnit} instance + * normalised via + * {@link CompilationUnitNormalizationRequest} first. + */ + public PackageNormalizationRequest(String toBeNormalized) { + this.toBeNormalized = toBeNormalized; + } + + @Override + public Object getParams() { + return this.toBeNormalized; + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/AnnotationsSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/AnnotationsSimilaritySwitch.java new file mode 100644 index 0000000000..ceffa1f9e0 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/AnnotationsSimilaritySwitch.java @@ -0,0 +1,90 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.eclipse.emf.ecore.EObject; +import org.emftext.language.java.annotations.AnnotationAttributeSetting; +import org.emftext.language.java.annotations.AnnotationInstance; +import org.emftext.language.java.annotations.util.AnnotationsSwitch; +import org.emftext.language.java.classifiers.Classifier; +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +/** + * Similarity decisions for annotation elements. + */ +public class AnnotationsSimilaritySwitch extends AnnotationsSwitch implements ILoggableJavaSwitch, IJavaSimilarityPositionInnerSwitch { + private IJavaSimilaritySwitch similaritySwitch; + private boolean checkStatementPosition; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public boolean shouldCheckStatementPosition() { + return this.checkStatementPosition; + } + + @Override + public IJavaSimilaritySwitch getContainingSwitch() { + return this.similaritySwitch; + } + + public AnnotationsSimilaritySwitch(IJavaSimilaritySwitch similaritySwitch, boolean checkStatementPosition) { + this.similaritySwitch = similaritySwitch; + this.checkStatementPosition = checkStatementPosition; + } + + @Override + public Boolean caseAnnotationInstance(AnnotationInstance instance1) { + this.logMessage("caseAnnotationInstance"); + + AnnotationInstance instance2 = (AnnotationInstance) this.getCompareElement(); + this.logComparison( + instance1.getAnnotation(), + instance2.getAnnotation(), + AnnotationInstance.class.getSimpleName()); + + Classifier class1 = instance1.getAnnotation(); + Classifier class2 = instance2.getAnnotation(); + Boolean classifierSimilarity = this.isSimilar(class1, class2); + this.logResult(classifierSimilarity, Classifier.class.getSimpleName()); + if (classifierSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + String namespace1 = instance1.getNamespacesAsString(); + String namespace2 = instance2.getNamespacesAsString(); + this.logComparison(namespace1, namespace2, "namespace"); + if (namespace1 == null) { + this.logResult(namespace2 == null, "namespace"); + return (namespace2 == null); + } else { + this.logResult(namespace1.equals(namespace2), "namespace"); + return (namespace1.equals(namespace2)); + } + } + + @Override + public Boolean caseAnnotationAttributeSetting(AnnotationAttributeSetting setting1) { + this.logMessage("caseAnnotationAttributeSetting"); + + AnnotationAttributeSetting setting2 = (AnnotationAttributeSetting) this.getCompareElement(); + this.logComparison(setting1.getAttribute(), setting2.getAttribute(), AnnotationAttributeSetting.class.getSimpleName()); + Boolean similarity = this.isSimilar(setting1.getAttribute(), setting2.getAttribute()); + this.logResult(similarity, AnnotationAttributeSetting.class.getSimpleName()); + if (similarity == Boolean.FALSE) { + return Boolean.FALSE; + } + return Boolean.TRUE; + } + + @Override + public Boolean defaultCase(EObject object) { + this.logMessage("defaultCase for Annotation"); + + this.logMessage("Default annotation comparing case for "+AnnotationsSimilaritySwitch.class.getSimpleName()+", similarity: true"); + return Boolean.TRUE; + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ArraysSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ArraysSimilaritySwitch.java new file mode 100644 index 0000000000..5dc5aee00f --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ArraysSimilaritySwitch.java @@ -0,0 +1,21 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.eclipse.emf.ecore.EObject; +import org.emftext.language.java.arrays.util.ArraysSwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; + +/** + * Similarity decision for array elements. + *

+ * All array elements are strongly typed. They have no identifying attributes. Their location + * and runtime type are assumed to be checked before this switch is called. So nothing to check + * here. + */ +public class ArraysSimilaritySwitch extends ArraysSwitch implements ILoggableJavaSwitch { + @Override + public Boolean defaultCase(EObject object) { + this.logMessage("defaultCase for Array"); + + return Boolean.TRUE; + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ClassifiersSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ClassifiersSimilaritySwitch.java new file mode 100644 index 0000000000..24c3a3c038 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ClassifiersSimilaritySwitch.java @@ -0,0 +1,72 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.emftext.language.java.classifiers.AnonymousClass; +import org.emftext.language.java.classifiers.ConcreteClassifier; +import org.emftext.language.java.classifiers.util.ClassifiersSwitch; +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +import com.google.common.base.Strings; + +/** + * Similarity decisions for classifier elements. + */ +public class ClassifiersSimilaritySwitch extends ClassifiersSwitch implements ILoggableJavaSwitch, IJavaSimilarityPositionInnerSwitch { + private IJavaSimilaritySwitch similaritySwitch; + private boolean checkStatementPosition; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public boolean shouldCheckStatementPosition() { + return this.checkStatementPosition; + } + + @Override + public IJavaSimilaritySwitch getContainingSwitch() { + return this.similaritySwitch; + } + + public ClassifiersSimilaritySwitch(IJavaSimilaritySwitch similaritySwitch, boolean checkStatementPosition) { + this.similaritySwitch = similaritySwitch; + this.checkStatementPosition = checkStatementPosition; + } + + /** + * Concrete classifiers such as classes and interface are identified by their location and + * name. The location is considered implicitly. + * + * @param classifier1 + * the classifier to compare with the compareelement + * @return True or false whether they are similar or not. + */ + @Override + public Boolean caseConcreteClassifier(ConcreteClassifier classifier1) { + this.logMessage("caseConcreteClassifier"); + + ConcreteClassifier classifier2 = (ConcreteClassifier) this.getCompareElement(); + + String name1 = this.normalizeClassifier(classifier1.getQualifiedName()); + String name2 = Strings.nullToEmpty(classifier2.getQualifiedName()); + + return (name1.equals(name2)); + } + + /** + * Anonymous classes are considered to be similar. + * + * @param anon the anonymous class to compare with the compare element. + * @return true. + */ + @Override + public Boolean caseAnonymousClass(AnonymousClass anon) { + this.logMessage("caseAnonymousClass"); + + return Boolean.TRUE; + } + +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/CommonsSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/CommonsSimilaritySwitch.java new file mode 100644 index 0000000000..38fb70cb04 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/CommonsSimilaritySwitch.java @@ -0,0 +1,57 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.emftext.language.java.commons.NamedElement; +import org.emftext.language.java.commons.util.CommonsSwitch; +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +/** + * Similarity decisions for commons elements. + */ +public class CommonsSimilaritySwitch extends CommonsSwitch implements ILoggableJavaSwitch, IJavaSimilarityPositionInnerSwitch { + private IJavaSimilaritySwitch similaritySwitch; + private boolean checkStatementPosition; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public boolean shouldCheckStatementPosition() { + return this.checkStatementPosition; + } + + @Override + public IJavaSimilaritySwitch getContainingSwitch() { + return this.similaritySwitch; + } + + public CommonsSimilaritySwitch(IJavaSimilaritySwitch similaritySwitch, boolean checkStatementPosition) { + this.similaritySwitch = similaritySwitch; + this.checkStatementPosition = checkStatementPosition; + } + + /** + * Check named element + * + * Similarity is defined by the names of the elements. + * + * @param element1 + * The method call to compare with the compare element. + * @return True As null always means null. + */ + @Override + public Boolean caseNamedElement(NamedElement element1) { + this.logMessage("caseNamedElement"); + + NamedElement element2 = (NamedElement) this.getCompareElement(); + + if (element1.getName() == null) { + return (element2.getName() == null); + } + + return (element1.getName().equals(element2.getName())); + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ContainersSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ContainersSimilaritySwitch.java new file mode 100644 index 0000000000..ab98afce0c --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ContainersSimilaritySwitch.java @@ -0,0 +1,137 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.emftext.language.java.containers.CompilationUnit; +import org.emftext.language.java.containers.Package; +import org.emftext.language.java.containers.util.ContainersSwitch; +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; +import org.splevo.jamopp.diffing.util.JaMoPPModelUtil; + +import com.google.common.base.Strings; + +/** + * Similarity decisions for container elements. + */ +public class ContainersSimilaritySwitch extends ContainersSwitch implements ILoggableJavaSwitch, IJavaSimilarityPositionInnerSwitch { + private IJavaSimilaritySwitch similaritySwitch; + private boolean checkStatementPosition; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public boolean shouldCheckStatementPosition() { + return this.checkStatementPosition; + } + + @Override + public IJavaSimilaritySwitch getContainingSwitch() { + return this.similaritySwitch; + } + + public ContainersSimilaritySwitch(IJavaSimilaritySwitch similaritySwitch, boolean checkStatementPosition) { + this.similaritySwitch = similaritySwitch; + this.checkStatementPosition = checkStatementPosition; + } + + /** + * Check the similarity of two CompilationUnits.
+ * Similarity is checked by + *

    + *
  • Comparing their names (including renamings)
  • + *
  • Comparing their namespaces' values (including renamings)
  • + *
+ * Note: CompilationUnit names are full qualified. So it is important to apply classifier as + * well as package renaming normalizations to them. + * + * @param unit1 + * The compilation unit to compare with the compareElement. + * @return True/False whether they are similar or not. + */ + @Override + public Boolean caseCompilationUnit(CompilationUnit unit1) { + this.logMessage("caseCompilationUnit"); + + CompilationUnit unit2 = (CompilationUnit) this.getCompareElement(); + this.logComparison(unit1.getName(), unit2.getName(), CompilationUnit.class.getSimpleName()); + + String name1 = this.normalizeCompilationUnit(unit1.getName()); + name1 = this.normalizePackage(name1); + String name2 = unit2.getName(); + + this.logResult(name1.equals(name2), "compilation unit name"); + if (!name1.equals(name2)) { + return Boolean.FALSE; + } + + String namespaceString1 = this.normalizeNamespace(unit1.getNamespacesAsString()); + String namespaceString2 = Strings.nullToEmpty(unit2.getNamespacesAsString()); + + this.logResult(namespaceString1.equals(namespaceString2), "compilation unit namespace"); + + if (!namespaceString1.equals(namespaceString2)) { + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + + /** + * Check package similarity.
+ * Similarity is checked by + *
    + *
  • full qualified package path
  • + *
+ * + * @param package1 + * The package to compare with the compare element. + * @return True/False if the packages are similar or not. + */ + @Override + public Boolean casePackage(Package package1) { + this.logMessage("casePackage"); + + Package package2 = (Package) this.getCompareElement(); + this.logComparison(package1, package2, Package.class.getSimpleName()); + + String packagePath1 = JaMoPPModelUtil.buildNamespacePath(package1); + packagePath1 = this.normalizeNamespace(packagePath1); + String packagePath2 = JaMoPPModelUtil.buildNamespacePath(package2); + + this.logComparison(packagePath1, packagePath2, "package namespace"); + this.logResult(packagePath1.equals(packagePath2), "package path"); + + if (!packagePath1.equals(packagePath2)) { + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + + /** + * Check module similarity.
+ * Similarity is checked by + *
    + *
  • module names
  • + *
+ * + * @param module1 The module to compare with the compare element. + * @return True/False if the modules are similar or not. + */ + @Override + public Boolean caseModule(org.emftext.language.java.containers.Module module1) { + this.logMessage("caseModule"); + + org.emftext.language.java.containers.Module module2 = + (org.emftext.language.java.containers.Module) this.getCompareElement(); + + this.logResult(module1.getName().equals(module2.getName()), org.emftext.language.java.containers.Module.class.getSimpleName()); + if (!module1.getName().equals(module2.getName())) { + return Boolean.FALSE; + } + return Boolean.TRUE; + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ExpressionsSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ExpressionsSimilaritySwitch.java new file mode 100644 index 0000000000..d444317384 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ExpressionsSimilaritySwitch.java @@ -0,0 +1,259 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EObject; +import org.emftext.language.java.expressions.AdditiveExpression; +import org.emftext.language.java.expressions.AndExpression; +import org.emftext.language.java.expressions.AndExpressionChild; +import org.emftext.language.java.expressions.AssignmentExpression; +import org.emftext.language.java.expressions.AssignmentExpressionChild; +import org.emftext.language.java.expressions.ConditionalAndExpression; +import org.emftext.language.java.expressions.ConditionalAndExpressionChild; +import org.emftext.language.java.expressions.ConditionalOrExpression; +import org.emftext.language.java.expressions.ConditionalOrExpressionChild; +import org.emftext.language.java.expressions.EqualityExpression; +import org.emftext.language.java.expressions.EqualityExpressionChild; +import org.emftext.language.java.expressions.Expression; +import org.emftext.language.java.expressions.InstanceOfExpression; +import org.emftext.language.java.expressions.InstanceOfExpressionChild; +import org.emftext.language.java.expressions.NestedExpression; +import org.emftext.language.java.expressions.RelationExpression; +import org.emftext.language.java.expressions.RelationExpressionChild; +import org.emftext.language.java.expressions.UnaryExpression; +import org.emftext.language.java.expressions.UnaryExpressionChild; +import org.emftext.language.java.expressions.util.ExpressionsSwitch; +import org.emftext.language.java.operators.AssignmentOperator; +import org.emftext.language.java.operators.EqualityOperator; +import org.emftext.language.java.operators.RelationOperator; +import org.emftext.language.java.operators.UnaryOperator; +import org.emftext.language.java.types.TypeReference; +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +/** + * Similarity decisions for expression elements. + *

+ * All expression elements are strong typed with no identifying attributes or non-containment + * references. Their location and runtime types are assumed to be checked before this switch is + * called. + *

+ */ +public class ExpressionsSimilaritySwitch extends ExpressionsSwitch implements ILoggableJavaSwitch, IJavaSimilarityPositionInnerSwitch { + private IJavaSimilaritySwitch similaritySwitch; + private boolean checkStatementPosition; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public boolean shouldCheckStatementPosition() { + return this.checkStatementPosition; + } + + @Override + public IJavaSimilaritySwitch getContainingSwitch() { + return this.similaritySwitch; + } + + public ExpressionsSimilaritySwitch(IJavaSimilaritySwitch similaritySwitch, boolean checkStatementPosition) { + this.similaritySwitch = similaritySwitch; + this.checkStatementPosition = checkStatementPosition; + } + + @Override + public Boolean caseAssignmentExpression(AssignmentExpression exp1) { + this.logMessage("caseAssignmentExpression"); + + AssignmentExpression exp2 = (AssignmentExpression) this.getCompareElement(); + + AssignmentExpressionChild child1 = exp1.getChild(); + AssignmentExpressionChild child2 = exp2.getChild(); + Boolean childSimilarity = this.isSimilar(child1, child2); + if (childSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + AssignmentOperator op1 = exp1.getAssignmentOperator(); + AssignmentOperator op2 = exp2.getAssignmentOperator(); + Boolean operatorSimilarity = this.isSimilar(op1, op2); + if (operatorSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + Expression value1 = exp1.getValue(); + Expression value2 = exp2.getValue(); + Boolean valueSimilarity = this.isSimilar(value1, value2); + if (valueSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + + @Override + public Boolean caseEqualityExpression(EqualityExpression exp1) { + this.logMessage("caseEqualityExpression"); + + EqualityExpression exp2 = (EqualityExpression) this.getCompareElement(); + + // check operator equality + EList operators1 = exp1.getEqualityOperators(); + EList operators2 = exp2.getEqualityOperators(); + Boolean operatorSimilarity = this.areSimilar(operators1, operators2); + if (operatorSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + // check expression equality + EList children1 = exp1.getChildren(); + EList children2 = exp2.getChildren(); + Boolean childSimilarity = this.areSimilar(children1, children2); + if (childSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + + @Override + public Boolean caseRelationExpression(RelationExpression exp1) { + this.logMessage("caseRelationExpression"); + + RelationExpression exp2 = (RelationExpression) this.getCompareElement(); + + // check operator equality + EList operators1 = exp1.getRelationOperators(); + EList operators2 = exp2.getRelationOperators(); + Boolean operatorSimilarity = this.areSimilar(operators1, operators2); + if (operatorSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + // check expression equality + EList children1 = exp1.getChildren(); + EList children2 = exp2.getChildren(); + Boolean childSimilarity = this.areSimilar(children1, children2); + if (childSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + + @Override + public Boolean caseAndExpression(AndExpression exp1) { + this.logMessage("caseAndExpression"); + + AndExpression exp2 = (AndExpression) this.getCompareElement(); + + // check expression equality + EList children1 = exp1.getChildren(); + EList children2 = exp2.getChildren(); + Boolean childSimilarity = this.areSimilar(children1, children2); + if (childSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + + @Override + public Boolean caseUnaryExpression(UnaryExpression exp1) { + this.logMessage("caseUnaryExpression"); + + UnaryExpression exp2 = (UnaryExpression) this.getCompareElement(); + + // check operator equality + EList operators1 = exp1.getOperators(); + EList operators2 = exp2.getOperators(); + Boolean operatorSimilarity = this.areSimilar(operators1, operators2); + if (operatorSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + // check expression equality + UnaryExpressionChild child1 = exp1.getChild(); + UnaryExpressionChild child2 = exp2.getChild(); + return this.isSimilar(child1, child2); + } + + @Override + public Boolean caseAdditiveExpression(AdditiveExpression exp1) { + this.logMessage("caseAdditiveExpression"); + + AdditiveExpression exp2 = (AdditiveExpression) this.getCompareElement(); + + Boolean opSimilarity = this.areSimilar(exp1.getAdditiveOperators(), exp2.getAdditiveOperators()); + if (opSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + return this.areSimilar(exp1.getChildren(), exp2.getChildren()); + } + + @Override + public Boolean caseInstanceOfExpression(InstanceOfExpression exp1) { + this.logMessage("caseInstanceOfExpression"); + + InstanceOfExpression exp2 = (InstanceOfExpression) this.getCompareElement(); + + // check type equality + TypeReference typeReference1 = exp1.getTypeReference(); + TypeReference typeReference2 = exp2.getTypeReference(); + Boolean typeSimilarity = this.isSimilar(typeReference1, typeReference2); + if (typeSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + // check expression equality + InstanceOfExpressionChild child1 = exp1.getChild(); + InstanceOfExpressionChild child2 = exp2.getChild(); + return this.isSimilar(child1, child2); + } + + @Override + public Boolean caseConditionalOrExpression(ConditionalOrExpression exp1) { + this.logMessage("caseConditionalOrExpression"); + + ConditionalOrExpression exp2 = (ConditionalOrExpression) this.getCompareElement(); + + // check expression equality + EList children1 = exp1.getChildren(); + EList children2 = exp2.getChildren(); + return this.areSimilar(children1, children2); + } + + @Override + public Boolean caseConditionalAndExpression(ConditionalAndExpression exp1) { + this.logMessage("caseConditionalAndExpression"); + + ConditionalAndExpression exp2 = (ConditionalAndExpression) this.getCompareElement(); + + // check expression equality + EList children1 = exp1.getChildren(); + EList children2 = exp2.getChildren(); + return this.areSimilar(children1, children2); + } + + @Override + public Boolean caseNestedExpression(NestedExpression exp1) { + this.logMessage("caseNestedExpression"); + + NestedExpression exp2 = (NestedExpression) this.getCompareElement(); + + // check expression equality + Expression childExp1 = exp1.getExpression(); + Expression childExp2 = exp2.getExpression(); + return this.isSimilar(childExp1, childExp2); + } + + @Override + public Boolean defaultCase(EObject object) { + this.logMessage("defaultCase for Expression"); + + return Boolean.TRUE; + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/GenericsSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/GenericsSimilaritySwitch.java new file mode 100644 index 0000000000..5b176f9c98 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/GenericsSimilaritySwitch.java @@ -0,0 +1,83 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.emftext.language.java.generics.ExtendsTypeArgument; +import org.emftext.language.java.generics.QualifiedTypeArgument; +import org.emftext.language.java.generics.SuperTypeArgument; +import org.emftext.language.java.generics.TypeParameter; +import org.emftext.language.java.generics.UnknownTypeArgument; +import org.emftext.language.java.generics.util.GenericsSwitch; +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +/** + * Similarity decisions for the generic elements. + */ +public class GenericsSimilaritySwitch extends GenericsSwitch implements ILoggableJavaSwitch, IJavaSimilarityPositionInnerSwitch { + private IJavaSimilaritySwitch similaritySwitch; + private boolean checkStatementPosition; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public boolean shouldCheckStatementPosition() { + return this.checkStatementPosition; + } + + @Override + public IJavaSimilaritySwitch getContainingSwitch() { + return this.similaritySwitch; + } + + public GenericsSimilaritySwitch(IJavaSimilaritySwitch similaritySwitch, boolean checkStatementPosition) { + this.similaritySwitch = similaritySwitch; + this.checkStatementPosition = checkStatementPosition; + } + + @Override + public Boolean caseQualifiedTypeArgument(QualifiedTypeArgument qta1) { + this.logMessage("caseQualifiedTypeArgument"); + + QualifiedTypeArgument qta2 = (QualifiedTypeArgument) this.getCompareElement(); + return this.isSimilar(qta1.getTypeReference(), qta2.getTypeReference()); + } + + @Override + public Boolean caseSuperTypeArgument(SuperTypeArgument sta1) { + this.logMessage("caseSuperTypeArgument"); + + SuperTypeArgument sta2 = (SuperTypeArgument) this.getCompareElement(); + return this.isSimilar(sta1.getSuperType(), sta2.getSuperType()); + } + + @Override + public Boolean caseExtendsTypeArgument(ExtendsTypeArgument eta1) { + this.logMessage("caseExtendsTypeArgument"); + + ExtendsTypeArgument eta2 = (ExtendsTypeArgument) this.getCompareElement(); + return this.isSimilar(eta1.getExtendType(), eta2.getExtendType()); + } + + @Override + public Boolean caseUnknownTypeArgument(UnknownTypeArgument arg) { + this.logMessage("caseUnknownTypeArgument"); + + return Boolean.TRUE; + } + + @Override + public Boolean caseTypeParameter(TypeParameter param1) { + this.logMessage("caseTypeParameter"); + + TypeParameter param2 = (TypeParameter) this.getCompareElement(); + + if (!param1.getName().equals(param2.getName())) { + return Boolean.FALSE; + } + + return this.areSimilar(param1.getExtendTypes(), param2.getExtendTypes()); + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/IJavaSimilarityInnerSwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/IJavaSimilarityInnerSwitch.java new file mode 100644 index 0000000000..66668b714a --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/IJavaSimilarityInnerSwitch.java @@ -0,0 +1,67 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.emftext.language.java.commons.NamespaceAwareElement; +import org.splevo.jamopp.diffing.similarity.base.ecore.IInnerSwitch; +import org.splevo.jamopp.diffing.similarity.requests.ClassifierNormalizationRequest; +import org.splevo.jamopp.diffing.similarity.requests.CompilationUnitNormalizationRequest; +import org.splevo.jamopp.diffing.similarity.requests.NamespaceCheckRequest; +import org.splevo.jamopp.diffing.similarity.requests.NamespaceNormalizationRequest; +import org.splevo.jamopp.diffing.similarity.requests.PackageNormalizationRequest; + +/** + * An interface that contains default methods, which create and send + * {@link ISimilarityRequest} instances to {@link ISimilarityRequestHandler} + * instances that are supposed to handle them.
+ *
+ * These methods can be used to spare code duplication in inner switches, which + * need them. + * + * @author atora + */ +public interface IJavaSimilarityInnerSwitch extends IInnerSwitch { + /** + * Sends out a {@link ClassifierNormalizationRequest} and returns the result. + * + * @see {@link #handleSimilarityRequest(org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest)} + */ + public default String normalizeClassifier(String origin) { + return (String) this.handleSimilarityRequest(new ClassifierNormalizationRequest(origin)); + } + + /** + * Sends out a {@link CompilationUnitNormalizationRequest} and returns the + * result. + * + * @see {@link #handleSimilarityRequest(org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest)} + */ + public default String normalizeCompilationUnit(String origin) { + return (String) this.handleSimilarityRequest(new CompilationUnitNormalizationRequest(origin)); + } + + /** + * Sends out a {@link PackageNormalizationRequest} and returns the result. + * + * @see {@link #handleSimilarityRequest(org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest)} + */ + public default String normalizePackage(String origin) { + return (String) this.handleSimilarityRequest(new PackageNormalizationRequest(origin)); + } + + /** + * Sends out a {@link NamespaceNormalizationRequest} and returns the result. + * + * @see {@link #handleSimilarityRequest(org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest)} + */ + public default String normalizeNamespace(String origin) { + return (String) this.handleSimilarityRequest(new NamespaceNormalizationRequest(origin)); + } + + /** + * Sends out a {@link NamespaceCheckRequest} and returns the result. + * + * @see {@link #handleSimilarityRequest(org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest)} + */ + public default Boolean compareNamespacesByPart(NamespaceAwareElement ele1, NamespaceAwareElement ele2) { + return (Boolean) this.handleSimilarityRequest(new NamespaceCheckRequest(ele1, ele2)); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/IJavaSimilarityPositionInnerSwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/IJavaSimilarityPositionInnerSwitch.java new file mode 100644 index 0000000000..ae669f191b --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/IJavaSimilarityPositionInnerSwitch.java @@ -0,0 +1,25 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.base.ecore.IPositionInnerSwitch; +import org.splevo.jamopp.diffing.similarity.requests.NewSimilaritySwitchRequest; + +/** + * An interface that bundles and complements {@link IJavaSimilarityInnerSwitch} + * and {@link IPositionInnerSwitch} interfaces. Contains methods, which are + * specific to computing similarity in the context of Java model elements. + * + * @author atora + * + */ +public interface IJavaSimilarityPositionInnerSwitch extends IJavaSimilarityInnerSwitch, IPositionInnerSwitch { + /** + * Sends out a {@link NewSimilaritySwitchRequest} and returns the result. + * + * @see {@link #handleSimilarityRequest(org.splevo.jamopp.diffing.similarity.base.ISimilarityRequest)} + */ + public default IJavaSimilaritySwitch requestNewSwitch(boolean checkStatementPosition) { + return (IJavaSimilaritySwitch) this + .handleSimilarityRequest(new NewSimilaritySwitchRequest(checkStatementPosition)); + } +} diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ImportsSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ImportsSimilaritySwitch.java new file mode 100644 index 0000000000..40c6335052 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ImportsSimilaritySwitch.java @@ -0,0 +1,78 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.emftext.language.java.imports.ClassifierImport; +import org.emftext.language.java.imports.StaticMemberImport; +import org.emftext.language.java.imports.util.ImportsSwitch; +import org.emftext.language.java.references.ReferenceableElement; +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +import com.google.common.base.Strings; + +/** + * Similarity decisions for the import elements. + */ +public class ImportsSimilaritySwitch extends ImportsSwitch implements ILoggableJavaSwitch, IJavaSimilarityPositionInnerSwitch { + private IJavaSimilaritySwitch similaritySwitch; + private boolean checkStatementPosition; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public boolean shouldCheckStatementPosition() { + return this.checkStatementPosition; + } + + @Override + public IJavaSimilaritySwitch getContainingSwitch() { + return this.similaritySwitch; + } + + public ImportsSimilaritySwitch(IJavaSimilaritySwitch similaritySwitch, boolean checkStatementPosition) { + this.similaritySwitch = similaritySwitch; + this.checkStatementPosition = checkStatementPosition; + } + + @Override + public Boolean caseClassifierImport(ClassifierImport import1) { + this.logMessage("caseClassifierImport"); + + ClassifierImport import2 = (ClassifierImport) this.getCompareElement(); + + Boolean similarity = this.isSimilar(import1.getClassifier(), import2.getClassifier()); + if (similarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + String namespace1 = Strings.nullToEmpty(import1.getNamespacesAsString()); + String namespace2 = Strings.nullToEmpty(import2.getNamespacesAsString()); + return (namespace1.equals(namespace2)); + } + + @Override + public Boolean caseStaticMemberImport(StaticMemberImport import1) { + this.logMessage("caseStaticMemberImport"); + + StaticMemberImport import2 = (StaticMemberImport) this.getCompareElement(); + + if (import1.getStaticMembers().size() != import2.getStaticMembers().size()) { + return Boolean.FALSE; + } + for (int i = 0; i < import1.getStaticMembers().size(); i++) { + ReferenceableElement member1 = import1.getStaticMembers().get(i); + ReferenceableElement member2 = import2.getStaticMembers().get(i); + Boolean similarity = this.isSimilar(member1, member2); + if (similarity == Boolean.FALSE) { + return Boolean.FALSE; + } + } + + String namespace1 = Strings.nullToEmpty(import1.getNamespacesAsString()); + String namespace2 = Strings.nullToEmpty(import2.getNamespacesAsString()); + return (namespace1.equals(namespace2)); + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/InstantiationsSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/InstantiationsSimilaritySwitch.java new file mode 100644 index 0000000000..4e78a5b812 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/InstantiationsSimilaritySwitch.java @@ -0,0 +1,120 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EObject; +import org.emftext.language.java.expressions.Expression; +import org.emftext.language.java.instantiations.ExplicitConstructorCall; +import org.emftext.language.java.instantiations.NewConstructorCall; +import org.emftext.language.java.instantiations.util.InstantiationsSwitch; +import org.emftext.language.java.types.Type; +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +/** + * Similarity decisions for object instantiation elements. + */ +public class InstantiationsSimilaritySwitch extends InstantiationsSwitch implements ILoggableJavaSwitch, IJavaSimilarityPositionInnerSwitch { + private IJavaSimilaritySwitch similaritySwitch; + private boolean checkStatementPosition; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public boolean shouldCheckStatementPosition() { + return this.checkStatementPosition; + } + + @Override + public IJavaSimilaritySwitch getContainingSwitch() { + return this.similaritySwitch; + } + + public InstantiationsSimilaritySwitch(IJavaSimilaritySwitch similaritySwitch, boolean checkStatementPosition) { + this.similaritySwitch = similaritySwitch; + this.checkStatementPosition = checkStatementPosition; + } + + /** + * Check class instance creation similarity.
+ * Similarity is checked by + *
    + *
  • instance type similarity
  • + *
  • number of constructor arguments
  • + *
  • types of constructor arguments
  • + *
+ * + * @param call1 + * The class instance creation to compare with the compare element. + * @return True/False if the class instance creations are similar or not. + */ + @Override + public Boolean caseExplicitConstructorCall(ExplicitConstructorCall call1) { + this.logMessage("caseExplicitConstructorCall"); + + ExplicitConstructorCall call2 = (ExplicitConstructorCall) this.getCompareElement(); + + // check the class instance types + Boolean typeSimilarity = this.isSimilar(call1.getCallTarget(), call2.getCallTarget()); + if (typeSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + // check number of type arguments + EList cic1Args = call1.getArguments(); + EList cic2Args = call2.getArguments(); + if (cic1Args.size() != cic2Args.size()) { + return Boolean.FALSE; + } + + // check the argument similarity + for (int i = 0; i < cic1Args.size(); i++) { + Boolean argumentSimilarity = this.isSimilar(cic1Args.get(i), cic2Args.get(i)); + if (argumentSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + } + + return Boolean.TRUE; + } + + @Override + public Boolean caseNewConstructorCall(NewConstructorCall call1) { + this.logMessage("caseNewConstructorCall"); + + NewConstructorCall call2 = (NewConstructorCall) this.getCompareElement(); + + Type type1 = call1.getTypeReference().getTarget(); + Type type2 = call2.getTypeReference().getTarget(); + Boolean typeSimilarity = this.isSimilar(type1, type2); + if (typeSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + EList types1 = call1.getArguments(); + EList types2 = call2.getArguments(); + if (types1.size() != types2.size()) { + return Boolean.FALSE; + } + for (int i = 0; i < types1.size(); i++) { + Expression argType1 = types1.get(i); + Expression argType2 = types2.get(i); + Boolean similarity = this.isSimilar(argType1, argType2); + if (similarity == Boolean.FALSE) { + return Boolean.FALSE; + } + } + + return Boolean.TRUE; + } + + @Override + public Boolean defaultCase(EObject object) { + this.logMessage("defaultCase for Instantiation"); + + return Boolean.TRUE; + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/LayoutSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/LayoutSimilaritySwitch.java new file mode 100644 index 0000000000..c4fd77ee36 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/LayoutSimilaritySwitch.java @@ -0,0 +1,18 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.eclipse.emf.ecore.EObject; +import org.emftext.commons.layout.util.LayoutSwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; + +/** + * Similarity Decisions for layout information is always true as they are not considered for + * now. + */ +public class LayoutSimilaritySwitch extends LayoutSwitch implements ILoggableJavaSwitch { + @Override + public Boolean defaultCase(EObject object) { + this.logMessage("defaultCase for Layout"); + + return Boolean.TRUE; + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/LiteralsSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/LiteralsSimilaritySwitch.java new file mode 100644 index 0000000000..679a88e23a --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/LiteralsSimilaritySwitch.java @@ -0,0 +1,174 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.eclipse.emf.ecore.EObject; +import org.emftext.language.java.literals.BinaryIntegerLiteral; +import org.emftext.language.java.literals.BinaryLongLiteral; +import org.emftext.language.java.literals.BooleanLiteral; +import org.emftext.language.java.literals.CharacterLiteral; +import org.emftext.language.java.literals.DecimalDoubleLiteral; +import org.emftext.language.java.literals.DecimalFloatLiteral; +import org.emftext.language.java.literals.DecimalIntegerLiteral; +import org.emftext.language.java.literals.DecimalLongLiteral; +import org.emftext.language.java.literals.HexDoubleLiteral; +import org.emftext.language.java.literals.HexFloatLiteral; +import org.emftext.language.java.literals.HexIntegerLiteral; +import org.emftext.language.java.literals.HexLongLiteral; +import org.emftext.language.java.literals.OctalIntegerLiteral; +import org.emftext.language.java.literals.OctalLongLiteral; +import org.emftext.language.java.literals.util.LiteralsSwitch; +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +/** + * Similarity decisions for literal elements. + */ +public class LiteralsSimilaritySwitch extends LiteralsSwitch implements ILoggableJavaSwitch, IJavaSimilarityInnerSwitch { + private IJavaSimilaritySwitch similaritySwitch; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public IJavaSimilaritySwitch getContainingSwitch() { + return this.similaritySwitch; + } + + public LiteralsSimilaritySwitch(IJavaSimilaritySwitch similaritySwitch) { + this.similaritySwitch = similaritySwitch; + } + + @Override + public Boolean caseBooleanLiteral(BooleanLiteral boolean1) { + this.logMessage("caseBooleanLiteral"); + + BooleanLiteral boolean2 = (BooleanLiteral) this.getCompareElement(); + return (boolean1.isValue() == boolean2.isValue()); + } + + @Override + public Boolean caseCharacterLiteral(CharacterLiteral char1) { + this.logMessage("caseCharacterLiteral"); + + CharacterLiteral char2 = (CharacterLiteral) this.getCompareElement(); + return char1.getValue().equals(char2.getValue()); + } + + @Override + public Boolean caseDecimalFloatLiteral(DecimalFloatLiteral float1) { + this.logMessage("caseDecimalFloatLiteral"); + + DecimalFloatLiteral float2 = (DecimalFloatLiteral) this.getCompareElement(); + return compareDouble(float1.getDecimalValue(), float2.getDecimalValue()); + } + + @Override + public Boolean caseHexFloatLiteral(HexFloatLiteral float1) { + this.logMessage("caseHexFloatLiteral"); + + HexFloatLiteral float2 = (HexFloatLiteral) this.getCompareElement(); + return compareDouble(float1.getHexValue(), float2.getHexValue()); + } + + @Override + public Boolean caseDecimalDoubleLiteral(DecimalDoubleLiteral double1) { + this.logMessage("caseDecimalDoubleLiteral"); + + DecimalDoubleLiteral double2 = (DecimalDoubleLiteral) this.getCompareElement(); + return compareDouble(double1.getDecimalValue(), double2.getDecimalValue()); + } + + @Override + public Boolean caseHexDoubleLiteral(HexDoubleLiteral double1) { + this.logMessage("caseHexDoubleLiteral"); + + HexDoubleLiteral double2 = (HexDoubleLiteral) this.getCompareElement(); + return compareDouble(double1.getHexValue(), double2.getHexValue()); + } + + private boolean compareDouble(double d1, double d2) { + return d1 == d2 || Double.isNaN(d1) && Double.isNaN(d2); + } + + @Override + public Boolean caseDecimalIntegerLiteral(DecimalIntegerLiteral int1) { + this.logMessage("caseDecimalIntegerLiteral"); + + DecimalIntegerLiteral int2 = (DecimalIntegerLiteral) this.getCompareElement(); + return (int1.getDecimalValue().equals(int2.getDecimalValue())); + } + + @Override + public Boolean caseHexIntegerLiteral(HexIntegerLiteral int1) { + this.logMessage("caseHexIntegerLiteral"); + + HexIntegerLiteral int2 = (HexIntegerLiteral) this.getCompareElement(); + return (int1.getHexValue().equals(int2.getHexValue())); + } + + @Override + public Boolean caseOctalIntegerLiteral(OctalIntegerLiteral int1) { + this.logMessage("caseOctalIntegerLiteral"); + + OctalIntegerLiteral int2 = (OctalIntegerLiteral) this.getCompareElement(); + return (int1.getOctalValue().equals(int2.getOctalValue())); + } + + @Override + public Boolean caseDecimalLongLiteral(DecimalLongLiteral long1) { + this.logMessage("caseDecimalLongLiteral"); + + DecimalLongLiteral long2 = (DecimalLongLiteral) this.getCompareElement(); + return (long1.getDecimalValue().equals(long2.getDecimalValue())); + } + + @Override + public Boolean caseHexLongLiteral(HexLongLiteral long1) { + this.logMessage("caseHexLongLiteral"); + + HexLongLiteral long2 = (HexLongLiteral) this.getCompareElement(); + return (long1.getHexValue().equals(long2.getHexValue())); + } + + @Override + public Boolean caseOctalLongLiteral(OctalLongLiteral long1) { + this.logMessage("caseOctalLongLiteral"); + + OctalLongLiteral long2 = (OctalLongLiteral) this.getCompareElement(); + return (long1.getOctalValue().equals(long2.getOctalValue())); + } + + @Override + public Boolean caseBinaryLongLiteral(BinaryLongLiteral long1) { + this.logMessage("caseBinaryLongLiteral"); + + BinaryLongLiteral long2 = (BinaryLongLiteral) this.getCompareElement(); + return long1.getBinaryValue().equals(long2.getBinaryValue()); + } + + @Override + public Boolean caseBinaryIntegerLiteral(BinaryIntegerLiteral int1) { + this.logMessage("caseBinaryIntegerLiteral"); + + BinaryIntegerLiteral int2 = (BinaryIntegerLiteral) this.getCompareElement(); + return int1.getBinaryValue().equals(int2.getBinaryValue()); + } + + /** + * Check null literal similarity.
+ * + * Null literals are always assumed to be similar. + * + * @param object + * The literal to compare with the compare element. + * @return True As null always means null. + */ + @Override + public Boolean defaultCase(EObject object) { + this.logMessage("defaultCase for Literals"); + + return Boolean.TRUE; + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/MembersSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/MembersSimilaritySwitch.java new file mode 100644 index 0000000000..ecee0fb31c --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/MembersSimilaritySwitch.java @@ -0,0 +1,211 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.apache.log4j.Level; +import org.eclipse.emf.common.util.EList; +import org.emftext.language.java.classifiers.AnonymousClass; +import org.emftext.language.java.classifiers.ConcreteClassifier; +import org.emftext.language.java.members.Constructor; +import org.emftext.language.java.members.EnumConstant; +import org.emftext.language.java.members.Member; +import org.emftext.language.java.members.Method; +import org.emftext.language.java.members.util.MembersSwitch; +import org.emftext.language.java.parameters.Parameter; +import org.emftext.language.java.types.Type; +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +import com.google.common.base.Strings; + +/** + * Similarity decisions for the member elements. + */ +public class MembersSimilaritySwitch extends MembersSwitch implements ILoggableJavaSwitch, IJavaSimilarityPositionInnerSwitch { + private IJavaSimilaritySwitch similaritySwitch; + private boolean checkStatementPosition; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public boolean shouldCheckStatementPosition() { + return this.checkStatementPosition; + } + + @Override + public IJavaSimilaritySwitch getContainingSwitch() { + return this.similaritySwitch; + } + + public MembersSimilaritySwitch(IJavaSimilaritySwitch similaritySwitch, boolean checkStatementPosition) { + this.similaritySwitch = similaritySwitch; + this.checkStatementPosition = checkStatementPosition; + } + + /** + * Check abstract method declaration similarity. Similarity is checked by + *
    + *
  • name
  • + *
  • parameter list size
  • + *
  • parameter types
  • + *
  • name
  • + *
  • container for + *
      + *
    • AbstractTypeDeclaration
    • + *
    • AnonymousClassDeclaration
    • + *
    • Model
    • + *
    + *
  • + *
+ * + * The container must be checked to check similarity for referenced methods. + * + * + * @param method1 + * The abstract method declaration to compare with the compare element. + * @return True/False if the abstract method declarations are similar or not. + */ + @Override + public Boolean caseMethod(Method method1) { + this.logMessage("caseMethod"); + + Method method2 = (Method) this.getCompareElement(); + + // if methods have different names they are not similar. + if (!method1.getName().equals(method2.getName())) { + return Boolean.FALSE; + } + + if (method1.getParameters().size() != method2.getParameters().size()) { + return Boolean.FALSE; + } + + for (int i = 0; i < method1.getParameters().size(); i++) { + Parameter param1 = method1.getParameters().get(i); + Parameter param2 = method2.getParameters().get(i); + Type type1 = param1.getTypeReference().getTarget(); + Type type2 = param2.getTypeReference().getTarget(); + Boolean typeSimilarity = this.isSimilar(type1, type2); + if (typeSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + if (param1.getTypeReference().getArrayDimension() != param2.getTypeReference().getArrayDimension()) { + return Boolean.FALSE; + } + } + + /* ************************************** + * methods as members of regular classes + */ + if (method1.getContainingConcreteClassifier() != null) { + ConcreteClassifier type1 = method1.getContainingConcreteClassifier(); + ConcreteClassifier type2 = method2.getContainingConcreteClassifier(); + return this.isSimilar(type1, type2); + } + + /* ************************************** + * methods as members of anonymous classes + */ + if (method1.getContainingAnonymousClass() != null) { + AnonymousClass type1 = method1.getContainingAnonymousClass(); + AnonymousClass type2 = method2.getContainingAnonymousClass(); + Boolean typeSimilarity = this.isSimilar(type1, type2); + if (typeSimilarity != null) { + return typeSimilarity; + } + } + + this.logMessage("MethodDeclaration in unknown container: " + method1.getName() + " : " + + method1.eContainer(), Level.WARN); + return super.caseMethod(method1); + } + + /** + * Check constuctor declaration similarity. Similarity is checked by + *
    + *
  • name
  • + *
  • parameter list size
  • + *
  • parameter types
  • + *
  • name
  • + *
  • container for + *
      + *
    • AbstractTypeDeclaration
    • + *
    • AnonymousClassDeclaration
    • + *
    • Model
    • + *
    + *
  • + *
+ * + * The container must be checked to check similarity for referenced methods. + * + * + * @param constructor1 + * The abstract method declaration to compare with the compare element. + * @return True/False if the abstract method declarations are similar or not. + */ + @Override + public Boolean caseConstructor(Constructor constructor1) { + this.logMessage("caseConstructor"); + + Constructor constructor2 = (Constructor) this.getCompareElement(); + + // if methods have different names they are not similar. + if (!constructor1.getName().equals(constructor2.getName())) { + return Boolean.FALSE; + } + + EList params1 = constructor1.getParameters(); + EList params2 = constructor2.getParameters(); + Boolean parameterSimilarity = this.areSimilar(params1, params2); + if (parameterSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + /* ************************************** + * methods as members of regular classes + */ + if (constructor1.getContainingConcreteClassifier() != null) { + ConcreteClassifier type1 = constructor1.getContainingConcreteClassifier(); + ConcreteClassifier type2 = constructor2.getContainingConcreteClassifier(); + return this.isSimilar(type1, type2); + } + + /* ************************************** + * methods as members of anonymous classes + */ + if (constructor1.getContainingAnonymousClass() != null) { + AnonymousClass type1 = constructor1.getContainingAnonymousClass(); + AnonymousClass type2 = constructor2.getContainingAnonymousClass(); + Boolean typeSimilarity = this.isSimilar(type1, type2); + if (typeSimilarity != null) { + return typeSimilarity; + } + } + + this.logMessage("ConstructorDeclaration in unknown container: " + constructor1.getName() + " : " + + constructor1.eContainer(), Level.WARN); + return super.caseConstructor(constructor1); + } + + @Override + public Boolean caseEnumConstant(EnumConstant const1) { + this.logMessage("caseEnumConstant"); + + EnumConstant const2 = (EnumConstant) this.getCompareElement(); + String name1 = Strings.nullToEmpty(const1.getName()); + String name2 = Strings.nullToEmpty(const2.getName()); + return (name1.equals(name2)); + } + + @Override + public Boolean caseMember(Member member1) { + this.logMessage("caseMember"); + + Member member2 = (Member) this.getCompareElement(); + String name1 = Strings.nullToEmpty(member1.getName()); + String name2 = Strings.nullToEmpty(member2.getName()); + return (name1.equals(name2)); + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ModifiersSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ModifiersSimilaritySwitch.java new file mode 100644 index 0000000000..c5409839ed --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ModifiersSimilaritySwitch.java @@ -0,0 +1,22 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.eclipse.emf.ecore.EObject; +import org.emftext.language.java.modifiers.util.ModifiersSwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; + +/** + * Similarity decisions for modifier elements. + *

+ * All modifier elements are strong typed with no identifying attributes or non-containment + * references. Their location and runtime types are assumed to be checked before this switch is + * called. + *

+ */ +public class ModifiersSimilaritySwitch extends ModifiersSwitch implements ILoggableJavaSwitch { + @Override + public Boolean defaultCase(EObject object) { + this.logMessage("defaultCase for Modifier"); + + return Boolean.TRUE; + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ModulesSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ModulesSimilaritySwitch.java new file mode 100644 index 0000000000..a53bd40823 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ModulesSimilaritySwitch.java @@ -0,0 +1,135 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.emftext.language.java.modules.AccessProvidingModuleDirective; +import org.emftext.language.java.modules.ModuleReference; +import org.emftext.language.java.modules.ProvidesModuleDirective; +import org.emftext.language.java.modules.RequiresModuleDirective; +import org.emftext.language.java.modules.UsesModuleDirective; +import org.emftext.language.java.modules.util.ModulesSwitch; +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +/** + * Similarity Decisions for module elements. + */ +public class ModulesSimilaritySwitch extends ModulesSwitch implements ILoggableJavaSwitch, IJavaSimilarityPositionInnerSwitch { + private IJavaSimilaritySwitch similaritySwitch; + private boolean checkStatementPosition; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public boolean shouldCheckStatementPosition() { + return this.checkStatementPosition; + } + + @Override + public IJavaSimilaritySwitch getContainingSwitch() { + return this.similaritySwitch; + } + + public ModulesSimilaritySwitch(IJavaSimilaritySwitch similaritySwitch, boolean checkStatementPosition) { + this.similaritySwitch = similaritySwitch; + this.checkStatementPosition = checkStatementPosition; + } + + /** + * Check ModuleReference similarity.
+ * Similarity is checked by + *
    + *
  • module names
  • + *
+ * + * @param modRef1 The module reference to compare with the compare element. + * @return True/False if the module references are similar or not. + */ + @Override + public Boolean caseModuleReference(ModuleReference modRef1) { + this.logMessage("caseModuleReference"); + + ModuleReference modRef2 = (ModuleReference) this.getCompareElement(); + if (this.compareNamespacesByPart(modRef1, modRef2)) { + return Boolean.TRUE; + } + return Boolean.FALSE; + } + + /** + * Check similarity for access providing module directives.
+ * Similarity is checked by + *
    + *
  • the provided package
  • + *
+ * + * @param dir1 The access providing module directive to compare with the compare element. + * @return True/False if the module directives are similar or not. + */ + @Override + public Boolean caseAccessProvidingModuleDirective(AccessProvidingModuleDirective dir1) { + this.logMessage("caseAccessProvidingModuleDirective"); + + AccessProvidingModuleDirective dir2 = (AccessProvidingModuleDirective) this.getCompareElement(); + if (!this.compareNamespacesByPart(dir1, dir2)) { + return Boolean.FALSE; + } + return Boolean.TRUE; + } + + /** + * Check similarity for require module directives.
+ * Similarity is checked by + *
    + *
  • required modules
  • + *
+ * + * @param dir1 The require module directive to compare with the compare element. + * @return True/False if the module directives are similar or not. + */ + @Override + public Boolean caseRequiresModuleDirective(RequiresModuleDirective dir1) { + this.logMessage("caseRequiresModuleDirective"); + + RequiresModuleDirective dir2 = (RequiresModuleDirective) this.getCompareElement(); + return this.isSimilar(dir1.getRequiredModule(), dir2.getRequiredModule()); + } + + /** + * Check similarity for provide module directives.
+ * Similarity is checked by + *
    + *
  • provided types
  • + *
+ * + * @param dir1 The provide module directive to compare with the compare element. + * @return True/False if the module directives are similar or not. + */ + @Override + public Boolean caseProvidesModuleDirective(ProvidesModuleDirective dir1) { + this.logMessage("caseProvidesModuleDirective"); + + ProvidesModuleDirective dir2 = (ProvidesModuleDirective) this.getCompareElement(); + return this.isSimilar(dir1.getTypeReference(), dir2.getTypeReference()); + } + + /** + * Check similarity for use module directives.
+ * Similarity is checked by + *
    + *
  • used types
  • + *
+ * + * @param dir1 The use module directive to compare with the compare element. + * @return True/False if the module directives are similar or not. + */ + @Override + public Boolean caseUsesModuleDirective(UsesModuleDirective dir1) { + this.logMessage("caseUsesModuleDirective"); + + UsesModuleDirective dir2 = (UsesModuleDirective) this.getCompareElement(); + return this.isSimilar(dir1.getTypeReference(), dir2.getTypeReference()); + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/OperatorsSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/OperatorsSimilaritySwitch.java new file mode 100644 index 0000000000..8af7d34720 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/OperatorsSimilaritySwitch.java @@ -0,0 +1,22 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.eclipse.emf.ecore.EObject; +import org.emftext.language.java.operators.util.OperatorsSwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; + +/** + * Similarity decisions for operator elements. + *

+ * All operator elements are strong typed with no identifying attributes or non-containment + * references. Their location and runtime types are assumed to be checked before this switch is + * called. + *

+ */ +public class OperatorsSimilaritySwitch extends OperatorsSwitch implements ILoggableJavaSwitch { + @Override + public Boolean defaultCase(EObject object) { + this.logMessage("defaultCase for Operator"); + + return Boolean.TRUE; + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ParametersSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ParametersSimilaritySwitch.java new file mode 100644 index 0000000000..704ccfc799 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ParametersSimilaritySwitch.java @@ -0,0 +1,44 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.emftext.language.java.parameters.Parameter; +import org.emftext.language.java.parameters.util.ParametersSwitch; +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +import com.google.common.base.Strings; + +/** + * Similarity decisions for parameter elements. + *

+ * Parameters are variables and for this named elements. So their names must be checked but no + * more identifying attributes or references exist. + *

+ */ +public class ParametersSimilaritySwitch extends ParametersSwitch implements ILoggableJavaSwitch, IJavaSimilarityInnerSwitch { + private IJavaSimilaritySwitch similaritySwitch; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public IJavaSimilaritySwitch getContainingSwitch() { + return this.similaritySwitch; + } + + public ParametersSimilaritySwitch(IJavaSimilaritySwitch similaritySwitch) { + this.similaritySwitch = similaritySwitch; + } + + @Override + public Boolean caseParameter(Parameter param1) { + this.logMessage("caseParameter"); + + Parameter param2 = (Parameter) this.getCompareElement(); + String name1 = Strings.nullToEmpty(param1.getName()); + String name2 = Strings.nullToEmpty(param2.getName()); + return (name1.equals(name2)); + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ReferencesSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ReferencesSimilaritySwitch.java new file mode 100644 index 0000000000..7b5a9c2175 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/ReferencesSimilaritySwitch.java @@ -0,0 +1,187 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.eclipse.emf.ecore.EObject; +import org.emftext.language.java.arrays.ArraySelector; +import org.emftext.language.java.expressions.Expression; +import org.emftext.language.java.references.ElementReference; +import org.emftext.language.java.references.IdentifierReference; +import org.emftext.language.java.references.MethodCall; +import org.emftext.language.java.references.Reference; +import org.emftext.language.java.references.ReferenceableElement; +import org.emftext.language.java.references.StringReference; +import org.emftext.language.java.references.util.ReferencesSwitch; +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; +import org.splevo.jamopp.util.JaMoPPElementUtil; + +/** + * Similarity decisions for reference elements. + */ +public class ReferencesSimilaritySwitch extends ReferencesSwitch implements ILoggableJavaSwitch, IJavaSimilarityPositionInnerSwitch { + private IJavaSimilaritySwitch similaritySwitch; + private boolean checkStatementPosition; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public boolean shouldCheckStatementPosition() { + return this.checkStatementPosition; + } + + @Override + public IJavaSimilaritySwitch getContainingSwitch() { + return this.similaritySwitch; + } + + public ReferencesSimilaritySwitch(IJavaSimilaritySwitch similaritySwitch, boolean checkStatementPosition) { + this.similaritySwitch = similaritySwitch; + this.checkStatementPosition = checkStatementPosition; + } + + @Override + public Boolean caseStringReference(StringReference ref1) { + this.logMessage("caseStringReference"); + + StringReference ref2 = (StringReference) this.getCompareElement(); + if (ref1.getValue() == null) { + return (ref2.getValue() == null); + } + + return (ref1.getValue().equals(ref2.getValue())); + } + + @Override + public Boolean caseIdentifierReference(IdentifierReference ref1) { + this.logMessage("caseIdentifierReference"); + + IdentifierReference ref2 = (IdentifierReference) this.getCompareElement(); + ReferenceableElement target1 = ref1.getTarget(); + ReferenceableElement target2 = ref2.getTarget(); + + // target identity similarity + Boolean similarity = this.isSimilar(target1, target2); + if (similarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + if (target1 != null) { + // target container similarity + // check this only if the reference target is located + // in another container than the reference itself. + // Otherwise such a situation would lead to endless loops + // e.g. for for "(Iterator i = c.iterator(); i.hasNext(); ) {" + // Attention: The reference could be encapsulated by an expression! + EObject ref1Container = JaMoPPElementUtil.getFirstContainerNotOfGivenType(ref1, Expression.class, + ArraySelector.class); + EObject ref2Container = JaMoPPElementUtil.getFirstContainerNotOfGivenType(ref2, Expression.class, + ArraySelector.class); + EObject target1Container = target1.eContainer(); + EObject target2Container = target2.eContainer(); + if (target1Container != ref1Container && target2Container != ref2Container + && target1Container != ref1 && target2Container != ref2) { + Boolean containerSimilarity = this.isSimilar(target1Container, target2Container); + if (containerSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + } + } + + if (ref1.getArraySelectors().size() != ref2.getArraySelectors().size()) { + return Boolean.FALSE; + } + for (int i = 0; i < ref1.getArraySelectors().size(); i++) { + ArraySelector selector1 = ref1.getArraySelectors().get(i); + ArraySelector selector2 = ref2.getArraySelectors().get(i); + Boolean positionSimilarity = this.isSimilar(selector1.getPosition(), + selector2.getPosition()); + if (positionSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + } + + Reference next1 = ref1.getNext(); + Reference next2 = ref2.getNext(); + Boolean nextSimilarity = this.isSimilar(next1, next2); + if (nextSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + + /** + * Check element reference similarity.
+ * + * Is checked by the target (the method called). Everything else are containment references + * checked indirectly. + * + * @param ref1 + * The method call to compare with the compare element. + * @return True As null always means null. + */ + @Override + public Boolean caseElementReference(ElementReference ref1) { + this.logMessage("caseElementReference"); + + ElementReference ref2 = (ElementReference) this.getCompareElement(); + + Boolean targetSimilarity = this.isSimilar(ref1.getTarget(), ref2.getTarget()); + if (targetSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + + /** + * Proof method call similarity. + * + * Similarity is decided by the method referenced and the arguments passed by. + * + * @param call1 + * The left / modified method call to compare with the original one. + * @return True/False if the method calls are similar or not. + */ + @Override + public Boolean caseMethodCall(MethodCall call1) { + this.logMessage("caseMethodCall"); + + MethodCall call2 = (MethodCall) this.getCompareElement(); + + Boolean targetSimilarity = this.isSimilar(call1.getTarget(), call2.getTarget()); + if (targetSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + if (call1.getArguments().size() != call2.getArguments().size()) { + return Boolean.FALSE; + } + + for (int i = 0; i < call1.getArguments().size(); i++) { + Expression exp1 = call1.getArguments().get(i); + Expression exp2 = call2.getArguments().get(i); + Boolean argSimilarity = this.isSimilar(exp1, exp2); + if (argSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + } + + Boolean nextSimilarity = this.isSimilar(call1.getNext(), call2.getNext()); + if (nextSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + + @Override + public Boolean defaultCase(EObject object) { + this.logMessage("defaultCase for Reference"); + + return Boolean.TRUE; + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/StatementsSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/StatementsSimilaritySwitch.java new file mode 100644 index 0000000000..5803c83123 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/StatementsSimilaritySwitch.java @@ -0,0 +1,362 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.eclipse.emf.ecore.EObject; +import org.emftext.language.java.expressions.Expression; +import org.emftext.language.java.parameters.OrdinaryParameter; +import org.emftext.language.java.statements.CatchBlock; +import org.emftext.language.java.statements.Conditional; +import org.emftext.language.java.statements.ExpressionStatement; +import org.emftext.language.java.statements.Jump; +import org.emftext.language.java.statements.JumpLabel; +import org.emftext.language.java.statements.LocalVariableStatement; +import org.emftext.language.java.statements.Return; +import org.emftext.language.java.statements.Statement; +import org.emftext.language.java.statements.StatementListContainer; +import org.emftext.language.java.statements.Switch; +import org.emftext.language.java.statements.SynchronizedBlock; +import org.emftext.language.java.statements.Throw; +import org.emftext.language.java.statements.util.StatementsSwitch; +import org.emftext.language.java.variables.Variable; +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; +import org.splevo.jamopp.util.JaMoPPElementUtil; + +import com.google.common.base.Strings; + +/** + * Similarity decisions for the statement elements. + */ +public class StatementsSimilaritySwitch extends StatementsSwitch implements ILoggableJavaSwitch, IJavaSimilarityPositionInnerSwitch { + private IJavaSimilaritySwitch similaritySwitch; + private boolean checkStatementPosition; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public boolean shouldCheckStatementPosition() { + return this.checkStatementPosition; + } + + @Override + public IJavaSimilaritySwitch getContainingSwitch() { + return this.similaritySwitch; + } + + public StatementsSimilaritySwitch(IJavaSimilaritySwitch similaritySwitch, boolean checkStatementPosition) { + this.similaritySwitch = similaritySwitch; + this.checkStatementPosition = checkStatementPosition; + } + + /** + * Check expression statement similarity.
+ * Similarity is checked by + *
    + *
  • similarity statements expressions
  • + *
+ * + * @param statement1 + * The expression statement to compare with the compare element. + * @return True/False if the expression statements are similar or not. + */ + @Override + public Boolean caseExpressionStatement(ExpressionStatement statement1) { + this.logMessage("caseExpressionStatement"); + + ExpressionStatement statement2 = (ExpressionStatement) this.getCompareElement(); + + Expression exp1 = statement1.getExpression(); + Expression exp2 = statement2.getExpression(); + + Boolean expSimilarity = this.isSimilar(exp1, exp2); + if (expSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + // check predecessor similarity + if (this.shouldCheckStatementPosition()) { + if (differentPredecessor(statement1, statement2) && differentSuccessor(statement1, statement2)) { + return Boolean.FALSE; + } + } + + return Boolean.TRUE; + } + + /** + * Check the similarity of a variable declaration. + * + * The similarity is decided by the declared variables name only. A changed variable type or + * value initialization should lead to a changed statement not a new one. + * + * @param varStmt1 + * The variable to compare with the original / right-side one + * @return True/False if they are similar or not. + */ + @Override + public Boolean caseLocalVariableStatement(LocalVariableStatement varStmt1) { + this.logMessage("caseLocalVariableStatement"); + + LocalVariableStatement varStmt2 = (LocalVariableStatement) this.getCompareElement(); + + Variable var1 = varStmt1.getVariable(); + Variable var2 = varStmt2.getVariable(); + Boolean varSimilarity = this.isSimilar(var1, var2); + if (varSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + if (this.shouldCheckStatementPosition()) { + varSimilarity = this.isSimilar(varStmt1.eContainer(), varStmt2.eContainer(), false); + if (!varSimilarity) { + return Boolean.FALSE; + } + if (differentPredecessor(varStmt1, varStmt2) && differentSuccessor(varStmt1, varStmt2)) { + return Boolean.FALSE; + } + } + + return Boolean.TRUE; + } + + /** + * Check return statement similarity.
+ * Similarity is checked by + *
    + *
  • expressions similarity
  • + *
+ * + * @param returnStatement1 + * The return statement to compare with the compare element. + * @return True/False if the return statements are similar or not. + */ + @Override + public Boolean caseReturn(Return returnStatement1) { + this.logMessage("caseReturn"); + + Return returnStatement2 = (Return) this.getCompareElement(); + + Expression exp1 = returnStatement1.getReturnValue(); + Expression exp2 = returnStatement2.getReturnValue(); + + return this.isSimilar(exp1, exp2); + } + + /** + * Check synchronized statement similarity.
+ * Similarity is checked by + *
    + *
  • expression similarity
  • + *
+ * + * @param statement1 + * The synchronized statement to compare with the compare element. + * @return True/False if the synchronized statements are similar or not. + */ + @Override + public Boolean caseSynchronizedBlock(SynchronizedBlock statement1) { + this.logMessage("caseSynchronizedBlock"); + + SynchronizedBlock statement2 = (SynchronizedBlock) this.getCompareElement(); + + Expression exp1 = statement1.getLockProvider(); + Expression exp2 = statement2.getLockProvider(); + Boolean similarity = this.isSimilar(exp1, exp2); + if (similarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + if (this.shouldCheckStatementPosition()) { + if (differentPredecessor(statement1, statement2) && differentSuccessor(statement1, statement2)) { + return Boolean.FALSE; + } + } + return Boolean.TRUE; + } + + /** + * Check throw statement similarity.
+ * + * Only one throw statement can exist at the same code location. As a result the container + * similarity checked implicitly is enough for this. + * + * @param throwStatement1 + * The throw statement to compare with the compare element. + * @return True/False if the throw statements are similar or not. + */ + @Override + public Boolean caseThrow(Throw throwStatement1) { + this.logMessage("caseThrow"); + + return Boolean.TRUE; + } + + @Override + public Boolean caseCatchBlock(CatchBlock catchBlock1) { + this.logMessage("caseCatchBlock"); + + CatchBlock catchBlock2 = (CatchBlock) this.getCompareElement(); + + OrdinaryParameter catchedException1 = catchBlock1.getParameter(); + OrdinaryParameter catchedException2 = catchBlock2.getParameter(); + + Boolean exceptionSimilarity = this.isSimilar(catchedException1, catchedException2); + if (exceptionSimilarity == Boolean.FALSE) { + return exceptionSimilarity; + } + + return Boolean.TRUE; + } + + /** + * Check if two conditional statements are similar. + * + * Similarity is checked by: + *
    + *
  • similarity of the expressions
  • + *
+ * + * The then and else statements are not checked as part of the condition statement check + * because this is only about the container if statement similarity. The contained + * statements are checked in a separate step of the compare process if the enclosing + * condition statement matches. + * + * @param conditional1 + * The statement to compare with the compare element. + * @return True/False whether they are similar or not. + */ + @Override + public Boolean caseConditional(Conditional conditional1) { + this.logMessage("caseConditional"); + + Conditional conditional2 = (Conditional) this.getCompareElement(); + + Expression expression1 = conditional1.getCondition(); + Expression expression2 = conditional2.getCondition(); + Boolean expressionSimilarity = this.isSimilar(expression1, expression2); + if (expressionSimilarity == Boolean.FALSE) { + return expressionSimilarity; + } + + return Boolean.TRUE; + } + + @Override + public Boolean caseJump(Jump jump1) { + this.logMessage("caseJump"); + + Jump jump2 = (Jump) this.getCompareElement(); + + Boolean similarity = this.isSimilar(jump1.getTarget(), jump2.getTarget()); + if (similarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + + @Override + public Boolean caseJumpLabel(JumpLabel label1) { + this.logMessage("caseJumpLabel"); + + JumpLabel label2 = (JumpLabel) this.getCompareElement(); + + String name1 = Strings.nullToEmpty(label1.getName()); + String name2 = Strings.nullToEmpty(label2.getName()); + + return (name1.equals(name2)); + } + + @Override + public Boolean caseSwitch(Switch switch1) { + this.logMessage("caseSwitch"); + + Switch switch2 = (Switch) this.getCompareElement(); + + return this.isSimilar(switch1.getVariable(), switch2.getVariable()); + } + + @Override + public Boolean defaultCase(EObject object) { + this.logMessage("defaultCase for Statement"); + + return Boolean.TRUE; + } + + /** + * Decide of two statements differ from each other or not. + * + * @param statement1 + * The first statement to compare + * @param statement2 + * The second statement to compare. + * @return True if they differ, null if not. + */ + private boolean differentPredecessor(Statement statement1, Statement statement2) { + Statement pred1 = getPredecessor(statement1); + Statement pred2 = getPredecessor(statement2); + Boolean similarity = this.isSimilar(pred1, pred2, false); + return similarity == Boolean.FALSE; + } + + /** + * Check if two statements have differing successor statements. + * + * @param statement1 + * The first statement to check. + * @param statement2 + * The second statement to check. + * @return True if their successor differ, false if not. + */ + private boolean differentSuccessor(Statement statement1, Statement statement2) { + Statement pred1 = getSuccessor(statement1); + Statement pred2 = getSuccessor(statement2); + Boolean similarity = this.isSimilar(pred1, pred2, false); + return similarity == Boolean.FALSE; + } + + /** + * Get the predecessor statement of a statement within the parents container statement list.
+ * If a statement is the first, the only one, or the container is not a + * {@link StatementListContainer}, or no predecessor exists, null will be returned. + * + * @param statement + * The statement to get the predecessor for. + * @return The predecessor or null if non exists. + */ + private Statement getPredecessor(Statement statement) { + + int pos = JaMoPPElementUtil.getPositionInContainer(statement); + if (pos > 0) { + StatementListContainer container = (StatementListContainer) statement.eContainer(); + return container.getStatements().get(pos - 1); + } + + return null; + } + + /** + * Get the successor statement of a statement within the parents container statement list.
+ * If a statement is the last, the only one, or the container is not a + * {@link StatementListContainer}, no successor exists, null will be returned. + * + * @param statement + * The statement to get the predecessor for. + * @return The predecessor or null if non exists. + */ + private Statement getSuccessor(Statement statement) { + + int pos = JaMoPPElementUtil.getPositionInContainer(statement); + if (pos != -1) { + StatementListContainer container = (StatementListContainer) statement.eContainer(); + if (container.getStatements().size() > pos + 1) { + return container.getStatements().get(pos + 1); + } + } + + return null; + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/TypesSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/TypesSimilaritySwitch.java new file mode 100644 index 0000000000..49a69d46b5 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/TypesSimilaritySwitch.java @@ -0,0 +1,142 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.eclipse.emf.ecore.EObject; +import org.emftext.language.java.types.ClassifierReference; +import org.emftext.language.java.types.InferableType; +import org.emftext.language.java.types.NamespaceClassifierReference; +import org.emftext.language.java.types.PrimitiveType; +import org.emftext.language.java.types.TypeReference; +import org.emftext.language.java.types.util.TypesSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; +import org.splevo.jamopp.diffing.similarity.JavaSimilarityChecker; + +import com.google.common.base.Strings; + +/** + * Similarity decisions for elements of the types package. + */ +public class TypesSimilaritySwitch extends TypesSwitch implements ILoggableJavaSwitch, IJavaSimilarityPositionInnerSwitch { + private IJavaSimilaritySwitch similaritySwitch; + private boolean checkStatementPosition; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public boolean shouldCheckStatementPosition() { + return this.checkStatementPosition; + } + + @Override + public IJavaSimilaritySwitch getContainingSwitch() { + return this.similaritySwitch; + } + + public TypesSimilaritySwitch(IJavaSimilaritySwitch similaritySwitch, boolean checkStatementPosition) { + this.similaritySwitch = similaritySwitch; + this.checkStatementPosition = checkStatementPosition; + } + + /** + * Check element reference similarity.
+ * + * Is checked by the target (the method called). Everything else are containment references + * checked indirectly. + * + * @param ref1 + * The method call to compare with the compare element. + * @return True As null always means null. + */ + @Override + public Boolean caseClassifierReference(ClassifierReference ref1) { + this.logMessage("caseClassifierReference"); + + ClassifierReference ref2 = (ClassifierReference) this.getCompareElement(); + + Boolean targetSimilarity = this.isSimilar(ref1.getTarget(), ref2.getTarget()); + if (targetSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + + @Override + public Boolean caseTypeReference(TypeReference ref1) { + this.logMessage("caseTypeReference"); + + TypeReference ref2 = (TypeReference) this.getCompareElement(); + + Boolean targetSimilarity = this.isSimilar(ref1.getTarget(), ref2.getTarget()); + if (targetSimilarity == Boolean.FALSE) { + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + + @Override + public Boolean caseNamespaceClassifierReference(NamespaceClassifierReference ref1) { + this.logMessage("caseNamespaceClassifierReference"); + + NamespaceClassifierReference ref2 = (NamespaceClassifierReference) this.getCompareElement(); + + String namespace1 = Strings.nullToEmpty(ref1.getNamespacesAsString()); + String namespace2 = Strings.nullToEmpty(ref2.getNamespacesAsString()); + if (!namespace1.equals(namespace2)) { + return Boolean.FALSE; + } + + ClassifierReference pureRef1 = ref1.getPureClassifierReference(); + ClassifierReference pureRef2 = ref2.getPureClassifierReference(); + + return this.isSimilar(pureRef1, pureRef2); + } + + /** + * Primitive types are always similar as their class similarity is assumed before by the + * outer {@link JavaSimilarityChecker}. + * + * Note: The fall back to the default case is not sufficient here, as the common + * TypeReference case would be used before, leading to a loop. + * + * @param type + * The primitive type object. + * @return TRUE + */ + @Override + public Boolean casePrimitiveType(PrimitiveType type) { + this.logMessage("casePrimitiveType"); + + return Boolean.TRUE; + } + + /** + * Inferable types are considered to be similar. + * + * @param type The element to compare with the compare element. + * @return true. + */ + @Override + public Boolean caseInferableType(InferableType type) { + this.logMessage("caseInferableType"); + + return Boolean.TRUE; + } + + /** + * Primitive type elements are strongly typed and the exact type is already checked by the + * outer {@link JavaSimilarityChecker}.
+ * {@inheritDoc} + */ + @Override + public Boolean defaultCase(EObject object) { + this.logMessage("defaultCase for Type"); + + return Boolean.TRUE; + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/VariablesSimilaritySwitch.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/VariablesSimilaritySwitch.java new file mode 100644 index 0000000000..6884027974 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/VariablesSimilaritySwitch.java @@ -0,0 +1,73 @@ +package org.splevo.jamopp.diffing.similarity.switches; + +import org.emftext.language.java.variables.AdditionalLocalVariable; +import org.emftext.language.java.variables.Variable; +import org.emftext.language.java.variables.util.VariablesSwitch; +import org.splevo.jamopp.diffing.similarity.IJavaSimilaritySwitch; +import org.splevo.jamopp.diffing.similarity.ILoggableJavaSwitch; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityRequestHandler; + +import com.google.common.base.Strings; + +/** + * Similarity decisions for the variable elements. + */ +public class VariablesSimilaritySwitch extends VariablesSwitch implements ILoggableJavaSwitch, IJavaSimilarityInnerSwitch { + private IJavaSimilaritySwitch similaritySwitch; + + @Override + public ISimilarityRequestHandler getSimilarityRequestHandler() { + return this.similaritySwitch; + } + + @Override + public IJavaSimilaritySwitch getContainingSwitch() { + return this.similaritySwitch; + } + + public VariablesSimilaritySwitch(IJavaSimilaritySwitch similaritySwitch) { + this.similaritySwitch = similaritySwitch; + } + + /** + * Check variable declaration similarity.
+ * Similarity is checked by + *
    + *
  • variable name
  • + *
  • variable container (name space)
  • + *
+ * + * @param var1 + * The variable declaration to compare with the compare element. + * @return True/False if the variable declarations are similar or not. + */ + @Override + public Boolean caseVariable(Variable var1) { + this.logMessage("caseVariable"); + + Variable var2 = (Variable) this.getCompareElement(); + + // check the variables name equality + if (!var1.getName().equals(var2.getName())) { + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + + @Override + public Boolean caseAdditionalLocalVariable(AdditionalLocalVariable var1) { + this.logMessage("caseAdditionalLocalVariable"); + + AdditionalLocalVariable var2 = (AdditionalLocalVariable) this.getCompareElement(); + + // check the variables name equality + String name1 = Strings.nullToEmpty(var1.getName()); + String name2 = Strings.nullToEmpty(var2.getName()); + if (!name1.equals(name2)) { + return Boolean.FALSE; + } + + return Boolean.TRUE; + } +} \ No newline at end of file diff --git a/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/package-info.java b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/package-info.java new file mode 100644 index 0000000000..fb8ee101b4 --- /dev/null +++ b/commit-based-cipm/bundles/fi/org.splevo.jamopp.diffing/src/org/splevo/jamopp/diffing/similarity/switches/package-info.java @@ -0,0 +1,4 @@ +/** + * Similarity definitions for the JaMoPP difference analysis. + */ +package org.splevo.jamopp.diffing.similarity.switches; \ No newline at end of file diff --git a/commit-based-cipm/bundles/si/tools.vitruv.applications.pcmjava.seffstatements.finegrained/src/tools/vitruv/applications/pcmjava/seffstatements/code2seff/finegrained/FineGrainedClassMethodBodyChangedTransformation.java b/commit-based-cipm/bundles/si/tools.vitruv.applications.pcmjava.seffstatements.finegrained/src/tools/vitruv/applications/pcmjava/seffstatements/code2seff/finegrained/FineGrainedClassMethodBodyChangedTransformation.java index dbd8d53b11..57050a243d 100644 --- a/commit-based-cipm/bundles/si/tools.vitruv.applications.pcmjava.seffstatements.finegrained/src/tools/vitruv/applications/pcmjava/seffstatements/code2seff/finegrained/FineGrainedClassMethodBodyChangedTransformation.java +++ b/commit-based-cipm/bundles/si/tools.vitruv.applications.pcmjava.seffstatements.finegrained/src/tools/vitruv/applications/pcmjava/seffstatements/code2seff/finegrained/FineGrainedClassMethodBodyChangedTransformation.java @@ -22,7 +22,10 @@ import org.somox.gast2seff.visitors.ResourceDemandingBehaviourForClassMethodFinding; import org.somox.gast2seff.visitors.VisitorUtils; import org.somox.sourcecodedecorator.SeffElementSourceCodeLink; -import org.splevo.jamopp.diffing.similarity.SimilarityChecker; +import org.splevo.jamopp.diffing.similarity.base.ISimilarityChecker; +import org.splevo.jamopp.diffing.similarity.base.MapSimilarityToolboxFactory; +import org.splevo.jamopp.diffing.similarity.JavaSimilarityToolboxBuilder; +import org.splevo.jamopp.diffing.similarity.JavaSimilarityChecker; import de.uka.ipd.sdq.identifier.Identifier; import tools.vitruv.applications.pcmjava.seffstatements.code2seff.BasicComponentFinding; @@ -45,7 +48,7 @@ public class FineGrainedClassMethodBodyChangedTransformation extends ExtendedCla private final Method newMethod; private final BasicComponentFinding basicComponentFinder; private ResourceDemandingBehaviourDiff rdbDifference; - private final SimilarityChecker similarityChecker; + private final ISimilarityChecker similarityChecker; public FineGrainedClassMethodBodyChangedTransformation(final Method newMethod, final BasicComponentFinding basicComponentFinder, @@ -56,7 +59,17 @@ public FineGrainedClassMethodBodyChangedTransformation(final Method newMethod, resourceDemandingBehaviourForClassMethodFinding); this.newMethod = newMethod; this.basicComponentFinder = basicComponentFinder; - this.similarityChecker = new SimilarityChecker(); + + var builder = new JavaSimilarityToolboxBuilder(); + builder.setSimilarityToolboxFactory(new MapSimilarityToolboxFactory()); + + var toolbox = builder.instantiate() + .buildNewSimilaritySwitchHandler() + .buildNormalizationHandlers() + .buildComparisonHandlers() + .build(); + + this.similarityChecker = new JavaSimilarityChecker(toolbox); } /**