| /* |
| * Copyright (c) 2006, 2008 Borland Software Corporation |
| * |
| * 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: |
| * Artem Tikhomirov (Borland) - initial API and implementation |
| */ |
| package org.eclipse.gmf.internal.xpand; |
| |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.eclipse.emf.common.util.Enumerator; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EClassifier; |
| import org.eclipse.emf.ecore.EEnum; |
| import org.eclipse.emf.ecore.EOperation; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.EcoreFactory; |
| import org.eclipse.emf.ecore.EcorePackage; |
| import org.eclipse.gmf.internal.xpand.model.ExecutionContext; |
| import org.eclipse.gmf.internal.xpand.model.XpandDefinitionWrap; |
| import org.eclipse.gmf.internal.xpand.model.XpandIterator; |
| import org.eclipse.ocl.TypeResolver; |
| import org.eclipse.ocl.ecore.EcoreEnvironment; |
| import org.eclipse.ocl.ecore.EcoreEnvironmentFactory; |
| import org.eclipse.ocl.expressions.CollectionKind; |
| import org.eclipse.ocl.types.OCLStandardLibrary; |
| import org.eclipse.ocl.util.TypeUtil; |
| import org.eclipse.ocl.utilities.UMLReflection; |
| |
| /** |
| * XXX Guess, will need special support to recognize the fact |
| * EJavaObject.isSupertypeOf(EObject) |
| * |
| * @author artem |
| */ |
| public class BuiltinMetaModel { |
| public final static String SET = "Set"; |
| public final static String LIST = "List"; |
| |
| |
| private static EPackage XECORE = EcoreFactory.eINSTANCE.createEPackage(); |
| |
| static { |
| XECORE.setName("xecore"); |
| XECORE.setNsPrefix("xecore"); |
| XECORE.setNsURI("uri:org.eclipse.modeling/m2t/xpand/xecore/1.0"); |
| } |
| |
| public static final EClass DEFINITION_TYPE = EcoreFactory.eINSTANCE.createEClass(); |
| |
| static { |
| DEFINITION_TYPE.setName("xpand2::Definition"); |
| DEFINITION_TYPE.getESuperTypes().add(EcorePackage.eINSTANCE.getEClass()); // XXX perhaps, with OCL, some other superclassifier? |
| EOperation proceedOp = EcoreFactory.eINSTANCE.createEOperation(); |
| proceedOp.setName("proceed"); |
| proceedOp.setEType(EcorePackage.eINSTANCE.getEObject()); // FIXME not sure what do I need as a type here |
| DEFINITION_TYPE.setInstanceClass(XpandDefinitionWrap.class); |
| DEFINITION_TYPE.getEOperations().add(proceedOp); |
| XECORE.getEClassifiers().add(DEFINITION_TYPE); |
| } |
| |
| public static final EClass ITERATOR_TYPE = EcoreFactory.eINSTANCE.createEClass(); |
| |
| static { |
| ITERATOR_TYPE.setName("xpand2::Iterator"); |
| ITERATOR_TYPE.getESuperTypes().add(EcorePackage.eINSTANCE.getEClass()); |
| EOperation isFirstIteration = EcoreFactory.eINSTANCE.createEOperation(); |
| isFirstIteration.setName("isFirstIteration"); |
| isFirstIteration.setEType(EcorePackage.eINSTANCE.getEBoolean()); |
| EOperation isLastIteration = EcoreFactory.eINSTANCE.createEOperation(); |
| isLastIteration.setName("isLastIteration"); |
| isLastIteration.setEType(EcorePackage.eINSTANCE.getEBoolean()); |
| EOperation counter = EcoreFactory.eINSTANCE.createEOperation(); |
| counter.setName("counter"); |
| counter.setEType(EcorePackage.eINSTANCE.getELong()); |
| EOperation elements = EcoreFactory.eINSTANCE.createEOperation(); |
| elements.setName("elements"); |
| elements.setEType(EcorePackage.eINSTANCE.getELong()); |
| EOperation counter1 = EcoreFactory.eINSTANCE.createEOperation(); |
| counter1.setName("counter1"); |
| counter1.setEType(EcorePackage.eINSTANCE.getELong()); |
| ITERATOR_TYPE.getEOperations().add(isFirstIteration); |
| ITERATOR_TYPE.getEOperations().add(isLastIteration); |
| ITERATOR_TYPE.getEOperations().add(counter); |
| ITERATOR_TYPE.getEOperations().add(counter1); |
| ITERATOR_TYPE.getEOperations().add(elements); |
| ITERATOR_TYPE.setInstanceClass(XpandIterator.class); |
| XECORE.getEClassifiers().add(ITERATOR_TYPE); |
| } |
| |
| public static EClassifier getType(ExecutionContext ctx, Object obj) { |
| return getType(ctx.getOCLEnvironment(), obj); |
| } |
| |
| public static EClassifier getType(EcoreEnvironment env, Object obj) { |
| // XXX (1) not sure how Collections are handled |
| // FIXME (2) need to support own types (IteratorType and DefinitionType) |
| // if (obj instanceof Collection) { |
| // EClassifier type = null; |
| // if (!((Collection) obj).isEmpty()) { |
| // // FIXME respect all! elements in the collection, not only the first one |
| // type = getType(((Collection) obj).iterator().next()); |
| // } |
| // if (obj instanceof Set) { |
| // return collectionTypes.getSetType(type); |
| // } |
| // if (obj instanceof List) { |
| // return collectionTypes.getListType(type); |
| // } |
| // return collectionTypes.getCollectionType(type); |
| // } |
| // if (obj instanceof XpandDefinitionWrap) { |
| // return DEFINITION_TYPE; |
| // } |
| // if (obj instanceof XpandIterator) { |
| // return ITERATOR_TYPE; |
| // } |
| if (obj instanceof Collection<?>) { |
| EClassifier firstElementType = ((Collection<?>) obj).isEmpty() ? null : getType(env, ((Collection<?>) obj).iterator().next()); |
| TypeResolver<EClassifier, EOperation, EStructuralFeature> tr = env.getTypeResolver(); |
| OCLStandardLibrary<EClassifier> stdLib = env.getOCLStandardLibrary(); |
| if (obj instanceof Set<?>) { |
| // XXX odd TypeResolver - CollectionType returned is EDataType for Ecore, need to cast nevertheless |
| return (EClassifier) tr.resolveCollectionType(CollectionKind.SET_LITERAL, firstElementType == null ? stdLib.getOclVoid() : firstElementType); |
| } |
| if (obj instanceof List<?>) { |
| return (EClassifier) tr.resolveCollectionType(CollectionKind.SEQUENCE_LITERAL, firstElementType == null ? stdLib.getOclVoid() : firstElementType); |
| } |
| return (EClassifier) tr.resolveCollectionType(CollectionKind.COLLECTION_LITERAL, firstElementType == null ? stdLib.getOclVoid() : firstElementType); |
| } |
| /** |
| * It's not possible to determine a type (meta-object) of Enumeration |
| * instance, so returning EEnumerator from here wich will be specially |
| * processed in getRelationship() method |
| */ |
| if (obj instanceof Enumerator) { |
| return EcorePackage.eINSTANCE.getEEnumerator(); |
| } |
| /** |
| * Workaround for current implementation of |
| * EcoreEnvironmentFactory.oclType(obj) - for now it returns OclAny |
| * instead of OclVoid if null was passed as a parameter |
| */ |
| if (obj == null) { |
| return env.getOCLStandardLibrary().getOclVoid(); |
| } |
| return EcoreEnvironmentFactory.INSTANCE.createEvaluationEnvironment().getType(obj); |
| // return TypeUtil.resolveType(ctx.getOCLEnvironment(), ee.getType(obj)); |
| } |
| |
| /** |
| * @param ctx |
| * @return true if first argument is more general and second is more |
| * specific, think Object and String |
| * @see AbstractTypeImpl.isAssignableFrom(this, t) |
| */ |
| public static boolean isAssignableFrom(ExecutionContext ctx, EClassifier t1, EClassifier t2) { |
| return 0 != (UMLReflection.SUBTYPE & getRelationship(ctx.getOCLEnvironment(), t1, t2)); |
| } |
| |
| public static int getRelationship(EcoreEnvironment env, EClassifier t1, EClassifier t2) { |
| /** |
| * Special processing for EEnumerator returned as a type for any |
| * enumeration instances - see above |
| */ |
| if (t1 instanceof EEnum && t2 == EcorePackage.eINSTANCE.getEEnumerator()) { |
| return UMLReflection.SUBTYPE; // HACK - any enumerator instance can be assigned to any enum attribute. |
| } |
| return TypeUtil.getRelationship(env, t2, t1); |
| } |
| } |