/***************************************************************************** * Copyright (c) 2010 CEA LIST. * * * 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: * Remi Schnekenburger (CEA LIST) remi.schnekenburger@cea.fr - Initial API and implementation * *****************************************************************************/ package org.eclipse.papyrus.infra.extendedtypes.util; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.gmf.runtime.emf.type.core.ElementTypeRegistry; import org.eclipse.gmf.runtime.emf.type.core.IElementType; import org.eclipse.gmf.runtime.emf.type.core.IMetamodelType; import org.eclipse.papyrus.infra.extendedtypes.ExtendedElementTypeConfiguration; import org.eclipse.papyrus.infra.extendedtypes.PostActionConfiguration; import org.eclipse.papyrus.infra.extendedtypes.PreActionConfiguration; import org.eclipse.papyrus.infra.extendedtypes.types.IExtendedHintedElementType; import org.eclipse.papyrus.infra.queries.core.configuration.QueryConfiguration; /** * Utility class for {@link IElementType}. */ public class ElementTypeUtils { /** * Tests if two elements types are equivalent * * @param referenceType * the reference type for the comparison * @param typeToCompare * the type that is compared to the reference one * @return <code>true</code> if both types are equivalent semantically */ public static boolean isSemanticallyEquivalent(IElementType referenceType, IElementType typeToCompare) { boolean isEquivalent = true; // first : easy test... if(typeToCompare.equals(referenceType)) { return true; } // 2. test the kind of element. if(referenceType instanceof IMetamodelType) { if(!(typeToCompare instanceof IMetamodelType)) { return false; } else { EClass referenceEclass = ((IMetamodelType)referenceType).getEClass(); EClass eclassToCompare = ((IMetamodelType)typeToCompare).getEClass(); isEquivalent = isEquivalent && referenceEclass.equals(eclassToCompare); } } else { if((typeToCompare instanceof IMetamodelType)) { return false; } } // metaclasses are equivalent. check for extended types now... if(referenceType instanceof IExtendedHintedElementType) { if(typeToCompare instanceof IExtendedHintedElementType) { isEquivalent = isEquivalent && isSemanticallyEquivalent((IExtendedHintedElementType)referenceType, (IExtendedHintedElementType)typeToCompare); } } return isEquivalent; } /** * Tests if two elements types are equivalent (configuration) * * @param referenceType * the reference type for the comparison * @param typeToCompare * the type that is compared to the reference one * @return <code>true</code> if both types are equivalent semantically */ public static boolean isSemanticallyEquivalent(IExtendedHintedElementType referenceType, IExtendedHintedElementType typeToCompare) { boolean isEquivalent = true; // check all pre/post action and validation ExtendedElementTypeConfiguration referenceConfiguration = referenceType.getConfiguration(); ExtendedElementTypeConfiguration configurationToCompare = typeToCompare.getConfiguration(); List<QueryConfiguration> referencePrevalidation = referenceConfiguration.getPreValidation(); List<QueryConfiguration> prevalidationToCompare = configurationToCompare.getPreValidation(); if(referencePrevalidation != null) { isEquivalent = isEquivalent && isEquivalent(referencePrevalidation, prevalidationToCompare); } else if(prevalidationToCompare != null) { isEquivalent = false; } List<PreActionConfiguration> referencePreaction = referenceConfiguration.getPreAction(); List<PreActionConfiguration> preactionToCompare = configurationToCompare.getPreAction(); if(referencePreaction != null) { isEquivalent = isEquivalent && isEquivalent(referencePreaction, preactionToCompare); } else if(preactionToCompare != null) { isEquivalent = false; } List<PostActionConfiguration> referencePostaction = referenceConfiguration.getPostAction(); List<PostActionConfiguration> postactionToCompare = configurationToCompare.getPostAction(); if(referencePostaction != null) { isEquivalent = isEquivalent && isEquivalent(referencePostaction, postactionToCompare); } else if(postactionToCompare != null) { isEquivalent = false; } return isEquivalent; } public static boolean isEquivalent(List<? extends EObject> referenceList, List<? extends EObject> listToCompare) { boolean isEquivalent = true; if(referenceList == null) { // only one is null : false if(listToCompare != null) { return false; } else { // both are null: true return true; } } else { // only one is null: false if(listToCompare == null) { return false; } } // check emptyness. If both empty : equivalent if(referenceList.isEmpty() && listToCompare.isEmpty()) { return true; } // check size. If different, false if(referenceList.size() != listToCompare.size()) { return false; } for(int i = 0; i < referenceList.size(); i++) { EObject reference = referenceList.get(i); EObject compared = listToCompare.get(i); isEquivalent = isEquivalent && EcoreUtil.equals(reference, compared); } return isEquivalent; } /** * Returns the closest non Extended element type for a given extended type * * @param requestElementType * the element type to study * @return the closest non extended element type or <code>null</code> if none was found. */ public static IElementType findClosestNonExtendedElementType(IExtendedHintedElementType requestElementType) { List<IElementType> superTypes = new ArrayList<IElementType>(Arrays.asList(requestElementType.getAllSuperTypes())); // reverse order for the list, because super type returns all super types from furthest to closest, we want the other order Collections.reverse(superTypes); for(IElementType superType : superTypes) { if(!(superType instanceof IExtendedHintedElementType)) { return superType; } } return null; } /** * Returns the closest super type which is not an extended type * * @param elementType * the element type for which the super type is searched. * @return the closest super type non extended or <code>null</code> if none was found */ public static IElementType getClosestDiagramType(IElementType elementType) { if(!(elementType instanceof IExtendedHintedElementType)) { return elementType; } // this is an extended type String diagramElementTypeID = ((IExtendedHintedElementType)elementType).getConfiguration().getSpecializedDiagramTypeID(); if(diagramElementTypeID != null) { return getClosestDiagramType(ElementTypeRegistry.getInstance().getType(diagramElementTypeID)); } else { IElementType[] superTypes = elementType.getAllSuperTypes(); if(superTypes.length > 1) { return getClosestDiagramType(superTypes[superTypes.length - 1]); } } return null; } }