/* * Copyright (c) 2006, 2007 Borland Software Corp * * 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: * vano - initial API and implementation */ package org.eclipse.gmf.mappings.presentation; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import org.eclipse.emf.common.notify.AdapterFactory; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.emf.edit.provider.IItemLabelProvider; import org.eclipse.gmf.mappings.CanvasMapping; import org.eclipse.gmf.mappings.ChildReference; import org.eclipse.gmf.mappings.CompartmentMapping; import org.eclipse.gmf.mappings.FeatureInitializer; import org.eclipse.gmf.mappings.FeatureSeqInitializer; import org.eclipse.gmf.mappings.LinkMapping; import org.eclipse.gmf.mappings.Mapping; import org.eclipse.gmf.mappings.MappingEntry; import org.eclipse.gmf.mappings.NodeMapping; import org.eclipse.gmf.mappings.NodeReference; import org.eclipse.gmf.mappings.TopNodeReference; public class FilterUtil { public static <T> List<T> sort(Collection<T> eObjects) { ArrayList<T> result = new ArrayList<T>(eObjects); Collections.sort(result, new EObjectsComparator()); return result; } public static <T extends EObject> List<T> filterByResourceSet(Collection<T> eClasses, ResourceSet resourceSet) { return sort(filterValidEObjectsFrom(eClasses, resourceSet)); } public static List<EClass> filterByContainmentFeature(Collection<EClass> eClasses, MappingEntry mappingEntry) { EClass superType = null; if (mappingEntry instanceof NodeMapping) { NodeReference nodeReference = (NodeReference) mappingEntry.eContainer(); if (nodeReference != null) { EReference modelReference = nodeReference.getChildrenFeature() != null ? nodeReference.getChildrenFeature() : nodeReference.getContainmentFeature(); if (modelReference != null) { superType = modelReference.getEReferenceType(); } } } else if (mappingEntry instanceof LinkMapping) { if (((LinkMapping) mappingEntry).getContainmentFeature() != null) { superType = ((LinkMapping) mappingEntry).getContainmentFeature().getEReferenceType(); } } return sort(getConcreteEClasses(getSubtypesOf(filterValidEObjectsFrom(eClasses, mappingEntry.eResource().getResourceSet()), superType))); } public static List<EStructuralFeature> filterByContainerMetaclass(Collection<EStructuralFeature> eReferences, MappingEntry mappingEntry) { EClass containerMetaClass = mappingEntry.getDomainMetaElement(); return sort(getEStructuralFeaturesOf(eReferences, containerMetaClass)); } public static List<EReference> filterByContainerMetaclass(Collection<EReference> eReferences, NodeReference nodeReference, boolean containmentOnly) { EClass containerMetaClass = null; EClass targetMetaClass = null; if (nodeReference instanceof ChildReference) { containerMetaClass = ((ChildReference) nodeReference).getParentNode().getDomainMetaElement(); } else if (nodeReference instanceof TopNodeReference) { CanvasMapping diagram = ((Mapping) nodeReference.eContainer()).getDiagram(); if (diagram != null) { containerMetaClass = diagram.getDomainMetaElement(); } } if (nodeReference.isSetChild()) { targetMetaClass = nodeReference.getChild().getDomainMetaElement(); } List<EReference> fromHierarchy = sort(getEReferences(getEStructuralFeaturesOf(eReferences, containerMetaClass), containmentOnly)); if (targetMetaClass == null) { // no child known, thus can take references from metaelement's hierarchy only return fromHierarchy; } List<EReference> targetsToChild = sort(getEReferences(getEReferencesOfType(eReferences, targetMetaClass), containmentOnly)); for (Iterator<EReference> it = targetsToChild.iterator(); it.hasNext();) { if (fromHierarchy.contains(it.next())) { it.remove(); } } ArrayList<EReference> rv = new ArrayList<EReference>(fromHierarchy.size() + targetsToChild.size()); rv.addAll(fromHierarchy); rv.addAll(targetsToChild); return rv; } public static List<EReference> filterByReferenceType(Collection<EReference> eReferences, LinkMapping linkMapping) { EClass referenceType = linkMapping.getDomainMetaElement(); return sort(getEReferences(getEReferencesOfType(eReferences, referenceType), true)); } public static Collection<EObject> filterByNodeMapping(Collection<EObject> childReferences, CompartmentMapping mapping) { return sort(getChildrenOf(childReferences, mapping.getParentNode(), false)); } public static Collection<EObject> filterByNodeMapping(Collection<EObject> compartments, ChildReference childReference) { return getChildrenOf(compartments, childReference.getParentNode(), true); } public static Collection<?> filterBySuperClasses(Collection<?> instances, Class<?>[] classes) { return sort(getSubClassesOf(instances, classes)); } public static Collection<EStructuralFeature> filterByFeatureInitializer(Collection<EStructuralFeature> features, FeatureInitializer featureInitializer) { if(featureInitializer.getFeatureSeqInitializer() == null || featureInitializer.getFeatureSeqInitializer().getElementClass() == null) { return features; } EClass eClass = featureInitializer.getFeatureSeqInitializer().getElementClass(); List<EStructuralFeature> result = new ArrayList<EStructuralFeature>(getEStructuralFeaturesOf(features, eClass)); for (Iterator<EStructuralFeature> it = result.iterator(); it.hasNext();) { EStructuralFeature nextFeature = it.next(); if(nextFeature == null || !nextFeature.isChangeable()) { it.remove(); } } return result; } public static Collection<EClass> filterByFeatureSeqInitializer(Collection<EClass> eClasses, FeatureSeqInitializer featureSeqInitializer) { if(featureSeqInitializer.getCreatingInitializer() != null) { EStructuralFeature feature = featureSeqInitializer.getCreatingInitializer().getFeature(); if(feature != null && feature.getEType() instanceof EClass) { for (Iterator<EClass> it = eClasses.iterator(); it.hasNext();) { EClass nextEClass = it.next(); EClass typeEClass = (EClass)feature.getEType(); if(nextEClass == null || nextEClass.isAbstract() || nextEClass.isInterface() || !typeEClass.isSuperTypeOf(nextEClass)) { it.remove(); } } } } else if(featureSeqInitializer.getElementClass() != null) { return Collections.singleton(featureSeqInitializer.getElementClass()); } return eClasses; } public static Collection<EClass> getSubtypesOf(Collection<EClass> eClasses, EClass superType) { if (superType == null) { return eClasses; } for (Iterator<EClass> it = eClasses.iterator(); it.hasNext();) { EClass nextEClass = it.next(); if (nextEClass != null && !superType.isSuperTypeOf(nextEClass)) { it.remove(); } } return eClasses; } public static Collection<EClass> getConcreteEClasses(Collection<EClass> eClasses) { for (Iterator<EClass> it = eClasses.iterator(); it.hasNext();) { EClass nextEClass = it.next(); if (nextEClass != null && (nextEClass.isAbstract() || nextEClass.isInterface())) { it.remove(); } } return eClasses; } public static Collection<EReference> getEReferences(Collection<EReference> eReferences, boolean containmentOnly) { if (!containmentOnly) { return eReferences; } for (Iterator<EReference> it = eReferences.iterator(); it.hasNext();) { EReference nextReference = it.next(); if (nextReference != null && !nextReference.isContainment()) { it.remove(); } } return eReferences; } public static <T extends EStructuralFeature> Collection<T> getEStructuralFeaturesOf(Collection<T> structuralFeatures, EClass featureContainerEClass) { Collection<T> result = getValidEStructuralFeatures(structuralFeatures); if (featureContainerEClass == null) { return result; } for (Iterator<T> it = result.iterator(); it.hasNext();) { EStructuralFeature nextFeature = it.next(); if (nextFeature != null && !nextFeature.getEContainingClass().isSuperTypeOf(featureContainerEClass)) { it.remove(); } } return result; } public static Collection<EReference> getEReferencesOfType(Collection<EReference> references, EClass referenceType) { Collection<EReference> result = getValidEStructuralFeatures(references); if (referenceType == null) { return result; } for (Iterator<EReference> it = result.iterator(); it.hasNext();) { EReference nextFeature = it.next(); if (nextFeature != null && !nextFeature.getEReferenceType().isSuperTypeOf(referenceType)) { it.remove(); } } return result; } public static <T extends EStructuralFeature> Collection<T> getValidEStructuralFeatures(Collection<T> structuralFeatures) { Collection<T> result = getValidEObjects(structuralFeatures); for (Iterator<T> it = result.iterator(); it.hasNext();) { EStructuralFeature nextFeature = it.next(); if (nextFeature != null && (nextFeature.getEContainingClass() == null)) { it.remove(); } } return result; } public static <T extends EObject> Collection<T> filterValidEObjectsFrom(Collection<T> eClasses, ResourceSet resourceSet) { Collection<T> result = getValidEObjects(eClasses); for (Iterator<T> it = result.iterator(); it.hasNext();) { EObject nextEClass = it.next(); if (nextEClass == null) { continue; } if (nextEClass.eResource().getResourceSet() != resourceSet) { it.remove(); } } return result; } public static <T extends EObject> Collection<T> getValidEObjects(Collection<T> eObjects) { LinkedList<T> result = new LinkedList<T>(); for (T nextEObject : eObjects) { if (nextEObject != null && (nextEObject.eContainer() == null)) { continue; } result.add(nextEObject); } return result; } public static <T extends EObject> Collection<T> getChildrenOf(Collection<T> elements, EObject container, boolean addNull) { LinkedList<T> result = new LinkedList<T>(); for (T nextEObject : elements) { if (nextEObject == null ? addNull : nextEObject.eContainer() == container) { result.add(nextEObject); } } return result; } public static Collection<?> getSubClassesOf(Collection<?> instances, Class<?>[] classes) { LinkedList<Object> result = new LinkedList<Object>(); for (Object nextInstance : instances) { for (int i = 0; i < classes.length; i++) { if (nextInstance == null || classes[i].isAssignableFrom(nextInstance.getClass())) { result.add(nextInstance); break; } } } return result; } private static class EObjectsComparator implements Comparator<Object> { public int compare(Object o1, Object o2) { if (o1 instanceof EObject && o2 instanceof EObject) { EObject firstEObject = (EObject) o1; EObject secondEObject = (EObject) o2; return compareLabels(firstEObject, secondEObject); } return compareObjects(o1, o2); } private int compareObjects(Object o1, Object o2) { if (o1 == null) { return o2 == null ? 0 : 1; } else { return o2 == null ? -1 : 0; } } private int compareLabels(EObject firstEObject, EObject secondEObject) { String firstLabel = getLabel(firstEObject); String secondLabel = getLabel(secondEObject); return firstLabel == null ? (secondLabel == null ? 0 : 1) : (secondLabel == null ? -1 : firstLabel.compareTo(secondLabel)); } private String getLabel(EObject eObject) { AdapterFactory adapterFactory = getAdapterFactory(eObject); if (adapterFactory == null) { return ""; } IItemLabelProvider itemLabelProvider = (IItemLabelProvider) adapterFactory.adapt(eObject, IItemLabelProvider.class); return itemLabelProvider != null ? itemLabelProvider.getText(eObject) : eObject == null ? "" : eObject.toString(); } private AdapterFactory getAdapterFactory(EObject eObject) { EditingDomain editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(eObject); if (editingDomain instanceof AdapterFactoryEditingDomain) { return ((AdapterFactoryEditingDomain) editingDomain).getAdapterFactory(); } return null; } } }