blob: 96c14cf03da74ac9509ca76807b2f3bc2e212e21 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2011 Obeo.
* 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:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.docs.intent.compare.match;
import org.eclipse.emf.compare.FactoryException;
import org.eclipse.emf.compare.match.statistic.MetamodelFilter;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.mylyn.docs.intent.core.descriptionunit.DescriptionBloc;
import org.eclipse.mylyn.docs.intent.core.document.IntentSection;
import org.eclipse.mylyn.docs.intent.markup.markup.Block;
/**
* Similarity checker using the Intent semantics to compare two Intent elements.
*
* @author <a href="mailto:alex.lagarde@obeo.fr">Alex Lagarde</a>
*/
public class IntentSimilarityChecker extends StatisticBasedSimilarityChecker {
/**
* Value taht represents a very strong similarity.
*/
private static final double MAX_SIMILARITY = 0.9999;
private EObject localRoot;
private EObject repositoryRoot;
/**
* IntentSimilarityChecker constructor.
*
* @param localRoot
* the root of the local AST of a Intent Element.
* @param repositoryRoot
* the root of the repository AST for a Intent Element
* @param metamodelFilter
* a metamodel filter the checker can use to know whether a feature alwaas has the same value
* or not in the models.
* @param bridge
* utility class to keep API compatibility.
*/
public IntentSimilarityChecker(MetamodelFilter metamodelFilter,
AbstractGenericMatchEngineToCheckerBridge bridge, EObject localRoot, EObject repositoryRoot) {
super(metamodelFilter, bridge);
this.localRoot = localRoot;
this.repositoryRoot = repositoryRoot;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.compare.match.matcher.StatisticBasedSimilarityChecker#isSimilar(org.eclipse.emf.ecore.EObject,
* org.eclipse.emf.ecore.EObject)
*/
@Override
public boolean isSimilar(EObject obj1, EObject obj2) throws FactoryException {
boolean isSimilar = false;
boolean haveSpecificMatcher = false;
// If the two objects are the roots, we consider that they are similar in any circumstance
if (areRoots(obj1, obj2)) {
isSimilar = true;
haveSpecificMatcher = true;
} else {
if (obj1 instanceof DescriptionBloc && obj2 instanceof DescriptionBloc) {
isSimilar = areSimilarDescriptionBlocs((DescriptionBloc)obj1, (DescriptionBloc)obj2);
haveSpecificMatcher = true;
} else {
if (obj1 instanceof IntentSection && obj2 instanceof IntentSection) {
isSimilar = areSimilarSessions((IntentSection)obj1, (IntentSection)obj2);
haveSpecificMatcher = true;
}
}
}
if (!haveSpecificMatcher) {
isSimilar = super.isSimilar(obj1, obj2);
}
return isSimilar;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.compare.match.engine.AbstractSimilarityChecker#fastLookup(org.eclipse.emf.ecore.EObject)
*/
@Override
public EObject fastLookup(EObject obj1) {
if (obj1 == localRoot) {
return repositoryRoot;
}
return super.fastLookup(obj1);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.compare.match.matcher.client.ui.editor.merger.match.StatisticBasedSimilarityChecker#absoluteMetric(org.eclipse.emf.ecore.EObject,
* org.eclipse.emf.ecore.EObject)
*/
@Override
public double absoluteMetric(EObject obj1, EObject obj2) throws FactoryException {
// If the two objects are the roots, we consider that they are similar in any circumstance
if (areRoots(obj1, obj2)) {
return MAX_SIMILARITY;
}
return super.absoluteMetric(obj1, obj2);
}
/**
* Indicates if the two given objects represent the roots of the compared element.
*
* @param obj1
* the first element to determine if it's a root
* @param obj2
* the second element to determine if it's a root
* @return true if the two given objects represent the roots of the compared element, false otherwise
*/
private boolean areRoots(EObject obj1, EObject obj2) {
return (obj1 == localRoot) && (obj2 == repositoryRoot);
}
/**
* Indicates if the first session matches the second one.
*
* @param session1
* the session to match
* @param session2
* the candidate session
* @return true if the first session matches the second one, false otherwise
* @throws FactoryException
* - on error accessing features.
*/
protected boolean areSimilarSessions(IntentSection session1, IntentSection session2) //TODO FIXME [naming] section should be better than session
throws FactoryException {
// 2 session are equals if :
// they have the same title
Block title1 = session1.getTitle();
Block title2 = session2.getTitle();
// TODO FIXME if section don't have any title yet, NPE
return isSimilar(title1, title2);
}
/**
* Indicates if the first description bloc matches the second one.
*
* @param obj1
* the description bloc to match
* @param obj2
* the candidate description bloc
* @return true if the first description bloc matches the second one, false otherwise
*/
private boolean areSimilarDescriptionBlocs(DescriptionBloc obj1, DescriptionBloc obj2) {
// FIXME : first verify that both description blocs are part of the same DU
// Two description blocs are equals if they have the same position in their container
int positionInContainer1 = obj1.eContainer().eContents().indexOf(obj1);
int positionInContainer2 = obj2.eContainer().eContents().indexOf(obj2);
boolean haveSamePositionInContainer = positionInContainer1 == positionInContainer2;
return haveSamePositionInContainer;
}
}