Java tutorial
/******************************************************************************* * Copyright (c) 2012 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.emf.compare.match.eobject.internal; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import java.util.Map; import java.util.Set; import org.eclipse.emf.compare.match.eobject.WeightProvider; import org.eclipse.emf.ecore.EAnnotation; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EOperation; import org.eclipse.emf.ecore.EParameter; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.impl.EStringToStringMapEntryImpl; /** * Default implementation which is parameterized to set weights based on features, to ignore features and * consider "name" features as more important. * * @author <a href="mailto:cedric.brun@obeo.fr">Cedric Brun</a> */ public class ReflectiveWeightProvider implements WeightProvider { /*** * Something not impacting the object identity unless it adds up a lot. */ private static final int SMALL = 5; /** * A normal change in an object. */ private static final int NORMAL = 10; /** * Likely to impact the object identity. */ private static final int SIGNIFICANT = 20; /** * Quite important regarding the Object identity. */ private static final int MAJOR = 150; /** * Very important regarding the Object identity. */ private static final int MASSIVE = 350; /** * It is very unlikely the elements are matching if they have differences of this magnitude. */ private static final int UNLIKELY_TO_MATCH = 1000; /** * The list of specific weight to apply on specific Features. */ private Map<EStructuralFeature, Integer> weights; /** * The list of features to ignore during the distance computation. */ private Set<EStructuralFeature> toBeIgnored; /** * Weight coefficient of a change on a reference. */ private int referenceChangeCoef = NORMAL; /** * Weight coefficient of a change on an attribute. */ private int attributeChangeCoef = SIGNIFICANT; /** * Create the weight provider. */ public ReflectiveWeightProvider() { weights = Maps.newHashMap(); toBeIgnored = Sets.newLinkedHashSet(); } /** * {@inheritDoc} */ public int getWeight(EStructuralFeature feature) { if (irrelevant(feature) || toBeIgnored.contains(feature)) { return 0; } Integer found = weights.get(feature); if (found == null) { found = Integer.valueOf(SMALL); /* * This is worst than empirical but it works in many cases, if your feature is a "name" its likely * that it's important for matching the element. At some point I'll have to come up with something * which is more extensible.. */ if ("name".equals(feature.getName()) || "id".equals(feature.getName())) { //$NON-NLS-1$ found = Integer.valueOf(SIGNIFICANT); } if (feature instanceof EReference && ((EReference) feature).isContainment()) { found = Integer.valueOf(NORMAL); } } if (feature instanceof EReference) { found = referenceChangeCoef * found.intValue(); } else { found = attributeChangeCoef * found.intValue(); } return found; } /** * return true i the feature is irrelevant for the comparison. * * @param feat * any feature. * @return true i the feature is irrelevant for the comparison. */ protected boolean irrelevant(EStructuralFeature feat) { boolean irrelevantFeature = feat.isDerived() || feat.isTransient(); if (!irrelevantFeature && feat instanceof EReference) { EReference ref = (EReference) feat; irrelevantFeature = ref.isContainment() || ref.isContainer(); } return irrelevantFeature; } /** * {@inheritDoc} */ // CHECKSTYLE:OFF public int getParentWeight(EObject a) { /* * these should belong to an Ecore specific class */ if (a instanceof EStructuralFeature) { return MASSIVE; } else if (a instanceof EAnnotation) { return UNLIKELY_TO_MATCH; } else if (a instanceof EOperation) { return MAJOR; } else if (a instanceof EParameter) { return UNLIKELY_TO_MATCH; } else if (a instanceof EStringToStringMapEntryImpl) { return UNLIKELY_TO_MATCH; } return SIGNIFICANT; } // CHECKSTYLE:ON /** * {@inheritDoc} */ public int getContainingFeatureWeight(EObject a) { /* * these should belong to an ECore specific class */ if (a instanceof EStructuralFeature || a instanceof EAnnotation || a instanceof EOperation) { return MAJOR; } return SIGNIFICANT; } }