| /******************************************************************************* |
| * Copyright (c) 2006 Eclipse.org |
| * |
| * 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 |
| *******************************************************************************/ |
| package org.eclipse.gmf.internal.xpand; |
| |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.LinkedList; |
| import java.util.Map; |
| |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EClassifier; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.EcoreFactory; |
| import org.eclipse.emf.ecore.EcorePackage; |
| |
| public class CollectionTypesSupport { |
| |
| private final Map<EClassifier, EClass> collectionsM1 = new HashMap<EClassifier, EClass>(); |
| private final Map<EClassifier, EClass> listsM1 = new HashMap<EClassifier, EClass>(); |
| private final Map<EClassifier, EClass> setsM1 = new HashMap<EClassifier, EClass>(); |
| |
| // These are M2 elements, next to EClass and EReferences, extension of ECore |
| // meta model |
| static final EClass COLLECTION_TYPE = EcoreFactory.eINSTANCE.createEClass(); |
| static final EClass LIST_TYPE = EcoreFactory.eINSTANCE.createEClass(); |
| static final EClass SET_TYPE = EcoreFactory.eINSTANCE.createEClass(); |
| |
| @SuppressWarnings("unchecked") |
| void init(EPackage xecore, EClass parameterizedType) { |
| COLLECTION_TYPE.setName("Collection"); |
| LIST_TYPE.setName("List"); |
| SET_TYPE.setName("Set"); |
| COLLECTION_TYPE.getESuperTypes().add(parameterizedType); |
| LIST_TYPE.getESuperTypes().add(COLLECTION_TYPE); |
| SET_TYPE.getESuperTypes().add(COLLECTION_TYPE); |
| xecore.getEClassifiers().add(COLLECTION_TYPE); |
| xecore.getEClassifiers().add(LIST_TYPE); |
| xecore.getEClassifiers().add(SET_TYPE); |
| |
| COLLECTION_OF_OBJECT = newCollectionType(EcorePackage.eINSTANCE.getEJavaObject()); |
| LIST_OF_OBJECT = newListType(EcorePackage.eINSTANCE.getEJavaObject()); |
| SET_OF_OBJECT = newSetType(EcorePackage.eINSTANCE.getEJavaObject()); |
| // XXX why didn't I put LIST_OF_* into collectionsM1, listsM1 and setsM1? |
| // treat collections without type, like {}, as collections of 'void' which is assignable to anything |
| collectionsM1.put(null, newCollectionType(BuiltinMetaModel.VOID)); |
| listsM1.put(null, newListType(BuiltinMetaModel.VOID)); |
| setsM1.put(null, newSetType(BuiltinMetaModel.VOID)); |
| } |
| |
| |
| /** |
| * @param name |
| * @return true if name is one of M2 collection meta-types (either Collection, List, Set) |
| */ |
| public boolean isCollectionMetaType(String name) { |
| return COLLECTION_TYPE.getName().equals(name) || LIST_TYPE.getName().equals(name) || SET_TYPE.getName().equals(name); |
| } |
| |
| public EClass getCollectionType(String metaTypeName, EClassifier innerType) { |
| assert isCollectionMetaType(metaTypeName); |
| if (LIST_TYPE.getName().equals(metaTypeName)) { |
| return getListType(innerType); |
| } |
| if (SET_TYPE.getName().equals(metaTypeName)) { |
| return getSetType(innerType); |
| } |
| if (COLLECTION_TYPE.getName().equals(metaTypeName)) { |
| return getCollectionType(innerType); |
| } |
| throw new IllegalStateException(); |
| } |
| |
| /*package*/ EClass getCollectionType(EClass metaType, EClassifier innerType) { |
| if (LIST_TYPE.equals(metaType)) { |
| return getListType(innerType); |
| } |
| if (SET_TYPE.equals(metaType)) { |
| return getSetType(innerType); |
| } |
| if (COLLECTION_TYPE.equals(metaType)) { |
| return getCollectionType(innerType); |
| } |
| throw new IllegalStateException(); |
| } |
| |
| |
| Collection newInstance(EClassifier m1) { |
| if (m1.eClass() == LIST_TYPE) { |
| return new LinkedList<Object>(); |
| } |
| if (m1.eClass() == SET_TYPE) { |
| return new HashSet<Object>(); |
| } |
| // can't create instance of Collection, right? |
| return null; |
| } |
| |
| public EClass getCollectionType(EClassifier innerType) { |
| EClass existing = collectionsM1.get(innerType); |
| if (existing == null) { |
| existing = newCollectionType(innerType); |
| collectionsM1.put(innerType, existing); |
| } |
| return existing; |
| } |
| |
| public EClass getListType(EClassifier innerType) { |
| EClass existing = listsM1.get(innerType); |
| if (existing == null) { |
| existing = newListType(innerType); |
| listsM1.put(innerType, existing); |
| } |
| return existing; |
| } |
| |
| public EClass getSetType(EClassifier innerType) { |
| EClass existing = setsM1.get(innerType); |
| if (existing == null) { |
| existing = newSetType(innerType); |
| setsM1.put(innerType, existing); |
| } |
| return existing; |
| } |
| |
| // way to implicitly extend user's model with typed lists |
| @SuppressWarnings("unchecked") |
| private static EClass newCollectionType(EClassifier innerType) { |
| EClass c = BuiltinMetaModel.internalNewParameterizedType(COLLECTION_TYPE, innerType); |
| // @see CollectionTypeImpl.getSuperTypes |
| c.getESuperTypes().add(EcorePackage.eINSTANCE.getEObject()); |
| return c; |
| } |
| |
| @SuppressWarnings("unchecked") |
| private static EClass newListType(EClassifier innerType) { |
| EClass c = BuiltinMetaModel.internalNewParameterizedType(LIST_TYPE, innerType); |
| // @see ListTypeImpl.getSuperTypes |
| c.getESuperTypes().add(COLLECTION_OF_OBJECT); // XXX perhaps, collection(inner) may be required |
| return c; |
| } |
| |
| @SuppressWarnings("unchecked") |
| private static EClass newSetType(EClassifier innerType) { |
| EClass c = BuiltinMetaModel.internalNewParameterizedType(SET_TYPE, innerType); |
| // @see SetTypeImpl.getSuperTypes |
| c.getESuperTypes().add(COLLECTION_OF_OBJECT); // XXX perhaps, collection(inner) may be required |
| return c; |
| } |
| |
| /* |
| * 1. Actually, [List|Set]TypeImpl extend Collection(innerType), but I guess |
| * it's an overkill |
| * |
| * 2. Instead of analyze's code (working with M1) EClassifier targetType = |
| * XEClass "OrderList" |
| * isAssignableFrom(BuiltinMetaModel.COLLECTION_OF_OBJECT, targetType) and |
| * having all these hierarchies of list|set extending collection (above) |
| * would be better to check |
| * COLLECTION_TYPE.isSuperClassOf("OrderCollection".eClass) |
| */ |
| |
| // These are M1 elements, next to user's "Purchase" and "Order" classes, |
| // user's model |
| // during analyze, we have EClasses from same meta-level |
| // and during evaluate, we work with instances of these |
| static EClass COLLECTION_OF_OBJECT; |
| static EClass LIST_OF_OBJECT; |
| static EClass SET_OF_OBJECT; |
| } |