blob: 223ecf312dd6c6ed5698101345fde3c2943674b1 [file] [log] [blame]
/*
* 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);
}
}