package org.eclipse.emf.ecore.xcore.scoping;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.emf.codegen.ecore.genmodel.GenModel;
import org.eclipse.emf.codegen.ecore.genmodel.GenModelFactory;
import org.eclipse.emf.codegen.ecore.genmodel.GenModelPackage;
import org.eclipse.emf.common.EMFPlugin;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.plugin.EcorePlugin;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xcore.XPackage;
import org.eclipse.emf.ecore.xcore.XcorePackage;
import org.eclipse.emf.ecore.xcore.util.EcoreXcoreBuilder;
import org.eclipse.emf.ecore.xcore.util.XcoreJvmInferrer;
import org.eclipse.xtext.common.types.TypesPackage;
import org.eclipse.xtext.naming.IQualifiedNameConverter;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.resource.AbstractEObjectDescription;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.resource.IResourceDescription;
import org.eclipse.xtext.resource.ISelectable;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.impl.AbstractScope;
import org.eclipse.xtext.scoping.impl.ImportNormalizer;
import org.eclipse.xtext.scoping.impl.ImportScope;
import org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider;
import org.eclipse.xtext.util.Strings;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
import com.google.inject.Provider;
public class XcoreImportedNamespaceAwareScopeProvider extends ImportedNamespaceAwareLocalScopeProvider
{
private static final URI ECORE_XCORE_URI = URI.createURI("platform:/plugin/org.eclipse.emf.ecore/model/Ecore.xcore");
private static final URI ECORE_GEN_MODEL_URI =
EMFPlugin.IS_ECLIPSE_RUNNING ?
URI.createURI("platform:/plugin/org.eclipse.emf.ecore/model/Ecore.genmodel"):
URI.createURI(EcorePlugin.INSTANCE.getBaseURL().toString() + "model/Ecore.genmodel");
@Inject
private IQualifiedNameConverter nameConverter;
@Inject
private Provider<EcoreXcoreBuilder> ecoreXcoreBuilderProvider;
@Inject
private XcoreJvmInferrer jvmInferrer;
@Inject
private IResourceDescription.Manager manager;
@Override
protected IScope getResourceScope(IScope parent, EObject context, EReference reference)
{
IScope resourceScope = super.getResourceScope(parent, context, reference);
if (reference == XcorePackage.Literals.XGENERIC_TYPE__TYPE)
{
return
new ImportScope
(getImplicitImports(false),
new EClassifierScope(resourceScope, context.eResource().getResourceSet(), nameConverter, ecoreXcoreBuilderProvider, jvmInferrer),
null,
GenModelPackage.Literals.GEN_BASE,
false);
}
else
{
return resourceScope;
}
}
@Override
public IScope getScope(EObject context, EReference reference)
{
if (reference == XcorePackage.Literals.XIMPORT_DIRECTIVE__IMPORTED_OBJECT)
{
final IScope classifierScope = getResourceScope(context.eResource(), XcorePackage.Literals.XGENERIC_TYPE__TYPE);
final IScope annotationScope = getResourceScope(context.eResource(), XcorePackage.Literals.XANNOTATION__SOURCE);
final IScope jvmTypeScope = getResourceScope(context.eResource(), TypesPackage.Literals.JVM_PARAMETERIZED_TYPE_REFERENCE__TYPE);
return
new IScope()
{
public IEObjectDescription getSingleElement(QualifiedName name)
{
IEObjectDescription result = classifierScope.getSingleElement(name);
if (result == null)
{
result = annotationScope.getSingleElement(name);
}
if (result == null)
{
result = jvmTypeScope.getSingleElement(name);
}
return result;
}
public Iterable<IEObjectDescription> getElements(QualifiedName name)
{
return Iterables.concat(classifierScope.getElements(name), annotationScope.getElements(name), jvmTypeScope.getElements(name));
}
public IEObjectDescription getSingleElement(EObject object)
{
IEObjectDescription result = classifierScope.getSingleElement(object);
if (result == null)
{
result = annotationScope.getSingleElement(object);
}
if (result == null)
{
result = jvmTypeScope.getSingleElement(object);
}
return result;
}
public Iterable<IEObjectDescription> getElements(EObject object)
{
return Iterables.concat(classifierScope.getElements(object), annotationScope.getElements(object), jvmTypeScope.getElements(object));
}
public Iterable<IEObjectDescription> getAllElements()
{
return Iterables.concat(classifierScope.getAllElements(), annotationScope.getAllElements(), jvmTypeScope.getAllElements());
}
};
}
else
{
return super.getScope(context, reference);
}
}
@Override
protected List<ImportNormalizer> internalGetImportedNamespaceResolvers(EObject context, boolean ignoreCase)
{
if (!(context instanceof XPackage))
{
return Collections.emptyList();
}
else
{
List<ImportNormalizer> importedNamespaceResolvers = super.internalGetImportedNamespaceResolvers(context, ignoreCase);
String name = ((XPackage)context).getName();
if (!Strings.isEmpty(name))
{
importedNamespaceResolvers.add(new ImportNormalizer(nameConverter.toQualifiedName(name), true, ignoreCase));
}
return importedNamespaceResolvers;
}
}
@Override
protected boolean isRelativeImport()
{
return false;
}
@Override
protected List<ImportNormalizer> getImplicitImports(boolean ignoreCase)
{
return Collections.singletonList(new ImportNormalizer(nameConverter.toQualifiedName("java.lang"), true, ignoreCase));
}
@Override
protected ISelectable internalGetAllDescriptions(Resource resource)
{
IResourceDescription description = manager.getResourceDescription(resource);
return description;
}
protected static class EClassifierScope extends AbstractScope
{
protected static final EDataType [] IMPLICIT_ALIASES =
new EDataType[]
{
EcorePackage.Literals.EBIG_DECIMAL,
EcorePackage.Literals.EBIG_INTEGER,
EcorePackage.Literals.EBOOLEAN,
EcorePackage.Literals.EBOOLEAN_OBJECT,
EcorePackage.Literals.EBYTE,
EcorePackage.Literals.EBYTE_OBJECT,
EcorePackage.Literals.ECHAR,
EcorePackage.Literals.ECHARACTER_OBJECT,
EcorePackage.Literals.EDATE,
EcorePackage.Literals.EDOUBLE,
EcorePackage.Literals.EDOUBLE_OBJECT,
EcorePackage.Literals.EFLOAT,
EcorePackage.Literals.EFLOAT_OBJECT,
EcorePackage.Literals.EINT,
EcorePackage.Literals.EINTEGER_OBJECT,
EcorePackage.Literals.EJAVA_CLASS,
EcorePackage.Literals.EJAVA_OBJECT,
EcorePackage.Literals.ELONG,
EcorePackage.Literals.ELONG_OBJECT,
EcorePackage.Literals.ESHORT,
EcorePackage.Literals.ESHORT_OBJECT,
EcorePackage.Literals.ESTRING,
};
private ResourceSet resourceSet;
private IQualifiedNameConverter nameConverter;
private Provider<EcoreXcoreBuilder> ecoreXcoreBuilderProvider;
private XcoreJvmInferrer jvmInferrer;
public EClassifierScope
(IScope parent,
ResourceSet resourceSet,
IQualifiedNameConverter nameConverter,
Provider<EcoreXcoreBuilder> ecoreXcoreBuilderProvider,
XcoreJvmInferrer jvmInferrer)
{
super(parent, false);
this.resourceSet = resourceSet;
this.nameConverter = nameConverter;
this.ecoreXcoreBuilderProvider = ecoreXcoreBuilderProvider;
this.jvmInferrer = jvmInferrer;
}
@Override
protected Iterable<IEObjectDescription> getAllLocalElements()
{
ArrayList<IEObjectDescription> result = new ArrayList<IEObjectDescription>();
for (final EDataType eDataType : IMPLICIT_ALIASES)
{
String instanceClassName = eDataType.getInstanceClassName();
final QualifiedName actualQualifiedName = QualifiedName.create("org", "eclipse", "emf", "ecore", eDataType.getName());
final QualifiedName qualifiedName = nameConverter.toQualifiedName(instanceClassName);
AbstractEObjectDescription eObjectDescription =
new AbstractEObjectDescription()
{
public QualifiedName getQualifiedName()
{
return qualifiedName;
}
public QualifiedName getName()
{
return qualifiedName;
}
public URI getEObjectURI()
{
IEObjectDescription element = getElement();
return element == null ? getSyntheticEObjectURI() : element.getEObjectURI();
}
public EObject getEObjectOrProxy()
{
IEObjectDescription element = getElement();
if (element == null)
{
InternalEObject genDataType = (InternalEObject)GenModelFactory.eINSTANCE.createGenDataType();
genDataType.eSetProxyURI(getSyntheticEObjectURI());
return genDataType;
}
else
{
return element.getEObjectOrProxy();
}
}
public EClass getEClass()
{
return GenModelPackage.Literals.GEN_DATA_TYPE;
}
protected URI getSyntheticEObjectURI()
{
return ECORE_XCORE_URI.appendFragment("/1/ecore/" + eDataType.getName());
}
protected IEObjectDescription getElement()
{
IEObjectDescription element = getParent().getSingleElement(actualQualifiedName);
if (element == null)
{
Resource ecoreXcoreResource = resourceSet.getResource(ECORE_XCORE_URI, false);
if (ecoreXcoreResource == null)
{
Resource genModelResource = resourceSet.getResource(ECORE_GEN_MODEL_URI, true);
GenModel genModel = (GenModel)genModelResource.getContents().get(0);
ecoreXcoreResource = resourceSet.getResource(ECORE_XCORE_URI, false);
EPackage ePackage = genModel.getGenPackages().get(0).getEcorePackage();
Resource ecoreResource = ePackage.eResource();
EcoreXcoreBuilder ecoreXcoreBuilder = ecoreXcoreBuilderProvider.get();
ecoreXcoreBuilder.initialize(genModel);
EcoreUtil.resolveAll(genModel);
XPackage xPackage = ecoreXcoreBuilder.getXPackage(ePackage);
ecoreXcoreResource = resourceSet.createResource(ECORE_XCORE_URI);
ecoreXcoreResource.getContents().add(xPackage);
ecoreXcoreResource.getContents().add(genModel);
ecoreXcoreResource.getContents().add(ePackage);
ecoreXcoreBuilder.link();
ecoreXcoreResource.getContents().addAll(jvmInferrer.getDeclaredTypes(xPackage));
resourceSet.getResources().remove(genModelResource);
resourceSet.getResources().remove(ecoreResource);
}
}
return element;
}
};
result.add(eObjectDescription);
}
return result;
}
}
}