blob: ead8ecca4c8a3fe080ea11598653a1889b677ee3 [file] [log] [blame]
/**
* Copyright (c) 2002-2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* IBM - Initial API and implementation
*/
package org.eclipse.emf.importer.java.builder;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.jar.Manifest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.emf.codegen.ecore.CodeGenEcorePlugin;
import org.eclipse.emf.codegen.ecore.genmodel.GenModel;
import org.eclipse.emf.codegen.ecore.genmodel.GenPackage;
import org.eclipse.emf.codegen.merge.java.JMerger;
import org.eclipse.emf.codegen.merge.java.facade.FacadeHelper;
import org.eclipse.emf.codegen.merge.java.facade.JAbstractType;
import org.eclipse.emf.codegen.merge.java.facade.JAnnotationType;
import org.eclipse.emf.codegen.merge.java.facade.JCompilationUnit;
import org.eclipse.emf.codegen.merge.java.facade.JEnum;
import org.eclipse.emf.codegen.merge.java.facade.JEnumConstant;
import org.eclipse.emf.codegen.merge.java.facade.JField;
import org.eclipse.emf.codegen.merge.java.facade.JImport;
import org.eclipse.emf.codegen.merge.java.facade.JMember;
import org.eclipse.emf.codegen.merge.java.facade.JMethod;
import org.eclipse.emf.codegen.merge.java.facade.JNode;
import org.eclipse.emf.codegen.merge.java.facade.JPackage;
import org.eclipse.emf.codegen.merge.java.facade.JType;
import org.eclipse.emf.codegen.util.CodeGenUtil;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.BasicMonitor;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.emf.common.util.Monitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.UniqueEList;
import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.EGenericType;
import org.eclipse.emf.ecore.EModelElement;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EParameter;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.ETypeParameter;
import org.eclipse.emf.ecore.ETypedElement;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.EcorePackage;
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.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.EcoreValidator;
import org.eclipse.emf.ecore.util.ExtendedMetaData;
import org.eclipse.emf.ecore.xml.namespace.XMLNamespacePackage;
import org.eclipse.emf.ecore.xml.type.XMLTypePackage;
import org.eclipse.emf.importer.ModelImporter;
import org.eclipse.emf.importer.java.JavaImporterPlugin;
public class JavaEcoreBuilder
{
/**
* The factory used to create JNodes.
*/
protected static FacadeHelper facadeHelper = CodeGenUtil.instantiateFacadeHelper(JMerger.DEFAULT_FACADE_HELPER_CLASS);
/**
* The file being generated.
*/
protected IFile genModelFile;
/**
* The GenModel being generated.
*/
protected GenModel genModel;
/**
* The map from a package name to the corresponding package.
* These are populated from the GenModels of required projects.
*/
protected Map<String, EPackage> externalPackageNameToEPackageMap = new LinkedHashMap<String, EPackage>();
/**
* The map from a package name to the corresponding package.
* These are populated on demand during traversal as modeled class and enums are discovered.
*/
protected Map<String, EPackage> packageNameToEPackageMap = new LinkedHashMap<String, EPackage>();
/**
* The map from package to the map of ordering constants.
* These are populated as the package interface is traversed.
*/
protected Map<EPackage, Map<Object, Integer>> ePackageToOrderingMap = new LinkedHashMap<EPackage, Map<Object, Integer>>();
/**
* The map from package to the it's prefix.
* These are populated as the package interfaces are traversed.
*/
protected Map<EPackage, String> ePackageToPrefixMap = new LinkedHashMap<EPackage, String>();
/**
* The map from a model element to the corresponding JNode.
* These are populated during traversal as each model element is created.
*/
protected Map<EModelElement, JNode> eModelElementToJNodeMap = new LinkedHashMap<EModelElement, JNode>();
/**
* The features handled during the traversal.
* These are populated during traversal as each feature is created.
* They must be patched after traversal is completed to ensure they have resolved to the right type of classifier.
*/
protected Set<EStructuralFeature> eStructuralFeatures = new LinkedHashSet<EStructuralFeature>();
/**
* The attributes that must be treated as attributes because the are explicitly declared to be of that kind.
*/
protected Set<EAttribute> eAttributes = new LinkedHashSet<EAttribute>();
/**
* A map from a generic type to the possibly null generic type that represents its proper Java type.
*/
protected Map<EGenericType, EGenericType> ecoreEGenericTypeToJavaEGenericTypeMap = new LinkedHashMap<EGenericType, EGenericType>();
/**
* The set of classifiers that were demand created.
*/
protected Set<EClassifier> demandCreatedEClassifiers = new LinkedHashSet<EClassifier>();
/**
* The map from a reference to the name of its opposite.
* These are populated during traversal as each reference with an opposite is created.
* They must be patched after traversal and patching of typed elements is completed.
* The opposite found as a feature of the type.
*/
protected Map<EReference, String> eReferenceToOppositeNameMap = new LinkedHashMap<EReference, String>();
/**
* The set of references that have opposites and have been explicitly marked as being transient.
*/
protected Set<EReference> transientEReferenceWithOpposite = new HashSet<EReference>();
/**
* The map from a reference to the names of its keys.
* These are populated during traversal as each reference with keys is created.
* They must be patched after traversal and patching of typed elements is completed.
* The key is found as an attribute of the type.
*/
protected Map<EReference, List<String>> eReferenceToKeyNamesMap = new LinkedHashMap<EReference, List<String>>();
/**
* All the external GenModels from all required projects.
*/
protected Collection<GenModel> externalGenModels = new UniqueEList<GenModel>();
/**
* All the used GenPackages.
*/
protected Collection<GenPackage> usedGenPackages = new ArrayList<GenPackage>();
/**
* A collection of the problems encountered during the processing.
*/
protected BasicDiagnostic basicDiagnostic;
/**
* Set to true when a compilation unit is processed and hence indicates if anything to process has been found.
*/
protected boolean foundJava;
/**
* The old version to against which to reconcile.
*/
protected GenModel oldGenModelVersion;
/**
* The utility used to convert a generate type to a fully qualified Java instance type.
*/
protected EcoreUtil.EGenericTypeConverter eGenericTypeConverter =
new EcoreUtil.EGenericTypeConverter()
{
@Override
protected String getInstanceTypeName(EClassifier eClassifier)
{
String result = super.getInstanceTypeName(eClassifier);
if (result == null)
{
EPackage ePackage = eClassifier.getEPackage();
for (Map.Entry<String, EPackage> entry : packageNameToEPackageMap.entrySet())
{
if (entry.getValue() == ePackage)
{
return entry.getKey() + '.' + eClassifier.getName();
}
}
for (Map.Entry<String, EPackage> entry : externalPackageNameToEPackageMap.entrySet())
{
if (entry.getValue() == ePackage)
{
return entry.getKey() + '.' + eClassifier.getName();
}
}
}
return result;
}
};
protected static final String MAP_ENTRY_CLASS_CONTAINER_ANNOTATION_SOURCE = EcorePackage.eNS_URI + "#MapEntryClassContainer";
/**
* Creates a builder for the given file.
*/
public JavaEcoreBuilder(IFile genModelFile)
{
this.genModelFile = genModelFile;
basicDiagnostic = new BasicDiagnostic(
JavaImporterPlugin.getPlugin().getBundle().getSymbolicName(),
0,
CodeGenEcorePlugin.INSTANCE.getString("_UI_ErrorsWereDetectedJava_message"),
null);
}
public JavaEcoreBuilder(IFile genModelFile, GenModel oldGenModelVersion)
{
this(genModelFile);
this.oldGenModelVersion = oldGenModelVersion;
}
public JavaEcoreBuilder(IFile genModelFile, GenModel oldGenModelVersion, GenModel genModel)
{
this(genModelFile, oldGenModelVersion);
this.genModel = genModel;
}
protected ResourceSet createResourceSet()
{
ResourceSet result = new ResourceSetImpl();
result.getURIConverter().getURIMap().putAll(EcorePlugin.computePlatformURIMap(true));
return result;
}
protected IPath analyzeProject(IProject project) throws Exception
{
// Walk the project looking for .java files to analyze.
//
IJavaProject javaProject = JavaCore.create(project);
IPackageFragmentRoot[] packageFragmentRoots = javaProject.getPackageFragmentRoots();
Set<IResource> visited = new HashSet<IResource>();
for (int i = 0; i < packageFragmentRoots.length; ++i)
{
if (packageFragmentRoots[i].getKind() == IPackageFragmentRoot.K_SOURCE)
{
traverse((IContainer)packageFragmentRoots[i].getUnderlyingResource(), visited);
}
}
for (Map.Entry<EGenericType, EGenericType> entry : ecoreEGenericTypeToJavaEGenericTypeMap.entrySet())
{
EGenericType ecoreEGenericType = entry.getKey();
EGenericType javaEGenericType = entry.getValue();
EModelElement eModelElement = null;
for (EObject eObject = ecoreEGenericType.eContainer(); eObject != null; eObject = eObject.eContainer())
{
if (eObject instanceof EModelElement)
{
eModelElement = (EModelElement)eObject;
break;
}
}
RequiredClassifierType requiredClassifierType =
ecoreEGenericType.eContainer() instanceof EClass || ecoreEGenericType.eContainer() instanceof EReference ?
RequiredClassifierType.CLASS :
eAttributes.contains(ecoreEGenericType.eContainer()) ?
RequiredClassifierType.DATA_TYPE :
RequiredClassifierType.NONE;
resolve(eModelElement, ecoreEGenericType, requiredClassifierType);
if (javaEGenericType != null)
{
resolve(eModelElement, javaEGenericType, requiredClassifierType);
}
if (javaEGenericType != null)
{
resolve(eModelElement, ecoreEGenericType, javaEGenericType);
}
}
for (Map.Entry<EGenericType, EGenericType> entry : ecoreEGenericTypeToJavaEGenericTypeMap.entrySet())
{
EGenericType ecoreEGenericType = entry.getKey();
EGenericType javaEGenericType = entry.getValue();
EModelElement eModelElement = null;
for (EObject eObject = ecoreEGenericType.eContainer(); eObject != null; eObject = eObject.eContainer())
{
if (eObject instanceof EModelElement)
{
eModelElement = (EModelElement)eObject;
break;
}
}
if (javaEGenericType == null)
{
resolve(eModelElement, ecoreEGenericType, javaEGenericType);
}
used(ecoreEGenericType);
}
for (EStructuralFeature eStructuralFeature : eStructuralFeatures)
{
EGenericType eGenericType = eStructuralFeature.getEGenericType();
EClassifier eClassifier = eGenericType.getERawType();
// If we have resolved to an EClass but we have an EAttribute, we can change it to be an EReference.
//
if (eClassifier instanceof EClass && eStructuralFeature instanceof EAttribute)
{
EAttribute eAttribute = (EAttribute)eStructuralFeature;
EClass container = eAttribute.getEContainingClass();
EReference eReference = EcoreFactory.eINSTANCE.createEReference();
eReference.setChangeable(eAttribute.isChangeable());
eReference.setVolatile(eAttribute.isVolatile());
eReference.setTransient(eAttribute.isTransient());
eReference.setDerived(eAttribute.isDerived());
eReference.setUnsettable(eAttribute.isUnsettable());
eReference.setLowerBound(eAttribute.getLowerBound());
eReference.setUpperBound(eAttribute.getUpperBound());
eReference.setName(eStructuralFeature.getName());
eReference.setEGenericType(eGenericType);
eReference.getEAnnotations().addAll(eStructuralFeature.getEAnnotations());
container.getEStructuralFeatures().add(container.getEStructuralFeatures().indexOf(eStructuralFeature), eReference);
container.getEStructuralFeatures().remove(eStructuralFeature);
eStructuralFeature = eReference;
}
else if (eClassifier instanceof EDataType && eStructuralFeature instanceof EReference)
{
EReference eReference = (EReference)eStructuralFeature;
EClass container = eReference.getEContainingClass();
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setChangeable(eReference.isChangeable());
eAttribute.setVolatile(eReference.isVolatile());
eAttribute.setTransient(eReference.isTransient());
eAttribute.setDerived(eReference.isDerived());
eAttribute.setUnsettable(eReference.isUnsettable());
eAttribute.setLowerBound(eReference.getLowerBound());
eAttribute.setUpperBound(eReference.getUpperBound());
eAttribute.setName(eStructuralFeature.getName());
eAttribute.setEGenericType(eGenericType);
eAttribute.getEAnnotations().addAll(eStructuralFeature.getEAnnotations());
container.getEStructuralFeatures().remove(eStructuralFeature);
eStructuralFeature = eAttribute;
eReferenceToOppositeNameMap.remove(eReference);
}
if (eClassifier.getEPackage() == null)
{
error(CodeGenEcorePlugin.INSTANCE.getString("_UI_TheTypeDoesNotResolveCorrectly_message", new Object []{ eClassifier.getInstanceTypeName() }));
eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(eClassifier instanceof EClass ? EcorePackage.Literals.EOBJECT : EcorePackage.Literals.EJAVA_OBJECT);
}
}
// Now we need to hook up opposites by finding the named feature in the type.
//
for (Map.Entry<EReference, String> entry : eReferenceToOppositeNameMap.entrySet())
{
EReference eReference = entry.getKey();
String oppositeName = entry.getValue();
EClass eClass = (EClass)eReference.getEType();
// TODO handle class cast exception better.
EReference eOpposite = (EReference)eClass.getEStructuralFeature(oppositeName);
if (eOpposite == null)
{
error(CodeGenEcorePlugin.INSTANCE.getString("_UI_TheAttributeIsNotAMemberOf_message", new Object []{ oppositeName, eClass.getName() }));
}
else if (eOpposite.getEOpposite() != eReference && eOpposite.getEOpposite() != null)
{
error
(CodeGenEcorePlugin.INSTANCE.getString
("_UI_TheOppositeAlreadyHasOpposite_message",
new Object []{ oppositeName, eOpposite.getEOpposite().getName(), eOpposite.getEOpposite().getEContainingClass().getName() }));
}
else
{
eReference.setEOpposite(eOpposite);
eOpposite.setEOpposite(eReference);
used(eOpposite);
// Containers are transient by default unless explicitly annotated otherwise.
//
if (eOpposite.isContainment() && !transientEReferenceWithOpposite.contains(eReference))
{
eReference.setTransient(true);
}
}
}
// Now we need to hook up keys by finding the named feature in the type.
//
for (Map.Entry<EReference, List<String>> entry : eReferenceToKeyNamesMap.entrySet())
{
EReference eReference = entry.getKey();
EClass eClass = (EClass)eReference.getEType();
for (String keyName : entry.getValue())
{
EStructuralFeature eKey = eClass.getEStructuralFeature(keyName);
if (eKey == null)
{
error(CodeGenEcorePlugin.INSTANCE.getString("_UI_TheAttributeIsNotAMemberOf_message", new Object []{ keyName, eClass.getName() }));
}
else if (!(eKey instanceof EAttribute))
{
// TODO Ignore for now.
}
else
{
eReference.getEKeys().add((EAttribute)eKey);
used(eKey);
}
}
}
// Clean up the temporary container annotations for holding map entry classes until they are for sure needed.
//
for (EPackage ePackage : packageNameToEPackageMap.values())
{
EAnnotation eAnnotation = ePackage.getEAnnotation(MAP_ENTRY_CLASS_CONTAINER_ANNOTATION_SOURCE);
if (eAnnotation != null)
{
EcoreUtil.remove(eAnnotation);
}
}
// Now we should sort.
//
for (Map.Entry<EPackage, Map<Object, Integer>> entry : ePackageToOrderingMap.entrySet())
{
EPackage ePackage = entry.getKey();
Map<Object, Integer> nameToIDMap = entry.getValue();
sort(ePackage.getEClassifiers(), nameToIDMap);
for (EClassifier eClassifier : ePackage.getEClassifiers())
{
if (eClassifier instanceof EClass)
{
EClass eClass = (EClass)eClassifier;
sort(eClass.getEStructuralFeatures(), nameToIDMap);
}
}
}
// Find the fragment root so that we can generate to the right location (by default).
//
IPath targetFragmentRoot = project.getFullPath();
for (int i = 0; i < packageFragmentRoots.length; ++i)
{
if (packageFragmentRoots[i].getKind() == IPackageFragmentRoot.K_SOURCE)
{
IPath path = packageFragmentRoots[i].getUnderlyingResource().getFullPath();
if (targetFragmentRoot.isPrefixOf(path))
{
targetFragmentRoot = path;
break;
}
}
}
facadeHelper.reset();
return targetFragmentRoot;
}
public void computeEPackages(Monitor monitor, ModelImporter modelImporter) throws Exception
{
IProject project = genModelFile.getProject();
project.open(BasicMonitor.toIProgressMonitor(monitor));
if (!project.hasNature(JavaCore.NATURE_ID) && oldGenModelVersion.getModelDirectory() != null)
{
project = project.getWorkspace().getRoot().getFolder(new Path(oldGenModelVersion.getModelDirectory())).getProject();
}
Collection<IFile> allGenModelFiles = new ArrayList<IFile>();
Collection<IProject> allReferencedProjects = new ArrayList<IProject>();
getAllReferencedProjects(allReferencedProjects, project.getDescription().getReferencedProjects());
getAllReferencedProjects(allReferencedProjects, project.getDescription().getDynamicReferences());
for (IProject referencedProject : allReferencedProjects)
{
getAllGenModelFiles(allGenModelFiles, referencedProject);
}
ResourceSet resourceSet = modelImporter.createResourceSet();
for (IFile file : allGenModelFiles)
{
Resource resource = resourceSet.getResource(modelImporter.createFileURI(file.getFullPath().toString()), true);
GenModel genModel = (GenModel)resource.getContents().get(0);
externalGenModels.add(genModel);
for (GenPackage genPackage : genModel.getGenPackages())
{
determineExternalPackages(genPackage, modelImporter);
}
}
// Iterate over all projects to look at the manifests.
//
List<String> allReferencedPluginIDs = new UniqueEList<String>();
allReferencedProjects.add(project);
for (IProject referencedProject : allReferencedProjects)
{
try
{
// Determine the required plugins.
//
URI manifestURI = URI.createURI(referencedProject.getFullPath() + "/META-INF/MANIFEST.MF");
Manifest manifest = new Manifest(resourceSet.getURIConverter().createInputStream(manifestURI));
String requires = manifest.getMainAttributes().getValue("Require-Bundle");
if (requires != null)
{
ManifestElement[] elements = ManifestElement.parseHeader(Constants.REQUIRE_BUNDLE, requires);
for (int j = 0; j < elements.length; ++j)
{
// Include each required plugin of the starting project and the exported ones of all the required projects.
//
ManifestElement element = elements[j];
if (project == referencedProject || "reexport".equals(element.getDirective("visibility")))
{
String pluginID = element.getValue();
allReferencedPluginIDs.add(pluginID);
}
}
}
}
catch (IOException exception)
{
// Ignore
}
}
// Iterate over all the plugin IDs to determine the dependency closure.
// The list grows as the plugins are visited.
//
for (int i = 0; i < allReferencedPluginIDs.size(); ++i)
{
// Determine the required plugins.
//
String pluginID = allReferencedPluginIDs.get(i);
Bundle bundle = Platform.getBundle(pluginID);
if (bundle != null)
{
String requires = (String)bundle.getHeaders().get(Constants.REQUIRE_BUNDLE);
if (requires != null)
{
ManifestElement[] elements = ManifestElement.parseHeader(Constants.REQUIRE_BUNDLE, requires);
for (int j = 0; j < elements.length; ++j)
{
// Also add each required plugin for consideration in the loop.
//
ManifestElement element = elements[j];
String value = element.getValue();
if ("reexport".equals(element.getDirective("visibility")))
{
allReferencedPluginIDs.add(value);
}
}
}
}
}
// Determine the inverse map from plugin IDs to their registered GenModel locations.
//
Map<String, List<URI>> allPluginsWithGenModels = new HashMap<String, List<URI>>();
for (Map.Entry<String, URI> entry : EcorePlugin.getEPackageNsURIToGenModelLocationMap(true).entrySet())
{
// If it's a platform plugin URI, include it in the map.
//
URI genModelLocation = entry.getValue();
if (genModelLocation.isPlatformResource())
{
List<URI> uris = allPluginsWithGenModels.get(genModelLocation.segment(1));
if (uris == null)
{
uris = new UniqueEList<URI>();
}
uris.add(genModelLocation);
allPluginsWithGenModels.put(genModelLocation.segment(1), uris);
}
}
// Keep only the plugins that have GenModels for consideration.
//
allReferencedPluginIDs.retainAll(allPluginsWithGenModels.keySet());
for (String pluginID : allReferencedPluginIDs)
{
// Consider each GenModel location URI for each required plugin.
//
for (URI uri : allPluginsWithGenModels.get(pluginID))
{
// Load the model and if it's not one already considered, e.g., a local version in the workspace, process its GenPackages.
//
Resource resource = resourceSet.getResource(uri, true);
GenModel genModel = (GenModel)resource.getContents().get(0);
if (externalGenModels.add(genModel))
{
for (GenPackage genPackage : genModel.getGenPackages())
{
determineExternalPackages(genPackage, modelImporter);
}
}
}
}
IPath targetFragmentRoot = analyzeProject(project);
modelImporter.setModelPluginDirectory(targetFragmentRoot.toString());
if (packageNameToEPackageMap.isEmpty())
{
error(JavaImporterPlugin.INSTANCE.getString(foundJava ? "_UI_NoModelElementsInJava_message" : "_UI_NoModelElements_message"));
}
for (EPackage ePackage : packageNameToEPackageMap.values())
{
modelImporter.getEPackages().add(ePackage);
ModelImporter.EPackageImportInfo ePackageInfo = modelImporter.getEPackageImportInfo(ePackage);
ePackageInfo.setPrefix(ePackageToPrefixMap.get(ePackage));
for (Map.Entry<String, EPackage> entry : packageNameToEPackageMap.entrySet())
{
if (entry.getValue() == ePackage)
{
String qualifiedPackageName = entry.getKey();
if (qualifiedPackageName != null)
{
int index = qualifiedPackageName.lastIndexOf(".");
if (index != -1)
{
ePackageInfo.setBasePackage(qualifiedPackageName.substring(0, index));
}
}
break;
}
}
}
}
public void used(EGenericType eGenericType)
{
if (eGenericType != null)
{
EClassifier eClassifier = eGenericType.getEClassifier();
if (eClassifier != null)
{
used(eClassifier);
}
used(eGenericType.getEUpperBound());
used(eGenericType.getELowerBound());
for (EGenericType eTypeArgument : eGenericType.getETypeArguments())
{
used(eTypeArgument);
}
}
}
public void used(EModelElement modelElement)
{
EPackage ePackage = (EPackage)EcoreUtil.getRootContainer(modelElement);
if (ePackage != EcorePackage.eINSTANCE)
{
for (GenModel genModel : externalGenModels)
{
GenPackage genPackage = genModel.findGenPackage(ePackage);
if (genPackage != null)
{
if (!getUsedGenPackages().contains(genPackage) && genPackage.eResource() != null)
{
getUsedGenPackages().add(genPackage);
// Compute the closure.
//
for (Iterator<EObject> j = ePackage.eAllContents(); j.hasNext();)
{
for (Iterator<EObject> k = j.next().eCrossReferences().iterator(); k.hasNext();)
{
EObject o = k.next();
if (o instanceof EModelElement)
{
used((EModelElement)o);
}
}
}
}
break;
}
}
}
}
public void determineExternalPackages(GenPackage genPackage)
{
determineExternalPackages(genPackage, null);
}
protected void determineExternalPackages(GenPackage genPackage, ModelImporter modelImporter)
{
if (modelImporter != null)
{
modelImporter.getReferencedGenPackages().add(genPackage);
}
EPackage ePackage = genPackage.getEcorePackage();
externalPackageNameToEPackageMap.put(genPackage.getInterfacePackageName(), ePackage);
for (GenPackage nestedGenPackage : genPackage.getNestedGenPackages())
{
determineExternalPackages(nestedGenPackage);
}
}
/**
* Walks the projects recursively.
*/
public void getAllReferencedProjects(Collection<IProject> result, IProject[] projects) throws CoreException
{
for (int i = 0; i < projects.length; ++i)
{
IProject project = projects[i];
if (!result.contains(project) && project.exists() && project.isOpen())
{
result.add(project);
getAllReferencedProjects(result, project.getDescription().getReferencedProjects());
getAllReferencedProjects(result, project.getDescription().getDynamicReferences());
}
}
}
/**
* Walks the container recursively.
*/
public void getAllGenModelFiles(Collection<IFile> result, IContainer container) throws CoreException
{
IResource[] contents = container.members();
for (int i = 0; i < contents.length; ++i)
{
IResource resource = contents[i];
if (resource.getType() == IResource.FILE)
{
getAllGenModelFiles(result, (IFile)resource);
}
else
{
getAllGenModelFiles(result, (IContainer)resource);
}
}
}
/**
* Walks the container recursively.
*/
public void getAllGenModelFiles(Collection<IFile> result, IFile file) throws CoreException
{
if (file.getName().endsWith(".genmodel"))
{
IProject project = file.getProject();
IJavaProject javaProject = JavaCore.create(project);
try
{
IPath outputLocation = javaProject.getOutputLocation();
if (project == project.getWorkspace().getRoot().findMember(javaProject.getOutputLocation())
|| !outputLocation.isPrefixOf(file.getFullPath()))
{
result.add(file);
}
}
catch (JavaModelException exception)
{
JavaImporterPlugin.INSTANCE.log(exception);
}
}
}
/**
* Walks the container recursively.
*/
public void traverse(IContainer container, Set<IResource> visited) throws CoreException
{
IResource[] contents = container.members();
for (int i = 0; i < contents.length; ++i)
{
IResource resource = contents[i];
if (visited.add(resource))
{
if (resource.getType() == IResource.FILE)
{
traverse((IFile)resource);
}
else
{
traverse((IContainer)resource, visited);
}
}
}
}
/**
* Analyzes .java files as compilation units.
*/
public void traverse(IFile file) throws CoreException
{
if ("java".equalsIgnoreCase(file.getProjectRelativePath().getFileExtension()))
{
try
{
BufferedInputStream bufferedInputStream = new BufferedInputStream(file.getContents(true));
byte[] input = new byte [bufferedInputStream.available()];
bufferedInputStream.read(input);
bufferedInputStream.close();
String encoding = null;
try
{
encoding = file.getCharset();
}
catch (CoreException ce)
{
// use no encoding
}
String contents = encoding == null ? new String(input) : new String(input, encoding);
JCompilationUnit compilationUnit = facadeHelper.createCompilationUnit("NAME", contents);
analyzeCompilationUnit(compilationUnit);
}
catch (IOException exception)
{
JavaImporterPlugin.INSTANCE.log(exception);
}
}
}
/**
* Walks the compilation unit to analyze the type.
*/
protected void analyzeCompilationUnit(JCompilationUnit compilationUnit)
{
foundJava = true;
for (JAbstractType abstractType : facadeHelper.getChildren(compilationUnit, JAbstractType.class))
{
if (abstractType instanceof JEnum)
{
analyzeEnum((JEnum)abstractType);
}
else if (abstractType instanceof JType)
{
analyzeType((JType)abstractType);
}
break;
}
}
protected void analyzeEnum(JEnum enumeration)
{
String modelAnnotation = getModelAnnotation(enumeration.getComment());
if (modelAnnotation != null)
{
EEnum eEnum = EcoreFactory.eINSTANCE.createEEnum();
eModelElementToJNodeMap.put(eEnum, enumeration);
eEnum.setName(enumeration.getName());
getEPackage(enumeration).getEClassifiers().add(eEnum);
eEnum.getEAnnotations().addAll(extractEAnnotations(modelAnnotation));
EcoreUtil.setDocumentation(eEnum, getModelDocumentation(enumeration.getComment()));
// Walk the fields.
//
boolean hasEnumLiteral = false;
for (JEnumConstant enumConstant : facadeHelper.getChildren(enumeration, JEnumConstant.class))
{
hasEnumLiteral |= analyzeEnumLiteral(eEnum, enumConstant);
}
if (!hasEnumLiteral)
{
for (JField field : facadeHelper.getChildren(enumeration, JField.class))
{
hasEnumLiteral |= analyzeEnumLiteral(eEnum, field);
}
}
}
}
protected EPackage getEPackage(JNode node)
{
JPackage jPackage = facadeHelper.getPackage(node);
String qualifiedPackageName = jPackage != null ?
jPackage.getQualifiedName()
: null;
EPackage ePackage = packageNameToEPackageMap.get(qualifiedPackageName);
if (ePackage == null)
{
// Create the EPackage on demand.
//
ePackage = EcoreFactory.eINSTANCE.createEPackage();
int index = qualifiedPackageName == null ? -1 : qualifiedPackageName.lastIndexOf(".");
String packageName = index == -1 ? qualifiedPackageName : qualifiedPackageName.substring(index + 1);
ePackage.setName(packageName);
ePackage.setNsURI("http:///" + (qualifiedPackageName == null ? "null" : qualifiedPackageName.replace('.', '/')) + ".ecore");
ePackage.setNsPrefix(qualifiedPackageName == null ? "null" : qualifiedPackageName);
packageNameToEPackageMap.put(qualifiedPackageName, ePackage);
if (packageName != null)
{
String prefix = Character.toUpperCase(packageName.charAt(0)) + packageName.substring(1);
ePackageToPrefixMap.put(ePackage, prefix);
}
}
return ePackage;
}
private static final String[] EMPTY_STRING_ARRAY = new String[0];
/**
* Walks the type either as an EClass or an ENum to analyze either the methods or the fields.
*/
protected void analyzeType(JType type)
{
// Check whether this has @model annotation contents.
// If not, it might be a package interface, for backwards compatibility.
//
String modelAnnotation = getModelAnnotation(type.getComment());
boolean isEClassifier = false;
String kind = null;
if (modelAnnotation != null)
{
kind = getModelAnnotationAttribute(modelAnnotation, "kind");
isEClassifier = !"package".equals(kind);
}
if (isEClassifier)
{
// Get the package name and see if there's an EPackage for it.
//
EPackage ePackage = getEPackage(type);
// If it's an interface, then it will be treated as an EClass
//
if ((type.getFlags() & Flags.AccInterface) != 0 || "class".equals(kind))
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eModelElementToJNodeMap.put(eClass, type);
eClass.setName(type.getName());
ePackage.getEClassifiers().add(eClass);
eClass.getEAnnotations().addAll(extractEAnnotations(modelAnnotation));
EcoreUtil.setDocumentation(eClass, getModelDocumentation(type.getComment()));
analyzeTypeParameters(eClass.getETypeParameters(), type.getTypeParameters(), modelAnnotation);
String[] superInterfaces = type.getSuperInterfaces();
String extend = getExtendsAnnotation(type.getComment());
if (extend != null)
{
List<String> superInterfaceList = new ArrayList<String>(Arrays.asList(superInterfaces));
Diagnostic diagnostic = EcoreValidator.EGenericTypeBuilder.INSTANCE.parseTypeArgumentList(extend);
if (diagnostic.getSeverity() == Diagnostic.OK)
{
@SuppressWarnings("unchecked")
List<EGenericType> eTypeArguments = (List<EGenericType>)diagnostic.getData().get(0);
for (EGenericType eGenericType : eTypeArguments)
{
superInterfaceList.remove(EcoreUtil.toJavaInstanceTypeName(eGenericType));
}
}
superInterfaces = new String [superInterfaceList.size()];
superInterfaceList.toArray(superInterfaces);
}
// Create a generic super type with an EClass as the classifier for each super interface in the Java representation.
//
List<EGenericType> javaEGenericSuperTypes = new ArrayList<EGenericType>();
for (String superType : superInterfaces)
{
Diagnostic diagnostic = EcoreValidator.EGenericTypeBuilder.INSTANCE.parseInstanceTypeName(superType);
if (diagnostic.getSeverity() == Diagnostic.OK)
{
EGenericType eGenericSuperType = (EGenericType)diagnostic.getData().get(0);
EClass eSuperClass = EcoreFactory.eINSTANCE.createEClass();
eSuperClass.setAbstract(true);
eSuperClass.setInterface(true);
eSuperClass.setInstanceTypeName(eGenericSuperType.getEClassifier().getInstanceTypeName());
eGenericSuperType.setEClassifier(eSuperClass);
javaEGenericSuperTypes.add(eGenericSuperType);
}
}
// Create a generic super type with an EClass as the classifier for each super interface in the @model representation
//
List<EGenericType> ecoreEGenericSuperTypes = null;
String superTypes = getModelAnnotationAttribute(modelAnnotation, "superTypes");
if (superTypes != null)
{
ecoreEGenericSuperTypes = new ArrayList<EGenericType>();
for (EGenericType ecoreEGenericSuperType : analyzeEGenericTypes(superTypes))
{
EClass eSuperClass = EcoreFactory.eINSTANCE.createEClass();
eSuperClass.setAbstract(true);
eSuperClass.setInterface(true);
eSuperClass.setInstanceTypeName(ecoreEGenericSuperType.getEClassifier().getInstanceTypeName());
ecoreEGenericSuperType.setEClassifier(eSuperClass);
ecoreEGenericSuperTypes.add(ecoreEGenericSuperType);
}
}
// Filter out explicit EObject from super types, except in the Ecore package itself, or if it appears in the @model superTypes.
//
if (!javaEGenericSuperTypes.isEmpty() &&
javaEGenericSuperTypes.get(0).getERawType().getInstanceTypeName().endsWith("EObject") &&
(ecoreEGenericSuperTypes == null ||
!ecoreEGenericSuperTypes.isEmpty() && !ecoreEGenericSuperTypes.get(0).getERawType().getInstanceTypeName().endsWith("EObject")) &&
!EcorePackage.eNS_URI.equals(ePackage.getNsURI()))
{
EGenericType superType = resolve(eClass, javaEGenericSuperTypes.get(0).getERawType().getInstanceTypeName(), RequiredClassifierType.CLASS, false);
EClassifier superClass = superType.getEClassifier();
if (superClass.getEPackage() != null &&
EcorePackage.eNS_URI.equals(superClass.getEPackage().getNsURI()) &&
"EObject".equals(superClass.getName()))
{
javaEGenericSuperTypes.remove(0);
}
}
// Match them and accumulate the appropriate result.
//
match(eClass.getEGenericSuperTypes(), javaEGenericSuperTypes, ecoreEGenericSuperTypes);
String isInterface = getModelAnnotationAttribute(modelAnnotation, "interface");
eClass.setInterface("true".equals(isInterface));
String isAbstract = getModelAnnotationAttribute(modelAnnotation, "abstract");
eClass.setAbstract("true".equals(isAbstract) || isAbstract == null && eClass.isInterface());
// Walk the methods.
//
for (JMethod method : facadeHelper.getChildren(type, JMethod.class))
{
analyzeMethod(eClass, method);
}
// Additional attributes and references may be defined directly on the interface in order to allow the
// get accessor method to have suppressed visibility.
//
String features = getModelAnnotationAttribute(modelAnnotation, "features");
if (features != null)
{
for (StringTokenizer stringTokenizer = new StringTokenizer(features, " "); stringTokenizer.hasMoreTokens();)
{
String feature = stringTokenizer.nextToken();
if (eClass.getEStructuralFeature(feature) == null)
{
analyzeMethod
(eClass,
getFilteredModelAnnotations(modelAnnotation, feature),
"get" + Character.toUpperCase(feature.charAt(0)) + feature.substring(1),
"java.lang.Object",
EMPTY_STRING_ARRAY,
EMPTY_STRING_ARRAY,
EMPTY_STRING_ARRAY,
EMPTY_STRING_ARRAY);
}
else
{
warning(CodeGenEcorePlugin.INSTANCE.getString("_UI_DuplicateFeature_message", new Object []{ feature, eClass.getName() }));
}
}
}
}
// Otherwise it's treated as an EEnum
//
else
{
EEnum eEnum = EcoreFactory.eINSTANCE.createEEnum();
eModelElementToJNodeMap.put(eEnum, type);
eEnum.setName(type.getName());
ePackage.getEClassifiers().add(eEnum);
eEnum.getEAnnotations().addAll(extractEAnnotations(modelAnnotation));
EcoreUtil.setDocumentation(eEnum, getModelDocumentation(type.getComment()));
// Walk the fields.
//
for (JField field : facadeHelper.getChildren(type, JField.class))
{
analyzeEnumLiteral(eEnum, field);
}
}
}
// Find Packages and Factories
else
{
JPackage jPackage = facadeHelper.getPackage(type);
String qualifiedPackageName = jPackage != null ? jPackage.getQualifiedName() : null;
String typeName = type.getName();
boolean isEPackage = false;
if (typeName.endsWith("Package") && typeName.length() > 7)
{
String packagePrefix = typeName.substring(0, typeName.length() - 7);
// It's definitely a package if it was declared as such.
//
if ("package".equals(kind))
{
isEPackage = true;
}
int index = qualifiedPackageName == null ? -1 : qualifiedPackageName.lastIndexOf(".");
String name = index == -1 ? qualifiedPackageName : qualifiedPackageName.substring(index + 1);
String nsURI = "http:///" + (qualifiedPackageName == null ? "null" : qualifiedPackageName.replace('.', '/')) + ".ecore";
String nsPrefix = qualifiedPackageName == null ? "null" : qualifiedPackageName;
List<EClass> eClasses = new ArrayList<EClass>();
List<EDataType> eDataTypes = new ArrayList<EDataType>();
Map<Object, Integer> ordering = new HashMap<Object, Integer>();
// It's definitely a package if expected constants eNAME, eNS_PREFIX, or eNS_URI appear.
//
for (JNode node : type.getChildren())
{
if (node instanceof JField)
{
JField field = (JField)node;
String fieldName = field.getName();
String fieldType = field.getType();
if ("eNAME".equals(fieldName))
{
isEPackage = true;
name = field.getInitializer();
name = name.substring(1, name.length() - 1);
}
else if ("eNS_URI".equals(fieldName))
{
isEPackage = true;
nsURI = field.getInitializer();
nsURI = nsURI.substring(1, nsURI.length() - 1);
}
else if ("eNS_PREFIX".equals(fieldName))
{
isEPackage = true;
nsPrefix = field.getInitializer();
nsPrefix = nsPrefix.substring(1, nsPrefix.length() - 1);
}
else if ("int".equals(fieldType) && !fieldName.endsWith("FEATURE_COUNT"))
{
try
{
String initializer = field.getInitializer();
int plusIndex = initializer.lastIndexOf("+");
if (plusIndex != -1)
{
initializer = initializer.substring(plusIndex + 1);
}
initializer = initializer.trim();
int value = Integer.parseInt(initializer);
ordering.put(fieldName, value);
}
catch (NumberFormatException exception)
{
// This will catch inherited features, or additional things we don't want to worry about.
}
}
}
else if (node instanceof JMethod)
{
JMethod method = (JMethod)node;
String methodAnnotation = getModelAnnotation(method.getComment());
if (methodAnnotation != null)
{
String returnType = method.getReturnType();
if (returnType != null)
{
if (returnType.endsWith("EDataType"))
{
EDataType eDataType = EcoreFactory.eINSTANCE.createEDataType();
eDataType.setInstanceTypeName(getModelAnnotationAttribute(methodAnnotation, "instanceClass"));
eDataType.setName(method.getName().substring(3));
String isSerializable = getModelAnnotationAttribute(methodAnnotation, "serializable");
if ("false".equals(isSerializable))
{
eDataType.setSerializable(false);
}
String typeParameterNames = getModelAnnotationAttribute(methodAnnotation, "typeParameters");
if (typeParameterNames != null)
{
for (StringTokenizer stringTokenizer = new StringTokenizer(typeParameterNames, " "); stringTokenizer.hasMoreTokens();)
{
String typeParameterName = stringTokenizer.nextToken();
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName(typeParameterName);
String typeParameterModelAnnotation = getFilteredModelAnnotations(methodAnnotation, typeParameterName);
String bounds = getModelAnnotationAttribute(typeParameterModelAnnotation, "bounds");
if (bounds != null)
{
eTypeParameter.getEBounds().addAll(analyzeEGenericTypes(bounds));
for (EGenericType eBound : eTypeParameter.getEBounds())
{
ecoreEGenericTypeToJavaEGenericTypeMap.put(eBound, null);
}
}
eDataType.getETypeParameters().add(eTypeParameter);
}
}
eDataTypes.add(eDataType);
eDataType.getEAnnotations().addAll(extractEAnnotations(methodAnnotation));
EcoreUtil.setDocumentation(eDataType, getModelDocumentation(method.getComment()));
}
else if (returnType.endsWith("EClass"))
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
String instanceClass = getModelAnnotationAttribute(methodAnnotation, "instanceClass");
if (instanceClass != null)
{
eClass.setInterface(true);
eClass.setAbstract(true);
eClass.setInstanceTypeName(instanceClass);
eClass.setName(method.getName().substring(3));
String typeParameterNames = getModelAnnotationAttribute(methodAnnotation, "typeParameters");
if (typeParameterNames != null)
{
for (StringTokenizer stringTokenizer = new StringTokenizer(typeParameterNames, " "); stringTokenizer.hasMoreTokens();)
{
String typeParameterName = stringTokenizer.nextToken();
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName(typeParameterName);
String typeParameterModelAnnotation = getFilteredModelAnnotations(methodAnnotation, typeParameterName);
String bounds = getModelAnnotationAttribute(typeParameterModelAnnotation, "bounds");
if (bounds != null)
{
eTypeParameter.getEBounds().addAll(analyzeEGenericTypes(bounds));
for (EGenericType eBound : eTypeParameter.getEBounds())
{
ecoreEGenericTypeToJavaEGenericTypeMap.put(eBound, null);
}
}
eClass.getETypeParameters().add(eTypeParameter);
}
}
eClasses.add(eClass);
}
else
{
eClass.setInstanceTypeName("java.util.Map$Entry");
eClass.setName(method.getName().substring(3));
eClasses.add(eClass);
String features = getModelAnnotationAttribute(methodAnnotation, "features");
if (features != null)
{
for (StringTokenizer stringTokenizer = new StringTokenizer(features, " "); stringTokenizer.hasMoreTokens();)
{
String feature = stringTokenizer.nextToken();
analyzeMethod
(eClass,
getFilteredModelAnnotations(methodAnnotation, feature),
"get" + Character.toUpperCase(feature.charAt(0)) + feature.substring(1),
"java.lang.Object",
EMPTY_STRING_ARRAY,
EMPTY_STRING_ARRAY,
EMPTY_STRING_ARRAY,
EMPTY_STRING_ARRAY);
}
}
else
{
analyzeMethod
(eClass,
getFilteredModelAnnotations(methodAnnotation, "key"),
"getKey",
"java.lang.Object",
EMPTY_STRING_ARRAY,
EMPTY_STRING_ARRAY,
EMPTY_STRING_ARRAY,
EMPTY_STRING_ARRAY);
analyzeMethod
(eClass,
getFilteredModelAnnotations(methodAnnotation, "value"),
"getValue",
"java.lang.Object",
EMPTY_STRING_ARRAY,
EMPTY_STRING_ARRAY,
EMPTY_STRING_ARRAY,
EMPTY_STRING_ARRAY);
}
}
eClass.getEAnnotations().addAll(extractEAnnotations(methodAnnotation));
EcoreUtil.setDocumentation(eClass, getModelDocumentation(method.getComment()));
}
}
}
}
}
if (isEPackage || !eClasses.isEmpty() || !eDataTypes.isEmpty())
{
EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
ePackageToOrderingMap.put(ePackage, ordering);
eModelElementToJNodeMap.put(ePackage, type);
ePackage.setNsURI(nsURI);
ePackage.setNsPrefix(nsPrefix);
ePackage.setName(name);
ePackage.getEClassifiers().addAll(eClasses);
ePackage.getEClassifiers().addAll(eDataTypes);
if (modelAnnotation != null)
{
ePackage.getEAnnotations().addAll(extractEAnnotations(modelAnnotation));
}
EcoreUtil.setDocumentation(ePackage, getModelDocumentation(type.getComment()));
ePackageToPrefixMap.put(ePackage, packagePrefix);
EPackage existingEPackage = packageNameToEPackageMap.get(qualifiedPackageName);
if (existingEPackage != null)
{
ePackage.getEClassifiers().addAll(existingEPackage.getEClassifiers());
ePackage.getEAnnotations().addAll(existingEPackage.getEAnnotations());
}
packageNameToEPackageMap.put(qualifiedPackageName, ePackage);
}
}
}
}
/**
* Creates an EOperation, EAttribute, or EReference as appropriate.
*/
protected void analyzeMethod(EClass eClass, JMethod method)
{
// Check whether this has @model annotation contents.
//
String modelAnnotation = getModelAnnotation(method.getComment());
if (modelAnnotation != null && method.getName() != null)
{
String methodName = method.getName();
String returnType = method.getReturnType();
String[] parameterNames = method.getParameterNames();
String[] parameterTypes = method.getFullParameterTypes();
String[] exceptionTypes = method.getExceptions();
String[] typeParameters = method.getTypeParameters();
ETypedElement eTypedElement = analyzeMethod(eClass, modelAnnotation, methodName, returnType, parameterNames, parameterTypes, exceptionTypes, typeParameters);
if (eTypedElement != null)
{
EcoreUtil.setDocumentation(eTypedElement, getModelDocumentation(method.getComment()));
}
eModelElementToJNodeMap.put(eTypedElement, method);
if (eTypedElement instanceof EOperation)
{
EOperation eOperation = (EOperation)eTypedElement;
for (EParameter eParameter : eOperation.getEParameters())
{
eModelElementToJNodeMap.put(eParameter, method);
}
}
}
}
protected ETypedElement analyzeMethod(
EClass eClass,
String modelAnnotation,
String methodName,
String returnType,
String[] parameterNames,
String[] parameterTypes,
String[] exceptionTypes,
String[] typeParameters)
{
// We will create an EAttribute, EReference, or an EOperation.
//
ETypedElement eTypedElement = null;
String featureName = methodName;
String parameters = getModelAnnotationAttribute(modelAnnotation, "parameters");
String kind = getModelAnnotationAttribute(modelAnnotation, "kind");
// An operation is declared via the kind property or, for backwards compatibility, by specifying parameters
// (though attribute or reference kind takes precedence).
//
boolean declaredEOperation =
"operation".equals(kind) ||
(parameters != null && !"attribute".equals(kind) && !"reference".equals(kind));
// Check whether there are parameters; the special attribute and reference rules only apply for the case of no arguments.
//
if (parameterNames.length == 0 &&
!declaredEOperation &&
methodName.startsWith("get") &&
methodName.length() > 3 &&
Character.isUpperCase(methodName.charAt(3)) &&
!"boolean".equals(returnType) &&
!"void".equals(returnType))
{
// The feature name is extracted lower cased.
//
featureName = CodeGenUtil.uncapName(methodName.substring(3));
}
else if (parameterNames.length == 0 &&
!declaredEOperation &&
methodName.startsWith("is") &&
methodName.length() > 2 &&
Character.isUpperCase(methodName.charAt(2)) &&
"boolean".equals(returnType))
{
// The name is extracted and lower cased.
//
featureName = CodeGenUtil.uncapName(methodName.substring(2));
}
else
{
// The method is not a structural feature, so it's modeled as an operation.
//
EOperation eOperation = EcoreFactory.eINSTANCE.createEOperation();
eTypedElement = eOperation;
eClass.getEOperations().add(eOperation);
analyzeTypeParameters(eOperation.getETypeParameters(), typeParameters, modelAnnotation);
handleETypedElement(eOperation, methodName, returnType, modelAnnotation, eClass.getName() + "." + methodName);
if (parameterTypes.length > 0)
{
// Each token in parameters will specify a dataType for the corresponding parameter, but can be overridden by a
// parameter-name-prefixed dataType property.
//
StringTokenizer stringTokenizer = new StringTokenizer(parameters == null ? "" : parameters);
for (int i = 0; i < parameterNames.length; ++i)
{
EParameter eParameter = EcoreFactory.eINSTANCE.createEParameter();
eOperation.getEParameters().add(eParameter);
String parameterName = parameterNames[i];
String parameterType = parameterTypes[i];
String parameterModelAnnotation = getFilteredModelAnnotations(modelAnnotation, parameterName);
if (stringTokenizer.hasMoreTokens())
{
String dataType = stringTokenizer.nextToken();
if (!"-".equals(dataType))
{
StringBuilder sb = new StringBuilder(parameterModelAnnotation);
sb.append("dataType=\"");
sb.append(dataType);
sb.append("\" ");
parameterModelAnnotation = sb.toString();
}
}
StringBuilder identifierName = new StringBuilder(eClass.getName());
identifierName.append('.');
identifierName.append(methodName);
identifierName.append('(');
identifierName.append(parameterName);
identifierName.append(')');
handleETypedElement(eParameter, parameterName, parameterType, parameterModelAnnotation, identifierName.toString());
eParameter.getEAnnotations().addAll(extractEAnnotations(parameterModelAnnotation));
}
}
if (exceptionTypes.length > 0)
{
// Each token in exceptions will specify a data type for the corresponding exception.
//
List<EGenericType> ecoreEGenericExceptions = new ArrayList<EGenericType>();
String exceptions = getModelAnnotationAttribute(modelAnnotation, "exceptions");
if (exceptions != null)
{
ecoreEGenericExceptions.addAll(analyzeEGenericTypes(exceptions));
}
List<EGenericType> javaEGenericExceptions = new ArrayList<EGenericType>();
for (String exception : exceptionTypes)
{
Diagnostic diagnostic = EcoreValidator.EGenericTypeBuilder.INSTANCE.parseInstanceTypeName(exception);
if (diagnostic.getSeverity() == Diagnostic.OK)
{
javaEGenericExceptions.add((EGenericType)diagnostic.getData().get(0));
}
}
match(eOperation.getEGenericExceptions(), javaEGenericExceptions, ecoreEGenericExceptions);
}
}
// If we aren't doing an operation...
//
if (eTypedElement == null)
{
// We'll create one of these.
//
EStructuralFeature eStructuralFeature = null;
// If any of these attributes appear, this must be a reference.
//
String opposite = getModelAnnotationAttribute(modelAnnotation, "opposite");
String keys = getModelAnnotationAttribute(modelAnnotation, "keys");
String containment = getModelAnnotationAttribute(modelAnnotation, "containment");
String resolveProxies = getModelAnnotationAttribute(modelAnnotation, "resolveProxies");
String mapType = getModelAnnotationAttribute(modelAnnotation, "mapType");
String keyType = getModelAnnotationAttribute(modelAnnotation, "keyType");
String valueType = getModelAnnotationAttribute(modelAnnotation, "valueType");
if ("reference".equals(kind) ||
opposite != null ||
keys != null ||
containment != null ||
resolveProxies != null ||
mapType != null ||
keyType != null && valueType != null)
{
EReference eReference = EcoreFactory.eINSTANCE.createEReference();
eTypedElement = eStructuralFeature = eReference;
eClass.getEStructuralFeatures().add(eReference);
// Set the EReference attributes.
//
eReference.setContainment
("true".equals(containment) ||
mapType != null && !stripTypeArguments(returnType).endsWith("Entry") ||
keyType != null && valueType != null);
eReference.setResolveProxies(eReference.isContainment() ? "true".equals(resolveProxies) : !"false".equals(resolveProxies));
eReference.setUnsettable("true".equals(getModelAnnotationAttribute(modelAnnotation, "unsettable")));
// Defer the handling of the opposite.
//
if (opposite != null)
{
eReferenceToOppositeNameMap.put(eReference, opposite);
if ("false".equals(getModelAnnotationAttribute(modelAnnotation, "transient")))
{
transientEReferenceWithOpposite.add(eReference);
}
}
if (keys != null)
{
List<String> keyNames = new ArrayList<String>();
for (StringTokenizer stringTokenizer = new StringTokenizer(keys, " ,\t\n\r\f"); stringTokenizer.hasMoreTokens();)
{
keyNames.add(stringTokenizer.nextToken());
}
eReferenceToKeyNamesMap.put(eReference, keyNames);
}
}
else
{
// Assume that it's an attribute for now.
// It will/could become a reference if the type resolves to an EClass.
//
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
if ("attribute".equals(kind))
{
eAttributes.add(eAttribute);
}
eTypedElement = eStructuralFeature = eAttribute;
eClass.getEStructuralFeatures().add(eAttribute);
// Set the EAttribute attributes.
//
eAttribute.setUnsettable("true".equals(getModelAnnotationAttribute(modelAnnotation, "unsettable")));
eAttribute.setID("true".equals(getModelAnnotationAttribute(modelAnnotation, "id")));
String defaultValueLiteral = getModelAnnotationAttribute(modelAnnotation, "defaultValue");
if (defaultValueLiteral == null)
{
defaultValueLiteral = getModelAnnotationAttribute(modelAnnotation, "default");
}
eStructuralFeature.setDefaultValueLiteral(defaultValueLiteral);
}
// Handle the type, multiplicity and other ETypedElement attributes.
//
handleETypedElement(eStructuralFeature, featureName, returnType, modelAnnotation, eClass.getName() + "." + methodName);
// Set the EStructuralFeature attributes.
//
eStructuralFeature.setChangeable(!"false".equals(getModelAnnotationAttribute(modelAnnotation, "changeable")));
eStructuralFeature.setDerived("true".equals(getModelAnnotationAttribute(modelAnnotation, "derived")));
eStructuralFeature.setVolatile("true".equals(getModelAnnotationAttribute(modelAnnotation, "volatile")));
eStructuralFeature.setTransient("true".equals(getModelAnnotationAttribute(modelAnnotation, "transient")));
// Set the visibility annotations for the EstructuralFeature.
//
EcoreUtil.setSuppressedVisibility
(eStructuralFeature, EcoreUtil.GET, "true".equals(getModelAnnotationAttribute(modelAnnotation, "suppressedGetVisibility")));
EcoreUtil.setSuppressedVisibility
(eStructuralFeature, EcoreUtil.SET, "true".equals(getModelAnnotationAttribute(modelAnnotation, "suppressedSetVisibility")));
EcoreUtil.setSuppressedVisibility
(eStructuralFeature, EcoreUtil.IS_SET, "true".equals(getModelAnnotationAttribute(modelAnnotation, "suppressedIsSetVisibility")));
EcoreUtil.setSuppressedVisibility
(eStructuralFeature, EcoreUtil.UNSET, "true".equals(getModelAnnotationAttribute(modelAnnotation, "suppressedUnsetVisibility")));
}
if (eTypedElement != null)
{
// Process the annotations.
//
eTypedElement.getEAnnotations().addAll(extractEAnnotations(modelAnnotation));
if (eTypedElement instanceof EStructuralFeature)
{
eStructuralFeatures.add((EStructuralFeature)eTypedElement);
}
}
return eTypedElement;
}
protected List<EGenericType> analyzeEGenericTypes(String genericTypes)
{
List<EGenericType> result = new ArrayList<EGenericType>();
int depth = 0;
int start = -1;
int length = genericTypes.length();
for (int i = 0; i < length; i = Character.offsetByCodePoints(genericTypes, i, 1))
{
int codePoint = genericTypes.codePointAt(i);
if (codePoint == '<')
{
++depth;
}
else if (codePoint == '>')
{
--depth;
}
else if (Character.isWhitespace(codePoint))
{
if (depth == 0 && start != -1)
{
EGenericType eGenericType = EcoreValidator.EGenericTypeBuilder.INSTANCE.buildEGenericType(genericTypes.substring(start, i));
result.add(eGenericType);
start = -1;
}
}
else if (start == -1)
{
start = i;
}
}
if (start != -1)
{
EGenericType eGenericType = EcoreValidator.EGenericTypeBuilder.INSTANCE.buildEGenericType(genericTypes.substring(start));
result.add(eGenericType);
}
return result;
}
void analyzeTypeParameters(List<ETypeParameter> eTypeParameters, String[] typeParameters, String modelAnnotation)
{
if (typeParameters.length > 0)
{
for (String typeParameter : typeParameters)
{
Diagnostic diagnostic = EcoreValidator.EGenericTypeBuilder.INSTANCE.parseTypeParameter(typeParameter);
if (diagnostic.getSeverity() == Diagnostic.OK)
{
ETypeParameter eTypeParameter = (ETypeParameter)diagnostic.getData().get(0);
List<EGenericType> javaEBounds = new ArrayList<EGenericType>(eTypeParameter.getEBounds());
eTypeParameter.getEBounds().clear();
List<EGenericType> ecoreEBounds = null;
String bounds = getModelAnnotationAttribute(getFilteredModelAnnotations(modelAnnotation, eTypeParameter.getName()), "bounds");
if (bounds != null)
{
ecoreEBounds = analyzeEGenericTypes(bounds);
}
match(eTypeParameter.getEBounds(), javaEBounds, ecoreEBounds);
eTypeParameters.add(eTypeParameter);
}
}
}
}
protected boolean isListType(String type)
{
type = stripTypeArguments(type);
return "EList".equals(type) || "org.eclipse.emf.common.util.EList".equals(type) || "List".equals(type) || "java.util.List".equals(type);
}
protected boolean isMapType(String type)
{
type = stripTypeArguments(type);
return "EMap".equals(type) || "org.eclipse.emf.common.util.EMap".equals(type) || "Map".equals(type) || "java.util.Map".equals(type);
}
protected void handleETypedElement(ETypedElement eTypedElement, String name, String type, String modelAnnotation, String identifierName)
{
eTypedElement.setName(name);
if ("void".equals(type)) return;
String mapType = getModelAnnotationAttribute(modelAnnotation, "mapType");
String dataType = getModelAnnotationAttribute(modelAnnotation, "dataType");
String modelType = getModelAnnotationAttribute(modelAnnotation, "type");
String keyType = getModelAnnotationAttribute(modelAnnotation, "keyType");
String valueType = getModelAnnotationAttribute(modelAnnotation, "valueType");
String many = getModelAnnotationAttribute(modelAnnotation, "many");
// For lists, maps, and feature maps, the default is many-valued, which can be overridden by an upper-bound declaration.
//
if (isListType(type) && (dataType == null || modelType != null && !isListType(modelType)))
{
eTypedElement.setUpperBound(-1);
Diagnostic diagnostic = EcoreValidator.EGenericTypeBuilder.INSTANCE.parseInstanceTypeName(type);
if (diagnostic.getSeverity() == Diagnostic.OK)
{
EGenericType eGenericType = (EGenericType)diagnostic.getData().get(0);
if (eGenericType.getETypeArguments().size() == 1)
{
EGenericType typeArgument = eGenericType.getETypeArguments().get(0);
if (typeArgument.getEClassifier() != null || typeArgument.getETypeParameter() != null)
{
type = eGenericTypeConverter.toJavaInstanceTypeName(typeArgument);
if (modelType == null)
{
modelType = type;
}
}
else
{
eTypedElement.setUpperBound(1);
}
}
}
if (modelType == null && !"false".equals(many) && eTypedElement.getUpperBound() != 1)
{
error(CodeGenEcorePlugin.INSTANCE.getString("_UI_TheTypeMustBeSpecifiedFor_message", new Object [] { identifierName }));
modelType = "java.lang.Object";
}
}
else if (mapType != null ||
keyType != null && valueType != null ||
"FeatureMap".equals(type) ||
"org.eclipse.emf.common.util.FeatureMap".equals(type))
{
eTypedElement.setUpperBound(-1);
}
if (many != null)
{
eTypedElement.setUpperBound("true".equals(many) ? -1 : 1);
}
eTypedElement.setLowerBound("true".equals(getModelAnnotationAttribute(modelAnnotation, "required")) ? 1 : 0);
String lowerBound = getModelAnnotationAttribute(modelAnnotation, "lowerBound");
if (lowerBound == null)
{
lowerBound = getModelAnnotationAttribute(modelAnnotation, "lower");
}
if (lowerBound != null)
{
try
{
eTypedElement.setLowerBound(Integer.parseInt(lowerBound));
}
catch (NumberFormatException exception)
{
warning(JavaImporterPlugin.INSTANCE.getString("_UI_ValueOfPropertyIsBad_message", new Object [] { lowerBound, "lower", identifierName }));
}
}
String upperBound = getModelAnnotationAttribute(modelAnnotation, "upperBound");
if (upperBound == null)
{
upperBound = getModelAnnotationAttribute(modelAnnotation, "upper");
}
if (upperBound != null)
{
try
{
eTypedElement.setUpperBound(Integer.parseInt(upperBound));
}
catch (NumberFormatException exception)
{
warning(JavaImporterPlugin.INSTANCE.getString("_UI_ValueOfPropertyIsBad_message", new Object [] { upperBound, "upper", identifierName }));
}
}
EGenericType ecoreEGenericType = null;
EGenericType javaEGenericType = null;
// The type can be augmented by specifying the it explicitly in the annotation.
// This mostly makes sense only for many-valued typed elements, where the Java
// type is a list and the item type needs to be specified.
//
if (modelType != null)
{
Diagnostic diagnostic = EcoreValidator.EGenericTypeBuilder.INSTANCE.parseInstanceTypeName(modelType);
if (diagnostic.getSeverity() == Diagnostic.OK)
{
javaEGenericType = (EGenericType)diagnostic.getData().get(0);
}
type = modelType;
}
if (mapType != null || keyType != null && valueType != null)
{
EPackage ePackage = (EPackage)EcoreUtil.getRootContainer(eTypedElement);
EGenericType ecoreKeyEGenericType = null;
EGenericType javaKeyEGenericType = null;
EGenericType ecoreValueEGenericType = null;
EGenericType javaValueEGenericType = null;
if (mapType != null)
{
Diagnostic diagnostic = EcoreValidator.EGenericTypeBuilder.INSTANCE.parseInstanceTypeName(mapType);
if (diagnostic.getSeverity() == Diagnostic.OK)
{
ecoreEGenericType = (EGenericType)diagnostic.getData().get(0);
resolve(eTypedElement, ecoreEGenericType, RequiredClassifierType.CLASS);
List<EGenericType> mapETypeArguments = ecoreEGenericType.getETypeArguments();
if (mapETypeArguments.size() == 2)
{
ecoreKeyEGenericType = mapETypeArguments.get(0);
ecoreValueEGenericType = mapETypeArguments.get(1);
}
mapETypeArguments.clear();
}
else
{
ecoreEGenericType = resolve(eTypedElement, mapType, RequiredClassifierType.CLASS, false);
}
if (ecoreEGenericType.getERawType().getEPackage() == null)
{
if (keyType == null || valueType == null && isMapType(type))
{
diagnostic = EcoreValidator.EGenericTypeBuilder.INSTANCE.parseInstanceTypeName(type);
if (diagnostic.getSeverity() == Diagnostic.OK)
{
EGenericType eGenericType = (EGenericType)diagnostic.getData().get(0);
if (eGenericType.getETypeArguments().size() == 2)
{
javaKeyEGenericType = eGenericType.getETypeArguments().get(0);
javaValueEGenericType = eGenericType.getETypeArguments().get(1);
}
}
}
if (javaKeyEGenericType == null)
{
javaKeyEGenericType = resolve(eTypedElement, keyType == null ? "java.lang.Object" : keyType, RequiredClassifierType.NONE, false);
}
if (javaValueEGenericType == null)
{
javaValueEGenericType = resolve(eTypedElement, valueType == null ? "java.lang.Object" : valueType, RequiredClassifierType.NONE, false);
}
}
}
else
{
javaKeyEGenericType = resolve(eTypedElement, keyType, RequiredClassifierType.NONE, false);
javaValueEGenericType = resolve(eTypedElement, valueType, RequiredClassifierType.NONE, false);
ecoreEGenericType = resolveMapEntry(ePackage, javaKeyEGenericType, javaValueEGenericType);
if (ecoreEGenericType == null)
{
ecoreEGenericType =
resolve
(eTypedElement,
javaKeyEGenericType.getERawType().getName() + "To" + javaValueEGenericType.getERawType().getName() + "MapEntry",
RequiredClassifierType.CLASS,
false);
}
}
EClass mapEClass = (EClass)ecoreEGenericType.getEClassifier();
if (mapEClass.getEPackage() == null && mapEClass.getEStructuralFeatures().isEmpty())
{
eModelElementToJNodeMap.put(mapEClass, getJCompilationUnit(eTypedElement));
mapEClass.setInstanceTypeName("java.util.Map$Entry");
mapEClass.setAbstract(false);
mapEClass.setInterface(false);
if (ecoreKeyEGenericType == null)
{
createFeature(mapEClass, "key", javaKeyEGenericType);
ecoreEGenericTypeToJavaEGenericTypeMap.put(javaKeyEGenericType, null);
}
else
{
createFeature(mapEClass, "key", ecoreKeyEGenericType);
ecoreEGenericTypeToJavaEGenericTypeMap.put(ecoreKeyEGenericType, javaKeyEGenericType);
}
if (ecoreValueEGenericType == null)
{
createFeature(mapEClass, "value", javaValueEGenericType);
ecoreEGenericTypeToJavaEGenericTypeMap.put(javaValueEGenericType, null);
}
else
{
createFeature(mapEClass, "value", ecoreValueEGenericType);
ecoreEGenericTypeToJavaEGenericTypeMap.put(ecoreValueEGenericType, javaValueEGenericType);
}
EAnnotation container = ePackage.getEAnnotation(MAP_ENTRY_CLASS_CONTAINER_ANNOTATION_SOURCE);
if (container == null)
{
container = EcoreFactory.eINSTANCE.createEAnnotation();
container.setSource(MAP_ENTRY_CLASS_CONTAINER_ANNOTATION_SOURCE);
ePackage.getEAnnotations().add(container);
}
container.getContents().add(mapEClass);
}
}
else if (dataType != null)
{
Diagnostic diagnostic = EcoreValidator.EGenericTypeBuilder.INSTANCE.parseInstanceTypeName(dataType);
if (diagnostic.getSeverity() == Diagnostic.OK)
{
ecoreEGenericType = (EGenericType)diagnostic.getData().get(0);
diagnostic = EcoreValidator.EGenericTypeBuilder.INSTANCE.parseInstanceTypeName(type);
if (diagnostic.getSeverity() == Diagnostic.OK)
{
javaEGenericType = (EGenericType)diagnostic.getData().get(0);
}
}
else
{
ecoreEGenericType = EcoreFactory.eINSTANCE.createEGenericType();
ecoreEGenericType.setEClassifier(EcorePackage.Literals.EJAVA_OBJECT);
basicDiagnostic.add(diagnostic);
}
}
else
{
Diagnostic diagnostic = EcoreValidator.EGenericTypeBuilder.INSTANCE.parseInstanceTypeName(type);
if (diagnostic.getSeverity() == Diagnostic.OK)
{
javaEGenericType = (EGenericType)diagnostic.getData().get(0);
}
else
{
ecoreEGenericType = EcoreFactory.eINSTANCE.createEGenericType();
ecoreEGenericType.setEClassifier(EcorePackage.Literals.EJAVA_OBJECT);
basicDiagnostic.add(diagnostic);
}
}
if (ecoreEGenericType == null)
{
eTypedElement.setEGenericType(javaEGenericType);
ecoreEGenericTypeToJavaEGenericTypeMap.put(javaEGenericType, null);
}
else
{
eTypedElement.setEGenericType(ecoreEGenericType);
ecoreEGenericTypeToJavaEGenericTypeMap.put(ecoreEGenericType, javaEGenericType);
}
eTypedElement.setUnique(!"false".equals(getModelAnnotationAttribute(modelAnnotation, "unique")));
eTypedElement.setOrdered(!"false".equals(getModelAnnotationAttribute(modelAnnotation, "ordered")));
}
protected JCompilationUnit getJCompilationUnit(EModelElement eModelElement)
{
for (; eModelElement != null; eModelElement = (EModelElement)eModelElement.eContainer())
{
JCompilationUnit compilationUnit = facadeHelper.getCompilationUnit(eModelElementToJNodeMap.get(eModelElement));
if (compilationUnit != null)
{
return compilationUnit;
}
}
return null;
}
/**
* Strips the type arguments from the type, if it has any.
*/
protected String stripTypeArguments(String type)
{
int start = type.indexOf('<');
if (start > 0)
{
int end = type.lastIndexOf('>');
if (end > start+1)
{
return type.substring(0, start).trim();
}
}
return type;
}
protected EStructuralFeature createFeature(EClass eClass, String name, EGenericType eGenericType)
{
EClassifier eClassifier = eGenericType.getERawType();
if (eClassifier instanceof EClass)
{
EReference eReference = EcoreFactory.eINSTANCE.createEReference();
eReference.setName(name);
eReference.setEGenericType(eGenericType);
eClass.getEStructuralFeatures().add(eReference);
eStructuralFeatures.add(eReference);
return eReference;
}
else
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName(name);
eAttribute.setEGenericType(eGenericType);
eClass.getEStructuralFeatures().add(eAttribute);
eStructuralFeatures.add(eAttribute);
return eAttribute;
}
}
/**
* Creates EEnumLiteral as appropriate.
* @return <code>true</code> when the method has created an EnumLiteral after
* analyzing the JMember
*/
protected boolean analyzeEnumLiteral(EEnum eEnum, JMember member)
{
String modelAnnotation = getModelAnnotation(member.getComment());
if (modelAnnotation != null)
{
String fieldName = member.getName();
EEnumLiteral eEnumLiteral = EcoreFactory.eINSTANCE.createEEnumLiteral();
eModelElementToJNodeMap.put(eEnumLiteral, member);
eEnumLiteral.getEAnnotations().addAll(extractEAnnotations(modelAnnotation));
EcoreUtil.setDocumentation(eEnumLiteral, getModelDocumentation(member.getComment()));
// Allow the value to be defined by an annotation or by the field's initializer
//
String value = getModelAnnotationAttribute(modelAnnotation, "value");
if (value == null)
{
if (member instanceof JField)
{
String initializer = ((JField)member).getInitializer();
if (initializer != null)
{
value = initializer.trim();
}
}
}
if (value != null)
{
try
{
int intValue = Integer.parseInt(value);
eEnumLiteral.setValue(intValue);
}
catch (NumberFormatException exception)
{
warning
(JavaImporterPlugin.INSTANCE.getString
("_UI_InvalidLiteralValueForField",
new Object [] { value, eEnum.getName() + "." + fieldName }));
eEnumLiteral.setValue(eEnum.getELiterals().size());
}
}
else
{
eEnumLiteral.setValue(eEnum.getELiterals().size());
}
// Allow a mixed case version of the name to be provided.
//
String name = getModelAnnotationAttribute(modelAnnotation, "name");
if (fieldName.endsWith("_VALUE") && (name == null || !name.toLowerCase().endsWith("value")))
{
fieldName = fieldName.substring(0, fieldName.length()-"_VALUE".length());
}
// But, if name doesn't expand into field name, ignore it.
//
if (name == null || !CodeGenUtil.format(name, '_', null, false, true).toUpperCase().equals(fieldName))
{
if (name != null)
{
warning
(JavaImporterPlugin.INSTANCE.getString
("_UI_InvalidLiteralNameForField", new Object[] { name, eEnum.getName() + "." + fieldName }));
}
name = fieldName;
}
eEnumLiteral.setName(name);
// Allow a distinct literal value to be provided, too.
//
String literal = getModelAnnotationAttribute(modelAnnotation, "literal");
if (literal != null)
{
eEnumLiteral.setLiteral(literal);
}
return eEnum.getELiterals().add(eEnumLiteral);
}
return false;
}
/**
* The pattern for extracting the model documentation.
*/
protected static Pattern modelDocExpression =
Pattern.compile
("<!--\\s*begin-model-doc\\s*-->[ \\f\\n\\r\\t]*\\*\\s?(.*?)<!--\\s*end-model-doc\\s*-->",
Pattern.MULTILINE | Pattern.DOTALL);
/**
* Returns the model documentation, or null.
*/
protected String getModelDocumentation(String comment)
{
if (comment != null)
{
Matcher matcher = modelDocExpression.matcher(comment);
if (matcher.find())
{
return comment.substring(matcher.start(1), matcher.end(1)).replaceAll("[\\n\\r]*\\s*\\*[\\s]?", "\n").replaceAll("\\s*$", "");
}
}
return null;
}
/**
* The pattern for extracting the @model annotations.
*/
protected static Pattern modelAnnotationExpression =
Pattern.compile
("@[ \\f\\n\\r\\t*]*model[ \\f\\n\\r\\t*]*((\\w*\\s*=\\s*(['\"])(?>\\\\.|.)*?\\3[ \\f\\n\\r\\t*]*)*)",
Pattern.MULTILINE);
/**
* Returns the @model annotation contents, or null.
*/
protected String getModelAnnotation(String comment)
{
if (comment != null)
{
Matcher matcher = modelAnnotationExpression.matcher(comment);
if (matcher.find())
{
return CodeGenUtil.xmlEscapeDecode(comment.substring(matcher.start(1), matcher.end(1)));
}
}
return null;
}
/**
* The pattern for extracting the @extends annotations.
*/
protected static Pattern extendsAnnotationExpression = Pattern.compile("@\\s*extends\\s*([.\\w<>,?\\s]+)", Pattern.MULTILINE);
/**
* The pattern for extracting the @implements annotations.
*/
protected static Pattern implementsAnnotationExpression = Pattern.compile("@\\s*implements\\s*([.\\w<>,?\\s]+)", Pattern.MULTILINE);
/**
* Returns the @extends/@implements annotation contents, or null.
*/
protected String getExtendsAnnotation(String comment)
{
if (comment != null)
{
StringBuilder result = new StringBuilder();
Matcher extendsMatcher = extendsAnnotationExpression.matcher(comment);
while (extendsMatcher.find())
{
if (result.length() != 0)
{
result.append(',');
}
result.append(comment.substring(extendsMatcher.start(1), extendsMatcher.end(1)));
}
Matcher implementsMatcher = implementsAnnotationExpression.matcher(comment);
while (implementsMatcher.find())
{
if (result.length() != 0)
{
result.append(',');
}
result.append(comment.substring(implementsMatcher.start(1), implementsMatcher.end(1)));
}
return result.length() == 0 ? null : result.toString();
}
return null;
}
/**
* Returns the unquoted value of attribute-name="value" or of attribute-name='value', or null.
*/
protected String getModelAnnotationAttribute(String modelAnnotation, String attributeName)
{
Pattern modelAnnotationAttributeExpressionDoubleQuote =
Pattern.compile
("\\b" + attributeName + "\\s*=\\s*([\"'])((?>\\\\.|.)*?)\\1",
Pattern.MULTILINE);
Matcher matcher = modelAnnotationAttributeExpressionDoubleQuote.matcher(modelAnnotation);
if (matcher.find())
{
return modelAnnotation.substring(matcher.start(2), matcher.end(2));
}
else
{
return null;
}
}
/**
* Returns the space separated concatenation of the unquoted value of each attribute-name="value" or attribute-name='value' repeat, or null.
*/
protected String getModelAnnotationAttributes(String modelAnnotation, String attributeName)
{
StringBuilder result = null;
Pattern modelAnnotationAttributeExpressionDoubleQuote =
Pattern.compile
("\\b" + attributeName + "\\s*=\\s*([\"'])((?>\\\\.|.)*?)\\1",
Pattern.MULTILINE);
for (Matcher matcher = modelAnnotationAttributeExpressionDoubleQuote.matcher(modelAnnotation); matcher.find();)
{
if (result == null)
{
result = new StringBuilder();
}
else
{
result.append(' ');
}
result.append(modelAnnotation.subSequence(matcher.start(2), matcher.end(2)));
}
return result == null ? null : result.toString();
}
protected static Pattern eAnnotationExpression = Pattern.compile("\\G\\s*((?>\\\\.|\\S)+)((?:\\s+(?>\\\\.|\\S)+\\s*+=\\s*(['\"])((?>\\\\.|.)*?)\\3)*)");
protected static Pattern eAnnotationDetailExpression = Pattern.compile("\\s+((?>\\\\.|\\S)+)\\s*+=\\s*((['\"])((?>\\\\.|.)*?)\\3)");
protected List<EAnnotation> extractEAnnotations(String modelAnnotation)
{
List<EAnnotation> result = Collections.emptyList();
String annotations = getModelAnnotationAttributes(modelAnnotation, "annotation");
if (annotations != null)
{
for (Matcher matcher = eAnnotationExpression.matcher(annotations); matcher.find();)
{
if (result == Collections.EMPTY_LIST)
{
result = new ArrayList<EAnnotation>();
}
EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
result.add(eAnnotation);
eAnnotation.setSource(parseString(matcher.group(1)));
EMap<String, String> details = eAnnotation.getDetails();
for (Matcher detailMatcher = eAnnotationDetailExpression.matcher(matcher.group(2)); detailMatcher.find();)
{
details.put(parseString(detailMatcher.group(1)), parseString(detailMatcher.group(4)));
}
}
}
String extendedMetaDataAnnotations = getModelAnnotationAttributes(modelAnnotation, "extendedMetaData");
if (extendedMetaDataAnnotations != null)
{
if (result == Collections.EMPTY_LIST)
{
result = new ArrayList<EAnnotation>();
}
EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
result.add(eAnnotation);
eAnnotation.setSource(ExtendedMetaData.ANNOTATION_URI);
EMap<String, String> details = eAnnotation.getDetails();
for (Matcher detailMatcher = eAnnotationDetailExpression.matcher(" " + extendedMetaDataAnnotations); detailMatcher.find();)
{
details.put(parseString(detailMatcher.group(1)), parseString(detailMatcher.group(4)));
}
}
return result;
}
private static String parseString(String stringLiteralBody)
{
return CodeGenUtil.parseString(stringLiteralBody);
}
/**
* Returns the filtered matches xyzAttribute-name="value" or of xyxAttribute-name='value', or null.
*/
protected String getFilteredModelAnnotations(String modelAnnotation, String filter)
{
StringBuilder result = new StringBuilder();
Pattern modelAnnotationAttributeExpressionDoubleQuote =
Pattern.compile
("\\b" + filter + "([A-Z]\\w*\\s*=\\s*([\"'])((?>\\\\.|.)*?)\\2)",
Pattern.MULTILINE);
int start = 0;
int end = modelAnnotation.length();
Matcher matcher;
while ((matcher = modelAnnotationAttributeExpressionDoubleQuote.matcher(modelAnnotation.subSequence(start, end))).find())
{
result.append(modelAnnotation.substring(start + matcher.start(1), start + matcher.start(1) + 1).toLowerCase());
result.append(modelAnnotation.substring(start + matcher.start(1) + 1, start + matcher.end(1)));
result.append(' ');
start += matcher.end(0);
}
return result.toString();
}
protected void match(List<EGenericType> target, List<EGenericType> javaEGenericTypes, List<EGenericType> ecoreEGenericTypes)
{
for (Iterator<EGenericType> i = javaEGenericTypes.iterator(), j = ecoreEGenericTypes == null ? null : ecoreEGenericTypes.iterator(); i.hasNext(); )
{
EGenericType javaEGenericType = i.next();
EGenericType ecoreEGenericType = j != null && j.hasNext() ? j.next() : null;
// If there is no Ecore representation or it's invalid, e.g., when - is used to omit a specification, then just use the Java representation.
//
if (ecoreEGenericType == null || ecoreEGenericType.getEClassifier() == null)
{
ecoreEGenericTypeToJavaEGenericTypeMap.put(javaEGenericType, null);
target.add(javaEGenericType);
}
else
{
ecoreEGenericTypeToJavaEGenericTypeMap.put(ecoreEGenericType, javaEGenericType);
target.add(ecoreEGenericType);
}
}
}
protected void resolve(EModelElement eModelElement, EGenericType ecoreEGenericType, EGenericType javaEGenericType)
{
EClassifier eClassifier = ecoreEGenericType.getERawType();
if (eClassifier.getEPackage() == null)
{
if (javaEGenericType != null)
{
ETypeParameter eTypeParameter = javaEGenericType.getETypeParameter();
if (eTypeParameter != null)
{
eClassifier = null;
ecoreEGenericType.setEClassifier(null);
ecoreEGenericType.setETypeParameter(eTypeParameter);
}
else
{
eClassifier.setInstanceTypeName
(ecoreEGenericType.getETypeArguments().isEmpty() ?
eGenericTypeConverter.toJavaInstanceTypeName(javaEGenericType) :
javaEGenericType.getEClassifier().getInstanceTypeName());
}
}
if (eClassifier != null)
{
EPackage ePackage = (EPackage)EcoreUtil.getRootContainer(eModelElement);
addToPackage(ePackage, eClassifier);
if (eClassifier instanceof EClass)
{
for (EStructuralFeature eStructuralFeature : ((EClass)eClassifier).getEStructuralFeatures())
{
resolve(eStructuralFeature, eStructuralFeature.getEGenericType(), (EGenericType)null);
}
}
}
}
EGenericType ecoreEUpperBound = ecoreEGenericType.getEUpperBound();
if (ecoreEUpperBound != null)
{
resolve(eModelElement, ecoreEUpperBound, javaEGenericType == null ? null : javaEGenericType.getEUpperBound());
}
else
{
EGenericType ecoreELowerBound = ecoreEGenericType.getELowerBound();
if (ecoreELowerBound != null)
{
resolve(eModelElement, ecoreELowerBound, javaEGenericType == null ? null : javaEGenericType.getELowerBound());
}
}
if (eClassifier != null)
{
int index = 0;
for (Iterator<EGenericType>
i = ecoreEGenericType.getETypeArguments().iterator(),
j = javaEGenericType == null ? null : javaEGenericType.getETypeArguments().iterator();
i.hasNext();
++index)
{
EGenericType eTypeArgument = i.next();
EGenericType eTypeArgumentInstance = j != null && j.hasNext() ? j.next() : null;
if (demandCreatedEClassifiers.contains(eClassifier) && eClassifier.getETypeParameters().size() <= index)
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName(index == 0? "T" : "T" + index);
eClassifier.getETypeParameters().add(eTypeParameter);
}
resolve(eModelElement, eTypeArgument, eTypeArgumentInstance);
}
}
}
protected void resolve(EModelElement eModelElement, EGenericType eGenericType, RequiredClassifierType requiredClassifierType)
{
EClassifier eClassifier = eGenericType.getEClassifier();
if (eClassifier != null)
{
if (eClassifier.eContainer() == null)
{
EGenericType resolvedEGenericType = resolve(eModelElement, eClassifier.getInstanceTypeName(), requiredClassifierType, false);
eGenericType.setETypeParameter(resolvedEGenericType.getETypeParameter());
eGenericType.setEClassifier(resolvedEGenericType.getEClassifier());
}
else if (eClassifier.getEPackage() == null)
{
EGenericType resolvedEGenericType = resolve(eModelElement, eClassifier.getName(), requiredClassifierType, false);
if (resolvedEGenericType.getERawType().getEPackage() == null)
{
EPackage ePackage = (EPackage)EcoreUtil.getRootContainer(eClassifier);
addToPackage(ePackage, eClassifier);
}
else
{
eGenericType.setETypeParameter(null);
eGenericType.setEClassifier(resolvedEGenericType.getEClassifier());
}
}
for (EGenericType eTypeArgument : eGenericType.getETypeArguments())
{
resolve(eModelElement, eTypeArgument, RequiredClassifierType.NONE);
}
}
else
{
EGenericType eUpperBound = eGenericType.getEUpperBound();
if (eUpperBound != null)
{
resolve(eModelElement, eUpperBound, RequiredClassifierType.NONE);
}
else
{
EGenericType eLowerBound = eGenericType.getELowerBound();
if (eLowerBound != null)
{
resolve(eModelElement, eLowerBound, RequiredClassifierType.NONE);
}
}
}
}
protected enum RequiredClassifierType
{
NONE
{
@Override
boolean isValid(EClassifier eClassifier)
{
return eClassifier != null;
}
},
CLASS
{
@Override
boolean isValid(EClassifier eClassifier)
{
return eClassifier instanceof EClass;
}
},
DATA_TYPE
{
@Override
boolean isValid(EClassifier eClassifier)
{
return eClassifier instanceof EDataType;
}
};
abstract boolean isValid(EClassifier eClassifier);
}
protected EGenericType resolve(EModelElement eModelElement, String typeName, RequiredClassifierType requiredClassifierType, boolean recordDemandCreatedEClassifier)
{
EPackage ePackage = (EPackage)EcoreUtil.getRootContainer(eModelElement);
// We want to resolve to this.
//
EGenericType eGenericType = null;
// Check if it is exactly the name of a type parameter that's in scope.
//
for (EObject eObject = eModelElement; eObject != null; eObject = eObject.eContainer())
{
EList<ETypeParameter> eTypeParameters = null;
if (eObject instanceof EOperation)
{
eTypeParameters = ((EOperation)eObject).getETypeParameters();
}
else if (eObject instanceof EClass)
{
eTypeParameters = ((EClass)eObject).getETypeParameters();
}
// If we've found thing with type parameters, search them for a match.
//
if (eTypeParameters != null)
{
for (ETypeParameter localETypeParameter : eTypeParameters)
{
if (typeName.equals(localETypeParameter.getName()))
{
// If we find a match, make this generic type be for this type parameter,
// and then stop the whole process.
eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setETypeParameter(localETypeParameter);
return eGenericType;
}
}
}
}
// Check if the name is qualified
//
String baseName = typeName;
String packageName = "";
int index = baseName.lastIndexOf(".");
// For arrays, consider the element type.
//
int i = baseName.indexOf('[');
String elementTypeName = i == -1 ? baseName : baseName.substring(0, i);
if (index == -1)
{
// Look through the imports of the containing compilation unit.
//
JCompilationUnit compilationUnit = getJCompilationUnit(eModelElement);
if (compilationUnit != null)
{
boolean firstType = true;
LOOP:
for (JType jType : facadeHelper.getChildren(compilationUnit, JType.class))
{
String name = jType.getName();
if (elementTypeName.equals(name))
{
packageName = facadeHelper.getPackage(compilationUnit).getQualifiedName();
typeName = packageName + "." + baseName;
break;
}
else if (firstType)
{
for (JAbstractType jAbstractType : facadeHelper.getChildren(jType, JAbstractType.class))
{
if (!(jAbstractType instanceof JAnnotationType))
{
String nestedName = jAbstractType.getName();
if (elementTypeName.equals(nestedName))
{
packageName = facadeHelper.getPackage(compilationUnit).getQualifiedName();
typeName = packageName + "." + name + '$' + baseName;
break LOOP;
}
}
}
firstType = false;
}
}
// Find an explicit import or the first wildcard import.
//
if (packageName.length() == 0)
{
boolean firstWildcard = true;
for (JImport jImport : facadeHelper.getChildren(compilationUnit, JImport.class))
{
String importName = jImport.getName();
if (importName.endsWith("." + elementTypeName))
{
int importIndex = importName.lastIndexOf(".");
packageName = importName.substring(0, importIndex);
typeName = packageName + "." + baseName;
break;
}
else if (firstWildcard && importName.endsWith(".*"))
{
int importIndex = importName.lastIndexOf(".");
packageName = importName.substring(0, importIndex);
typeName = packageName + "." + baseName;
firstWildcard = false;
}
}
}
// Find the modeled package for the import and look up the name there.
//
EPackage otherEPackage = packageNameToEPackageMap.get(packageName);
if (otherEPackage == null)
{
otherEPackage = externalPackageNameToEPackageMap.get(packageName);
}
if (otherEPackage != null)
{
EClassifier eClassifier = otherEPackage.getEClassifier(baseName);
if (requiredClassifierType.isValid(eClassifier))
{
eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(eClassifier);
}
}
}
// If we can't find it, try the simple name in the package...
//
if (eGenericType == null && "".equals(packageName))
{
EClassifier eClassifier = ePackage.getEClassifier(baseName);
if (requiredClassifierType.isValid(eClassifier))
{
eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(eClassifier);
}
else if (i != -1 && CodeGenUtil.isJavaLangType(elementTypeName))
{
packageName = "java.lang";
typeName = packageName + "." + baseName;
}
}
}
else
{
// Find the modeled package for the name and look up the name there.
//
packageName = baseName.substring(0, index);
if (eModelElement.eContainer() instanceof EClassifier &&
packageName.equals(((EClassifier)eModelElement.eContainer()).getName()))
{
JCompilationUnit compilationUnit = getJCompilationUnit(eModelElement);
if (compilationUnit != null)
{
typeName = packageName;
packageName = facadeHelper.getPackage(compilationUnit).getQualifiedName();
typeName = packageName + "." + typeName + "$" + baseName.substring(index + 1);
}
}
else
{
baseName = baseName.substring(index + 1);
EPackage otherEPackage = packageNameToEPackageMap.get(packageName);
if (otherEPackage == null)
{
otherEPackage = externalPackageNameToEPackageMap.get(packageName);
if (otherEPackage == null)
{
if ("org.eclipse.emf.ecore".equals(packageName))
{
otherEPackage = EcorePackage.eINSTANCE;
}
else if ("org.eclipse.emf.ecore.xml.type".equals(packageName))
{
otherEPackage = XMLTypePackage.eINSTANCE;
}
else if ("org.eclipse.emf.ecore.xml.namespace".equals(packageName))
{
otherEPackage = XMLNamespacePackage.eINSTANCE;
}
}
}
if (otherEPackage != null)
{
EClassifier eClassifier = otherEPackage.getEClassifier(baseName);
if (eClassifier != null)
{
eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(eClassifier);
}
}
}
}
// If we still don't have one, we'll have to settle for an EDataType or EClass with an instance class name.
//
if (eGenericType == null)
{
// See if we already have the EDataType.
//
String modifiedName = typeName.replace('$', '.');
for (EClassifier ePackageClassifier : ePackage.getEClassifiers())
{
String name = ePackageClassifier.getInstanceTypeName();
if (name != null &&
name.replace('$', '.').equals(modifiedName) &&
requiredClassifierType.isValid(ePackageClassifier))
{
eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(ePackageClassifier);
break;
}
}
}
if (eGenericType == null &&
EcorePackage.Literals.EOBJECT.getInstanceTypeName().equals(typeName) &&
requiredClassifierType != RequiredClassifierType.DATA_TYPE)
{
eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(EcorePackage.Literals.EOBJECT);
}
// Just to be helpful, we'll recognize a type of org.eclipse.emf.ecore.util.FeatureMap and convert it to EFeatureMapEntry.
// This way a dataType need not be specified. But, we won't do this if recordDemandCreateEDataType is false, so we don't
// change the instanceClass of a new EDataType that's implicitly being defined for FeatureMap.
//
if (eGenericType == null &&
EcorePackage.Literals.EFEATURE_MAP.getInstanceTypeName().equals(typeName) &&
requiredClassifierType != RequiredClassifierType.CLASS)
{
eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(EcorePackage.Literals.EFEATURE_MAP_ENTRY);
}
// If we don't have one yet, maybe it's one of the special types...
//
if (eGenericType == null &&
requiredClassifierType != RequiredClassifierType.CLASS &&
(packageName.length() == 0 ||
packageName.equals("java.lang") ||
packageName.equals("java.math") ||
packageName.equals("java.util")))
{
for (EClassifier ecoreEClassifier : EcorePackage.eINSTANCE.getEClassifiers())
{
if (ecoreEClassifier instanceof EDataType)
{
String instanceClassName = ecoreEClassifier.getInstanceClassName();
if ((instanceClassName.equals(typeName) || instanceClassName.equals("java.lang." + typeName)) &&
(ecoreEClassifier.getETypeParameters().isEmpty() ||
ecoreEClassifier == EcorePackage.Literals.EJAVA_CLASS))
{
eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(ecoreEClassifier);
break;
}
}
}
}
// If we still don't have one, we'll have to settle for a demand created EDataType or EClass,
// so create a new EClassifier with a nice unique name.
//
if (eGenericType == null)
{
// If the name isn't qualified, it might be a primitive or from java.lang. Otherwise, assume it's in the current
// package and use the nsPrefix for the qualified package name.
//
boolean primitive = false;
String instanceTypeName = typeName;
if (packageName.length() == 0)
{
if (CodeGenUtil.isJavaPrimitiveType(elementTypeName))
{
primitive = true;
}
else if (CodeGenUtil.isJavaLangType(elementTypeName))
{
packageName = "java.lang";
instanceTypeName = packageName + "." + instanceTypeName;
}
else
{
packageName = ePackage.getNsPrefix();
instanceTypeName = packageName + '.' + instanceTypeName;
}
}
EClassifier eClassifier = null;
if (!"java.util.Map$Entry".equals(instanceTypeName))
{
for (EClassifier demandCreatedEClassifier : demandCreatedEClassifiers)
{
if (requiredClassifierType.isValid(demandCreatedEClassifier) &&
instanceTypeName.equals(demandCreatedEClassifier.getInstanceTypeName()))
{
eClassifier = demandCreatedEClassifier;
}
}
}
if (eClassifier == null)
{
if (requiredClassifierType == RequiredClassifierType.CLASS)
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setAbstract(true);
eClass.setInterface(true);
eClassifier = eClass;
}
else
{
eClassifier = EcoreFactory.eINSTANCE.createEDataType();
}
demandCreatedEClassifiers.add(eClassifier);
eClassifier.setInstanceTypeName(instanceTypeName);
// Even primitives should be represented by a data type with a conventional (i.e. capitalized) name.
//
String name = baseName;
if (primitive && name.length() > 0)
{
name = CodeGenUtil.capName(name);
}
// Make array names legal.
//
while (name.endsWith("[]"))
{
name = name.substring(0, name.length() - 2) + "Array";
}
eClassifier.setName(name);
if (recordDemandCreatedEClassifier)
{
addToPackage(ePackage, eClassifier);
}
}
eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(eClassifier);
}
return eGenericType;
}
protected void addToPackage(EPackage ePackage, EClassifier eClassifier)
{
String baseName = eClassifier.getName();
String name = baseName;
// Avoid classifier name collisions.
//
for (int j = 1; ePackage.getEClassifier(name) != null; ++j)
{
name = baseName + "_" + j;
}
eClassifier.setName(name);
ePackage.getEClassifiers().add(eClassifier);
}
protected EGenericType resolveMapEntry(EPackage ePackage, EGenericType keyEGenericType, EGenericType valueEGenericType)
{
for (EClassifier ePackageClassifier : ePackage.getEClassifiers())
{
if (ePackageClassifier instanceof EClass &&
("java.util.Map.Entry".equals(ePackageClassifier.getInstanceClassName()) || "java.util.Map$Entry".equals(ePackageClassifier.getInstanceClassName())))
{
EClass mapEntryInterface = (EClass)ePackageClassifier;
EStructuralFeature keyFeature = mapEntryInterface.getEStructuralFeature("key");
if (keyFeature != null && EcoreUtil.equals(keyFeature.getEGenericType(), keyEGenericType) && !keyFeature.isMany())
{
EStructuralFeature valueFeature = mapEntryInterface.getEStructuralFeature("value");
if (valueFeature != null && EcoreUtil.equals(valueFeature.getEGenericType(), valueEGenericType) && !valueFeature.isMany())
{
EGenericType result = EcoreFactory.eINSTANCE.createEGenericType();
result.setEClassifier(mapEntryInterface);
return result;
}
}
}
}
return null;
}
protected <T extends ENamedElement> void sort(EList<T> namedElements, final Map<Object, Integer> nameToIDMap)
{
Collection<T> ordered = new TreeSet<T>(new Comparator<T>()
{
@Override
public boolean equals(Object object)
{
return object == this;
}
public int compare(T firstObject, T secondObject)
{
int firstValue = getOrderingValue(firstObject, nameToIDMap);
int secondValue = getOrderingValue(secondObject, nameToIDMap);
return firstValue - secondValue;
}
});
ordered.addAll(namedElements);
int index = 0;
for (T eNamedElement : ordered)
{
namedElements.move(index++, eNamedElement);
}
}
protected int getOrderingValue(ENamedElement eNamedElement, Map<Object, Integer> nameToIDMap)
{
Integer result = nameToIDMap.get(eNamedElement);
if (result == null)
{
if (eNamedElement instanceof EClassifier)
{
String prefix = ePackageToPrefixMap.get(eNamedElement.eContainer());
String name = eNamedElement.getName();
String id = CodeGenUtil.format(name, '_', prefix, true, true).toUpperCase();
result = nameToIDMap.get(id);
}
else
{
String prefix = ePackageToPrefixMap.get(eNamedElement.eContainer().eContainer());
String eClassName = ((ENamedElement)eNamedElement.eContainer()).getName();
String eFeatureName = eNamedElement.getName();
String id = CodeGenUtil.format(eClassName, '_', prefix, true, true).toUpperCase() + "__"
+ CodeGenUtil.format(eFeatureName, '_', prefix, true, false).toUpperCase();
result = nameToIDMap.get(id);
}
if (result != null)
{
nameToIDMap.put(eNamedElement, result);
}
}
if (result != null)
{
return result;
}
return Integer.MAX_VALUE;
}
protected <T extends ENamedElement> T getNamedElement(List<T> namedElements, String name)
{
if (name != null)
{
for (T namedElement : namedElements)
{
if (name.equals(namedElement.getName()))
{
return namedElement;
}
}
}
return null;
}
/**
* Returns the diagnostic.
* @return the status.
*/
public Diagnostic getDiagnostic()
{
return basicDiagnostic;
}
/**
* Returns the generator model.
* @return the generator model.
*/
public GenModel getGenModel()
{
return genModel;
}
/**
* Returns the list of used GenPackages.
* @return the list of used GenPackages.
*/
public Collection<GenPackage> getUsedGenPackages()
{
return usedGenPackages;
}
/**
* Produces another IStatus in the MultiStatus.
* @param message a description of the error.
*/
protected void error(String message)
{
System.err.println("-->Error: " + message);
basicDiagnostic.add(new BasicDiagnostic(Diagnostic.ERROR, JavaImporterPlugin.getPlugin().getBundle().getSymbolicName(), 0, message, null));
}
/**
* Produces another IStatus in the MultiStatus, with warning severity.
* @param message a description of the error.
*/
protected void warning(String message)
{
System.err.println("-->Warning: " + message);
basicDiagnostic.add(new BasicDiagnostic(Diagnostic.WARNING, JavaImporterPlugin.getPlugin().getBundle().getSymbolicName(), 0, message, null));
}
}