blob: 0fba69b1a1855f1b1618c6796d3b3918969052d0 [file] [log] [blame]
/*******************************************************************************
* 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;
}