| /* |
| * Copyright (c) 2005 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 - initial API and implementation |
| * |
| * $Id: UML2Util.java,v 1.6 2005/12/16 03:54:53 khussey Exp $ |
| */ |
| package org.eclipse.uml2.common.util; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.emf.common.util.AbstractTreeIterator; |
| import org.eclipse.emf.common.util.DiagnosticChain; |
| import org.eclipse.emf.common.util.TreeIterator; |
| import org.eclipse.emf.common.util.UniqueEList; |
| import org.eclipse.emf.ecore.EAnnotation; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EClassifier; |
| import org.eclipse.emf.ecore.EDataType; |
| import org.eclipse.emf.ecore.EEnum; |
| import org.eclipse.emf.ecore.EModelElement; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.ETypedElement; |
| import org.eclipse.emf.ecore.EcoreFactory; |
| import org.eclipse.emf.ecore.EcorePackage; |
| import org.eclipse.emf.ecore.InternalEObject; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.emf.ecore.util.ECrossReferenceAdapter; |
| import org.eclipse.emf.ecore.util.EcoreSwitch; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| |
| /** |
| * @since 2.0 |
| */ |
| public class UML2Util { |
| |
| protected UML2Util() { |
| super(); |
| } |
| |
| public static interface EObjectMatcher { |
| |
| public boolean matches(EObject eObject); |
| |
| } |
| |
| public static class EClassMatcher |
| implements EObjectMatcher { |
| |
| protected final EObject eObject; |
| |
| public EClassMatcher(EObject eObject) { |
| super(); |
| |
| this.eObject = eObject; |
| } |
| |
| public boolean matches(EObject otherEObject) { |
| |
| return null == eObject || null == otherEObject |
| ? null == eObject && null == otherEObject |
| : eObject.eClass() == otherEObject.eClass(); |
| } |
| } |
| |
| public static interface Converter { |
| |
| Collection convert(Collection eObjects, Map options, |
| DiagnosticChain diagnostics, Map context); |
| |
| } |
| |
| protected static class UMLCrossReferenceAdapter |
| extends ECrossReferenceAdapter { |
| |
| protected void adapt(EObject eObject) { |
| Resource resource = eObject.eResource(); |
| |
| if (resource == null) { |
| addAdapter(EcoreUtil.getRootContainer(eObject)); |
| } else { |
| ResourceSet resourceSet = resource.getResourceSet(); |
| |
| if (resourceSet == null) { |
| addAdapter(resource); |
| } else { |
| addAdapter(resourceSet); |
| } |
| } |
| } |
| |
| public Collection getNonNavigableInverseReferences(EObject eObject) { |
| adapt(eObject); |
| return super.getNonNavigableInverseReferences(eObject); |
| } |
| |
| public Collection getInverseReferences(EObject eObject) { |
| adapt(eObject); |
| return super.getInverseReferences(eObject); |
| } |
| } |
| |
| protected static final UMLCrossReferenceAdapter CROSS_REFERENCE_ADAPTER = new UMLCrossReferenceAdapter(); |
| |
| /** |
| * The empty string. |
| */ |
| public static final String EMPTY_STRING = ""; //$NON-NLS-1$ |
| |
| protected static final String LINE_SEPARATOR = System.getProperties() |
| .getProperty("line.separator"); //$NON-NLS-1$ |
| |
| public static boolean safeEquals(Object thisObject, Object thatObject) { |
| return null == thisObject |
| ? null == thatObject |
| : thisObject.equals(thatObject); |
| } |
| |
| public static boolean isEmpty(String string) { |
| return null == string || 0 == string.length(); |
| } |
| |
| public static EObject findEObject(Collection eObjects, EObjectMatcher filter) { |
| return findEObject(eObjects.iterator(), filter); |
| } |
| |
| public static EObject findEObject(Iterator iterator, EObjectMatcher filter) { |
| |
| while (iterator.hasNext()) { |
| EObject eObject = (EObject) iterator.next(); |
| |
| if (filter.matches(eObject)) { |
| return eObject; |
| } |
| } |
| |
| return null; |
| } |
| |
| protected static EClassifier getCommonEType(EClassifier eType, |
| final EClassifier otherEType) { |
| |
| if (null == eType || eType.equals(otherEType)) { |
| return eType; |
| } else { |
| return (EClassifier) new EcoreSwitch() { |
| |
| public Object caseEClassifier(EClassifier eClassifier) { |
| |
| return EcorePackage.eINSTANCE.getEObject(); |
| } |
| |
| public Object caseEClass(EClass eClass) { |
| |
| if (otherEType instanceof EClass) { |
| EClass otherEClass = (EClass) otherEType; |
| |
| if (eClass.isSuperTypeOf(otherEClass)) { |
| return eClass; |
| } else if (otherEClass.isSuperTypeOf(eClass)) { |
| return otherEClass; |
| } |
| |
| for (Iterator eAllSuperTypes = eClass |
| .getEAllSuperTypes().iterator(); eAllSuperTypes |
| .hasNext();) { |
| |
| EClass eSuperType = (EClass) eAllSuperTypes.next(); |
| |
| if (eSuperType.isSuperTypeOf(otherEClass)) { |
| return eSuperType; |
| } |
| } |
| |
| for (Iterator otherEAllSuperTypes = otherEClass |
| .getEAllSuperTypes().iterator(); otherEAllSuperTypes |
| .hasNext();) { |
| |
| EClass otherESuperType = (EClass) otherEAllSuperTypes |
| .next(); |
| |
| if (otherESuperType.isSuperTypeOf(eClass)) { |
| return otherESuperType; |
| } |
| } |
| } |
| |
| return super.caseEClass(eClass); |
| } |
| |
| public Object caseEDataType(EDataType eDataType) { |
| return otherEType instanceof EDataType |
| && eDataType.getInstanceClass().equals( |
| ((EDataType) otherEType).getInstanceClass()) |
| ? eDataType |
| : EcorePackage.eINSTANCE.getEJavaObject(); |
| } |
| |
| public Object caseEEnum(EEnum eEnum) { |
| return otherEType instanceof EEnum |
| ? EcorePackage.eINSTANCE.getEEnumerator() |
| : EcorePackage.eINSTANCE.getEJavaObject(); |
| } |
| }.doSwitch(eType); |
| } |
| } |
| |
| protected static int getLesserLowerBound(int lowerBound, int otherLowerBound) { |
| return Math.min(lowerBound, otherLowerBound); |
| } |
| |
| protected static int getGreaterUpperBound(int upperBound, |
| int otherUpperBound) { |
| |
| return ETypedElement.UNBOUNDED_MULTIPLICITY == upperBound |
| || ETypedElement.UNBOUNDED_MULTIPLICITY == otherUpperBound |
| ? ETypedElement.UNBOUNDED_MULTIPLICITY |
| : Math.max(upperBound, otherUpperBound); |
| } |
| |
| /** |
| * Obtains a valid Java identifier based on the specified name. |
| * |
| * @param name |
| * The name from which to obtain a valid identifier. |
| * @return A valid (Java) identifier. |
| */ |
| protected static String getValidJavaIdentifier(String name) { |
| return getValidJavaIdentifier(name, new StringBuffer()).toString(); |
| } |
| |
| /** |
| * Appends a valid Java identifier based on the specified name to the |
| * specified buffer. |
| * |
| * @param name |
| * The name from which to obtain the valid identifier. |
| * @param validJavaIdentifier |
| * The buffer to which to append the valid identifier. |
| * @return The buffer. |
| */ |
| protected static StringBuffer getValidJavaIdentifier(String name, |
| StringBuffer validJavaIdentifier) { |
| |
| if (isEmpty(name)) { |
| validJavaIdentifier.append('_'); |
| } else { |
| char char_0 = name.charAt(0); |
| |
| if (Character.isJavaIdentifierStart(char_0)) { |
| validJavaIdentifier.append(char_0); |
| } else { |
| validJavaIdentifier.append('_'); |
| |
| if (Character.isJavaIdentifierPart(char_0)) { |
| validJavaIdentifier.append(char_0); |
| } |
| } |
| |
| for (int i = 1; i < name.length(); i++) { |
| char char_i = name.charAt(i); |
| |
| if (Character.isJavaIdentifierPart(char_i)) { |
| validJavaIdentifier.append(char_i); |
| } |
| } |
| } |
| |
| return validJavaIdentifier; |
| } |
| |
| protected static boolean isNCNameStart(char c) { |
| return Character.isLetter(c) || c == '_'; |
| } |
| |
| protected static boolean isNCNamePart(char c) { |
| return Character.isLetterOrDigit(c) || c == '.' || c == '-' || c == '_'; |
| } |
| |
| protected static String getValidNCName(String name) { |
| return getValidNCName(name, new StringBuffer()).toString(); |
| } |
| |
| protected static StringBuffer getValidNCName(String name, |
| StringBuffer validNCName) { |
| |
| if (isEmpty(name)) { |
| validNCName.insert(0, '_'); |
| } else { |
| |
| for (int i = name.length(); --i > 0;) { |
| char char_i = name.charAt(i); |
| |
| if (isNCNamePart(char_i)) { |
| validNCName.insert(0, char_i); |
| } |
| } |
| |
| char char_0 = name.charAt(0); |
| |
| if (isNCNameStart(char_0)) { |
| validNCName.insert(0, char_0); |
| } else { |
| |
| if (isNCNamePart(char_0)) { |
| validNCName.insert(0, char_0); |
| } |
| |
| validNCName.insert(0, '_'); |
| } |
| } |
| |
| return validNCName; |
| } |
| |
| protected static String getXMIIdentifier(InternalEObject internalEObject) { |
| return getXMIIdentifier(internalEObject, new StringBuffer()).toString(); |
| } |
| |
| protected static StringBuffer getXMIIdentifier( |
| InternalEObject internalEObject, StringBuffer xmiIdentifier) { |
| InternalEObject eInternalContainer = internalEObject |
| .eInternalContainer(); |
| Resource.Internal eDirectResource = internalEObject.eDirectResource(); |
| |
| while (eInternalContainer != null && eDirectResource == null) { |
| getValidNCName(eInternalContainer.eURIFragmentSegment( |
| internalEObject.eContainingFeature(), internalEObject), |
| xmiIdentifier); |
| |
| internalEObject = eInternalContainer; |
| eInternalContainer = internalEObject.eInternalContainer(); |
| eDirectResource = internalEObject.eDirectResource(); |
| |
| if (eInternalContainer != null && eDirectResource == null) { |
| xmiIdentifier.insert(0, '-'); |
| } |
| } |
| |
| if (eDirectResource != null) { |
| int index = eDirectResource.getContents().indexOf(internalEObject); |
| int length = xmiIdentifier.length(); |
| |
| if (index > 0 || length == 0) { |
| |
| if (length > 0) { |
| xmiIdentifier.insert(0, '-'); |
| } |
| |
| xmiIdentifier.insert(0, index); |
| xmiIdentifier.insert(0, '_'); |
| } |
| } |
| |
| return xmiIdentifier; |
| } |
| |
| public static int getInstanceCount(ResourceSet resourceSet, |
| EClassifier eClassifier) { |
| return getInstanceCount(resourceSet.getAllContents(), eClassifier); |
| } |
| |
| public static int getInstanceCount(Resource resource, |
| EClassifier eClassifier) { |
| return getInstanceCount(resource.getAllContents(), eClassifier); |
| } |
| |
| public static int getInstanceCount(EObject eObject, EClassifier eClassifier) { |
| return getInstanceCount(eObject.eAllContents(), eClassifier); |
| } |
| |
| public static int getInstanceCount(Iterator iterator, |
| EClassifier eClassifier) { |
| int count = 0; |
| |
| while (iterator.hasNext()) { |
| |
| if (eClassifier.isInstance(iterator.next())) { |
| count++; |
| } |
| } |
| |
| return count; |
| } |
| |
| protected static void addConstraint(EModelElement eModelElement, |
| String constraint) { |
| |
| if (!isEmpty(constraint)) { |
| List constraints = new ArrayList(EcoreUtil |
| .getConstraints(eModelElement)); |
| |
| constraints.add(constraint); |
| |
| EcoreUtil.setConstraints(eModelElement, constraints); |
| } |
| } |
| |
| protected static void addDocumentation(EModelElement eModelElement, |
| String text) { |
| |
| if (!isEmpty(text)) { |
| String documentation = EcoreUtil.getDocumentation(eModelElement); |
| |
| EcoreUtil.setDocumentation(eModelElement, null == documentation |
| ? text |
| : documentation + LINE_SEPARATOR + text); |
| } |
| } |
| |
| protected static Collection getRootContainers(Collection eObjects) { |
| Collection rootContainers = new UniqueEList(); |
| |
| for (Iterator i = eObjects.iterator(); i.hasNext();) { |
| rootContainers.add(EcoreUtil.getRootContainer((EObject) i.next())); |
| } |
| |
| return rootContainers; |
| } |
| |
| protected static TreeIterator getAllContents(EObject eObject, |
| boolean includeRoot, final boolean defensiveCopy) { |
| return new AbstractTreeIterator(eObject, includeRoot) { |
| |
| protected Iterator getChildren(Object object) { |
| return defensiveCopy |
| ? new ArrayList(((EObject) object).eContents()).iterator() |
| : ((EObject) object).eContents().iterator(); |
| } |
| }; |
| } |
| |
| protected static EAnnotation createEAnnotation(EModelElement eModelElement, |
| String source) { |
| EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation(); |
| |
| eAnnotation.setSource(source); |
| eAnnotation.setEModelElement(eModelElement); |
| |
| return eAnnotation; |
| } |
| |
| protected static EAnnotation getEAnnotation(EModelElement eModelElement, |
| String source, boolean createOnDemand) { |
| EAnnotation eAnnotation = eModelElement.getEAnnotation(source); |
| |
| return eAnnotation == null && createOnDemand |
| ? createEAnnotation(eModelElement, source) |
| : eAnnotation; |
| } |
| |
| protected static void destroy(EObject eObject) { |
| |
| if (eObject != null) { |
| |
| for (Iterator allContents = getAllContents(eObject, true, true); allContents |
| .hasNext();) { |
| |
| EObject containedEObject = (EObject) allContents.next(); |
| |
| for (Iterator inverseReferences = CROSS_REFERENCE_ADAPTER |
| .getInverseReferences(containedEObject).iterator(); inverseReferences |
| .hasNext();) { |
| |
| EStructuralFeature.Setting setting = (EStructuralFeature.Setting) inverseReferences |
| .next(); |
| |
| if (setting.getEStructuralFeature().isChangeable()) { |
| EcoreUtil.remove(setting, containedEObject); |
| } |
| } |
| |
| containedEObject.eAdapters().clear(); |
| } |
| |
| EcoreUtil.remove(eObject); |
| } |
| } |
| } |