package org.applause.lang.scoping; import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; import org.applause.lang.applauseDsl.ApplauseDslFactory; import org.applause.lang.applauseDsl.CollectionIterator; import org.applause.lang.applauseDsl.CollectionLiteral; import org.applause.lang.applauseDsl.ComplexProviderConstruction; import org.applause.lang.applauseDsl.ContentProvider; import org.applause.lang.applauseDsl.Expression; import org.applause.lang.applauseDsl.ObjectReference; import org.applause.lang.applauseDsl.Parameter; import org.applause.lang.applauseDsl.Property; import org.applause.lang.applauseDsl.ProviderConstruction; import org.applause.lang.applauseDsl.ScalarExpression; import org.applause.lang.applauseDsl.SimpleProviderConstruction; import org.applause.lang.applauseDsl.SimpleType; import org.applause.lang.applauseDsl.StringConcat; import org.applause.lang.applauseDsl.StringFunction; import org.applause.lang.applauseDsl.StringLiteral; import org.applause.lang.applauseDsl.StringReplace; import org.applause.lang.applauseDsl.StringSplit; import org.applause.lang.applauseDsl.StringUrlConform; import org.applause.lang.applauseDsl.Type; import org.applause.lang.applauseDsl.TypeDescription; import org.applause.lang.applauseDsl.VariableDeclaration; import org.applause.lang.applauseDsl.util.ApplauseDslSwitch; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.xtext.EcoreUtil2; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; public class TypeUtil { // public class TypeDesc { // private final Type type; // private final boolean many; // // public TypeDesc(Type type, boolean many) { // this.type = type; // this.many = many; // } // // public Type getType() { // return type; // } // public boolean isMany() { // return many; // } // } private static ApplauseDslSwitch<TypeDescription> typeOf = new ApplauseDslSwitch<TypeDescription>() { public TypeDescription caseProperty(Property object) { return object.getDescription(); }; public TypeDescription caseVariableDeclaration(VariableDeclaration object) { return null; }; public TypeDescription caseParameter(Parameter object) { return object.getDescription(); }; public TypeDescription caseCollectionIterator(CollectionIterator object) { return createDesc(doGetTypeOf(object.getCollection()).getType(), false); }; public TypeDescription caseObjectReference(ObjectReference object) { while (object.getTail() != null) object = object.getTail(); return doGetTypeOf(object.getObject()); }; public Type getStringType(EObject object) { EObject model = EcoreUtil.getRootContainer(object); List<SimpleType> allSimpleTypes = EcoreUtil2.getAllContentsOfType(model, SimpleType.class); Predicate<SimpleType> stringTypePredicate = new Predicate<SimpleType>() { public boolean apply(SimpleType input) { return "String".equals(input.getName()); } }; try { return Iterables.getOnlyElement(Iterables.filter(allSimpleTypes, stringTypePredicate)); } catch(NoSuchElementException ex) { return null; } } public TypeDescription caseStringLiteral(StringLiteral object) { return createStringDesc(object); } public TypeDescription caseStringFunction(StringFunction object) { return createStringDesc(object); }; public TypeDescription caseStringSplit(StringSplit object) { return createDesc(getStringType(object), true); }; private TypeDescription createStringDesc(EObject object) { return createDesc(getStringType(object), false); }; private TypeDescription createDesc(Type type, boolean isMany) { TypeDescription result = ApplauseDslFactory.eINSTANCE.createTypeDescription(); result.setMany(isMany); result.setType(type); return result; }; public TypeDescription caseCollectionLiteral(CollectionLiteral object) { return createDesc(doGetTypeOf(object.getItems().get(0)).getType(), true); }; public TypeDescription caseComplexProviderConstruction(ComplexProviderConstruction object) { ContentProvider p = object.getProvider(); if(p==null) return null; return createDesc(p.getType(), p.isMany()); }; public TypeDescription caseSimpleProviderConstruction(SimpleProviderConstruction object) { return doGetTypeOf(object.getExpression()); }; }; private static TypeDescription doGetTypeOf(EObject object) { // System.out.println("doGetTypeOf: " + object.eClass().getName()); TypeDescription result = typeOf.doSwitch(object); if(result == null) { typeOf.doSwitch(object); } return result; } public static TypeDescription getTypeOf(ScalarExpression expression) { return doGetTypeOf(expression); } public static TypeDescription getTypeOf(VariableDeclaration declaration) { return doGetTypeOf(declaration); } public static TypeDescription getTypeOf(Expression expression) { return doGetTypeOf(expression); } public static TypeDescription getTypeOf(ProviderConstruction construction) { return doGetTypeOf(construction); } public static ApplauseDslSwitch<Iterable<ObjectReference>> referencesIn = new ApplauseDslSwitch<Iterable<ObjectReference>>() { public Iterable<ObjectReference> caseScalarExpression(ScalarExpression object) { return Iterables.emptyIterable(); }; public Iterable<ObjectReference> caseObjectReference(ObjectReference object) { return Arrays.asList(object); }; public Iterable<ObjectReference> caseStringConcat(StringConcat sc) { Iterable<ObjectReference> result = Iterables.emptyIterable(); for(ScalarExpression e : sc.getValues()) { result = Iterables.concat(result, getReferencesIn(e)); } return result; }; public Iterable<ObjectReference> caseStringUrlConform(StringUrlConform object) { return getReferencesIn(object.getValue()); }; @SuppressWarnings("unchecked") public Iterable<ObjectReference> caseStringReplace(StringReplace object) { return Iterables.concat( getReferencesIn(object.getValue()), getReferencesIn(object.getMatch()), getReferencesIn(object.getReplacement()) ); }; }; public static List<ObjectReference> getReferencesIn(ScalarExpression e) { return ImmutableList.copyOf(referencesIn.doSwitch(e)); } public static boolean isAssignable(TypeDescription target, TypeDescription value) { if(target == null || value == null) return false; return isAssignable(target.getType(), value.getType()) && (target.isMany() == value.isMany()); } private static boolean isAssignable(Type target, Type value) { if(target == null || value == null) return false; // look at type hierarchy return target == value; } public static String asReadableString(TypeDescription desc) { if(desc==null || desc.getType() == null) return "unknown"; return desc.getType().getName() + (desc.isMany()?"[]":""); } }