blob: 360ad112978e74cdd8ddb43cc8b007e84fff35b6 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2004, 2009 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
****************************************************************************/
package org.eclipse.gmf.runtime.emf.core.util;
import java.lang.ref.WeakReference;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.gmf.runtime.emf.core.internal.util.MetamodelManager;
/**
* Some utility functions that work at the meta-class level.
*
* @author rafikj
*/
public class PackageUtil {
/**
* Mapping of {@link EClass} ==> name {@link EAttribute}. Use a weak
* map to allow reclamation of dynamically-generated Ecore models; in order
* for this to work, the keys are also weak refs.
*/
private static final Map NAME_ATTRIBUTES = new java.util.WeakHashMap();
/**
* Mapping of {@link EClass} ==> qualified name {@link EAttribute}.
* Use a weak map to allow reclamation of dynamically-generated Ecore
* models; in order for this to work, the keys are also weak refs.
*/
private static final Map QNAME_ATTRIBUTES = new java.util.WeakHashMap();
/**
* Gets the ID of a meta-model element. The ID of a meta-model element is
* the fully qualified name of the element going up to the root EPackage.
*
* @param element
* The Meta-model element.
* @return The ID.
*/
public static String getID(ENamedElement element) {
return MetamodelManager.getID(element);
}
/**
* Gets meta-model element by ID.
*
* @param id
* The element ID.
* @return The meta-model element.
*/
public static ENamedElement getElement(String id) {
return MetamodelManager.getElement(id);
}
/**
* Gets the localized name of a meta-model element. The name will not
* contain spaces.
*
* @param element
* The meta-model element.
* @return The localized name of the meta-model element.
*/
public static String getLocalizedName(ENamedElement element) {
return MetamodelManager.getLocalName(element);
}
/**
* Gets the localized display name of a meta-model element. Display name may
* contain spaces.
* <p>
* NOTE: This should be used to make model changes (e.g. name an element).
* When displaying strings in the UI (menus, dialogs, etc.) get the string
* from one of our resource managers.
* </p>
*
* @param element
* The meta-model element.
* @return The localized name of the meta-model element.
*/
public static String getDisplayName(ENamedElement element) {
return MetamodelManager.getDisplayName(element);
}
/**
* Checks if a container <code>EClass</code> can contain another
* <code>EClass</code>. The check can be recursive.
*
* @param class1
* The container <code>EClass</code>.
* @param class2
* The contained <code>EClass</code>.
* @param recursive
* True if recursive.
* @return True if an object can contain other objects of a given type.
*/
public static boolean canContain(EClass class1, EClass class2,
boolean recursive) {
return Util.canContain(class1, class2, recursive ? (new HashSet())
: null);
}
/**
* Checks if a container <code>EClass</code> can contain another
* <code>EClass</code> at a given containment reference. The check can be
* recursive.
*
* @param class1
* The container <code>EClass</code>.
* @param reference
* The reference.
* @param class2
* The contained <code>EClass</code>.
* @param recursive
* True if recursive.
* @return True if an object can contain other objects of a given type.
*/
public static boolean canContain(EClass class1, EReference reference,
EClass class2, boolean recursive) {
if ((reference.isContainment())
&& (class1.getEAllReferences().contains(reference))) {
EClass eType = (EClass) reference.getEType();
if ((eType.equals(class2)) || (eType.isSuperTypeOf(class2))) {
return true;
}
}
if (recursive) {
if (reference.isContainment()) {
EClass eType = (EClass) reference.getEType();
if (canContain(eType, class2, true))
return true;
}
}
return false;
}
/**
* Checks if a container <code>EClass</code> can reference another
* <code>EClass</code>.
*
* @param class1
* The referencer <code>EClass</code>.
* @param class2
* The referenced <code>EClass</code>.
* @return True if an object can contain other objects of a given type.
*/
public static boolean canReference(EClass class1, EClass class2) {
Iterator i = class1.getEAllReferences().iterator();
while (i.hasNext()) {
EReference reference = (EReference) i.next();
if (!reference.isContainment()) {
EClass eType = (EClass) reference.getEType();
if ((eType.equals(class2)) || (eType.isSuperTypeOf(class2))) {
return true;
}
}
}
return false;
}
/**
* Checks if a container <code>EClass</code> can reference another
* <code>EClass</code> at a given non-containment reference.
*
* @param class1
* The referencer <code>EClass</code>.
* @param reference
* The reference.
* @param class2
* The referenced <code>EClass</code>.
* @return True if an object can contain other objects of a given type.
*/
public static boolean canReference(EClass class1, EReference reference,
EClass class2) {
if ((!reference.isContainment())
&& (class1.getEAllReferences().contains(reference))) {
EClass eType = (EClass) reference.getEType();
if ((eType.equals(class2)) || (eType.isSuperTypeOf(class2))) {
return true;
}
}
return false;
}
/**
* Finds a feature that can contain an object of type eClass.
*
* @param container
* The container <code>EClass</code>.
* @param eClass
* The contained <code>EClass</code>.
* @return The found feature.
*/
public static EReference findFeature(EClass container, EClass eClass) {
Iterator i = container.getEAllReferences().iterator();
while (i.hasNext()) {
EReference reference = (EReference) i.next();
if (canContain(container, reference, eClass, false))
return reference;
}
return null;
}
/**
* Gets the name attribute of an <code>EClass</code>.
*
* @param eClass
* The <code>EClass</code>.
* @return The name attribute.
*/
public static EAttribute getNameAttribute(EClass eClass) {
EAttribute nameAttribute = null;
// first, try to get the cached attribute
WeakReference ref = (WeakReference) NAME_ATTRIBUTES.get(eClass);
if (ref != null) {
nameAttribute = (EAttribute) ref.get();
} else {
EStructuralFeature feature = eClass.getEStructuralFeature("name"); //$NON-NLS-1$
if (feature != null) {
if (feature instanceof EAttribute) {
EClassifier type = feature.getEType();
if (type != null) {
if (type.getInstanceClass() == String.class)
nameAttribute = (EAttribute) feature;
}
}
}
// cache the result, whatever it is. As long as the key (EClass)
// isn't GCed, then the value (WeakRef) will remain to indicate
// that we have at least cached a null
NAME_ATTRIBUTES.put(eClass, new WeakReference(nameAttribute));
}
return nameAttribute;
}
/**
* Gets the qualified name attribute of an <code>EClass</code>.
*
* @param eClass
* The <code>EClass</code>.
* @return The qualified name attribute.
*/
public static EAttribute getQualifiedNameAttribute(EClass eClass) {
EAttribute nameAttribute = null;
// first, try to get the cached attribute
WeakReference ref = (WeakReference) QNAME_ATTRIBUTES.get(eClass);
if (ref != null) {
nameAttribute = (EAttribute) ref.get();
} else {
EStructuralFeature feature = eClass
.getEStructuralFeature("qualifiedName"); //$NON-NLS-1$
if (feature != null) {
if ((feature instanceof EAttribute)
&& (feature.getEType().getInstanceClass() == String.class))
nameAttribute = (EAttribute) feature;
}
// cache the result, whatever it is. As long as the key (EClass)
// isn't GCed, then the value (WeakRef) will remain to indicate
// that we have at least cached a null
QNAME_ATTRIBUTES.put(eClass, new WeakReference(nameAttribute));
}
return nameAttribute;
}
private PackageUtil() {
// private
}
}