package org.archstudio.dblgen; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.archstudio.dblgen.DataBindingGenerationStatus.Status; import org.archstudio.dblgen.builder.Xadl3SchemaLocation; import org.archstudio.dblgen.core.Activator; import org.archstudio.releng.pde.actions.SortManifests; import org.archstudio.sysutils.SystemUtils; import org.archstudio.utils.eclipse.jdt.CodeGeneration; import org.archstudio.utils.osgi.OSGiUtils; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.RegistryFactory; import org.eclipse.emf.codegen.ecore.generator.Generator; import org.eclipse.emf.codegen.ecore.generator.GeneratorAdapterFactory; import org.eclipse.emf.codegen.ecore.genmodel.GenJDKLevel; import org.eclipse.emf.codegen.ecore.genmodel.GenModel; import org.eclipse.emf.codegen.ecore.genmodel.GenModelPackage; import org.eclipse.emf.codegen.ecore.genmodel.GenPackage; import org.eclipse.emf.codegen.ecore.genmodel.generator.GenBaseGeneratorAdapter; import org.eclipse.emf.codegen.ecore.genmodel.generator.GenModelGeneratorAdapterFactory; import org.eclipse.emf.common.util.BasicMonitor; import org.eclipse.emf.common.util.Monitor; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.converter.ModelConverter.EPackageConvertInfo; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.URIConverter; import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; import org.eclipse.osgi.framework.util.Headers; import org.eclipse.osgi.util.ManifestElement; import org.eclipse.pde.core.plugin.IExtensions; import org.eclipse.pde.core.plugin.IExtensionsModelFactory; import org.eclipse.pde.core.plugin.IPluginAttribute; import org.eclipse.pde.core.plugin.IPluginElement; import org.eclipse.pde.core.plugin.IPluginExtension; import org.eclipse.pde.core.plugin.IPluginModelBase; import org.eclipse.pde.core.plugin.IPluginObject; import org.eclipse.pde.core.plugin.PluginRegistry; import org.eclipse.pde.core.project.IBundleProjectDescription; import org.eclipse.pde.core.project.IBundleProjectService; import org.eclipse.pde.core.project.IPackageExportDescription; import org.eclipse.pde.core.project.IRequiredBundleDescription; import org.eclipse.pde.internal.core.bundle.WorkspaceBundlePluginModel; import org.eclipse.xsd.ecore.importer.XSDImporter; import org.eclipse.xsd.util.XSDResourceFactoryImpl; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import com.google.common.base.Function; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; import com.google.common.collect.Sets; @SuppressWarnings("restriction") public class DataBindingGeneratorImpl implements IDataBindingGenerator { public static final String XADL3_SCHEMA_NATURE_ID = "org.archstudio.dblgen.xadl3SchemaNature"; static { Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("xsd", new XSDResourceFactoryImpl()); Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("xml", new XMIResourceFactoryImpl()); Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("*", new XMIResourceFactoryImpl()); GeneratorAdapterFactory.Descriptor.Registry.INSTANCE.addDescriptor(GenModelPackage.eNS_URI, GenModelGeneratorAdapterFactory.DESCRIPTOR); URIConverter.URI_MAP.put(URI.createURI(EcorePackage.eNS_URI), URI.createURI("platform:/plugin/org.eclipse.emf.ecore/model/Ecore.xsd")); } /** * Parses an XML file. * * @param documentInputStream Input stream for XML content * @return Parsed DOM Document object * @throws ParserConfigurationException If the parser was misconfigured somehow. * @throws SAXException on a parsing error. * @throws IOException on an I/O error. */ private static Document parseDocument(InputStream documentInputStream) throws ParserConfigurationException, SAXException, IOException { DocumentBuilder docBuilder; Document doc = null; DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); docBuilderFactory.setIgnoringElementContentWhitespace(true); docBuilder = docBuilderFactory.newDocumentBuilder(); doc = docBuilder.parse(documentInputStream); return doc; } private static String getProjectName(IProject project) throws BundleException, IOException, CoreException { Headers<String, String> manifestHeaders = Headers.parseManifest( new ByteArrayInputStream(SystemUtils.blt(project.getFile("META-INF/MANIFEST.MF").getContents()))); ManifestElement[] elements = ManifestElement.parseHeader("Bundle-SymbolicName", manifestHeaders.get("Bundle-SymbolicName")); return elements[0].getValue(); } private static String getSchemaNsUri(InputStream is) throws ParserConfigurationException, SAXException, IOException { Document doc = DataBindingGeneratorImpl.parseDocument(is); Element elt = doc.getDocumentElement(); String xmlns = elt.getAttribute("targetNamespace"); if (xmlns == null || xmlns.trim().length() == 0) { xmlns = elt.getAttribute("xmlns"); } return xmlns; } private static IPluginExtension copyPluginExtensions(IExtensionsModelFactory factory, IPluginExtension pluginExtension) throws CoreException { IPluginExtension extension = factory.createExtension(); if (pluginExtension.getId() != null && pluginExtension.getId().length() > 0) { extension.setId(pluginExtension.getId()); } if (pluginExtension.getName() != null && pluginExtension.getName().length() > 0) { extension.setName(pluginExtension.getName()); } if (pluginExtension.getPoint() != null && pluginExtension.getPoint().length() > 0) { extension.setPoint(pluginExtension.getPoint()); } for (IPluginObject child : pluginExtension.getChildren()) { extension.add(copyPluginExtension(factory, extension, child)); } return extension; } private static IPluginObject copyPluginExtension(IExtensionsModelFactory factory, IPluginObject parent, IPluginObject child) throws CoreException { IPluginElement newChild = factory.createElement(parent); if (child.getName() != null && child.getName().length() > 0) { newChild.setName(child.getName()); } for (IPluginAttribute attribute : ((IPluginElement) child).getAttributes()) { newChild.setAttribute(attribute.getName(), attribute.getValue()); } for (IPluginObject grandchild : ((IPluginElement) child).getChildren()) { newChild.add(copyPluginExtension(factory, child, grandchild)); } if (((IPluginElement) child).getText() != null) { newChild.setText(((IPluginElement) child).getText()); } return newChild; } /** * Internal data structure for capturing data about a Schema in a xADL Schema project. */ private static class SchemaRecord { /** The name space URI of the schema. */ final URI nsUri; /** The project containing the schema May be <code>null</code>. */ final IProject project; /** The bundle containing the schema. May be <code>null</code>. */ final Bundle bundle; /** Relative path from the bundle/project root to the schema. */ String schemaPath; /** Absolute URL to schema. */ String schemaUrl; /** URL of the schema file as resolved against the bundle/project. */ URL xsdFileUrl; /** Parsed schema doc object. */ final Document doc; /** The bundle/project name containing the schema. */ final String name; /** The import nsUri's within the XSD file. */ final List<String> imports; /** The target package name for the schema. */ final String packageName; public SchemaRecord(URI nsuri, IProject project, Bundle bundle, String schemaPath, String schemaUrl, URL xsdFileUrl, String packageName) throws ParserConfigurationException, SAXException, IOException, CoreException, BundleException { this.nsUri = nsuri; this.project = project; this.bundle = bundle; this.schemaPath = schemaPath; this.schemaUrl = schemaUrl; this.xsdFileUrl = xsdFileUrl; this.packageName = packageName; doc = DataBindingGeneratorImpl.parseDocument(xsdFileUrl.openStream()); name = getName(); imports = getImports(); } public String getName() throws BundleException, IOException, CoreException { if (project != null) { return getProjectName(project); } else if (bundle != null) { return bundle.getSymbolicName(); } throw new NullPointerException("Project and bundle not defined."); } List<String> getImports() { List<String> imports = new ArrayList<>(); Element docElt = doc.getDocumentElement(); NodeList children = docElt.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node n = children.item(i); if (n.getNodeName().endsWith(":import") && n instanceof Element) { imports.add(((Element) n).getAttribute("namespace")); } } return imports; } } private Monitor emfMonitor; // Name space URI to schema record. private Map<String, SchemaRecord> schemaRecords = new HashMap<>(); // A mapping from SchemaRecord.name (i.e., bundle or project name) to all SchemaRecord ns URI's in // that bundle/project. private ListMultimap<String, String> namedSchemaRecords = ArrayListMultimap.create(); public DataBindingGeneratorImpl() throws ParserConfigurationException, SAXException, IOException, CoreException, BundleException { // Refresh the resources in case they've been modified. IWorkspace workspace = ResourcesPlugin.getWorkspace(); IWorkspaceRoot workspaceRoot = workspace.getRoot(); workspaceRoot.refreshLocal(IResource.DEPTH_INFINITE, null); initializeSchemaRecordsFromBundles(); // Scan projects second in order to overwrite any installed bundles. initializeSchemaRecordsFromProjects(); } public synchronized void setMonitor(Monitor emfMonitor) { if (emfMonitor == null) { this.emfMonitor = DataBindingGeneratorImpl.createBasicPrintingMonitor(); } else { this.emfMonitor = emfMonitor; } } public static Monitor createBasicPrintingMonitor() { return new BasicMonitor.Printing(System.out); } private void initializeSchemaRecordsFromBundles() throws ParserConfigurationException, SAXException, IOException, CoreException, BundleException { for (IConfigurationElement c : RegistryFactory.getRegistry() .getConfigurationElementsFor("org.archstudio.dblgen", "processedSchema")) { URI nsURI = URI.createURI(c.getAttribute("nsURI")); String schemaPath = c.getAttribute("file"); String schemaUrl = c.getAttribute("url"); Bundle bundle = Platform.getBundle(c.getContributor().getName()); URL fileUrl; if (schemaPath != null) { fileUrl = bundle.getResource(schemaPath); if (fileUrl == null) { throw new NullPointerException("Cannot find schema for " + c.getContributor().getName() + "/" + schemaPath + ". Did you include it in the build?"); } } else if (schemaUrl != null) { fileUrl = new URL(schemaUrl); } else { throw new NullPointerException( "Neither file nor url are defined for " + c.getContributor().getName() + "."); } SchemaRecord record = new SchemaRecord(nsURI, null, bundle, schemaPath, schemaUrl, fileUrl, null); schemaRecords.put(nsURI.toString(), record); namedSchemaRecords.put(record.name, nsURI.toString()); } for (IConfigurationElement c : RegistryFactory.getRegistry() .getConfigurationElementsFor("org.archstudio.dblgen", "schemalocation")) { URL url = new URL(c.getAttribute("url")); URI nsURI = URI.createURI(getSchemaNsUri(url.openStream())); String packageName = c.getAttribute("name"); Bundle bundle = Platform.getBundle(c.getContributor().getName()); SchemaRecord record = new SchemaRecord(nsURI, null, bundle, null, url.toString(), url, packageName); schemaRecords.put(nsURI.toString(), record); namedSchemaRecords.put(record.name, nsURI.toString()); } } private void initializeSchemaRecordsFromProjects() throws ParserConfigurationException, SAXException, IOException, CoreException, BundleException { IWorkspace workspace = ResourcesPlugin.getWorkspace(); for (final IProject project : workspace.getRoot().getProjects()) { if (project.isAccessible() && project.hasNature(DataBindingGeneratorImpl.XADL3_SCHEMA_NATURE_ID)) { final String name = getProjectName(project); // Clear out bundle schema for the same name. namedSchemaRecords.removeAll(name); project.getFolder("model").accept(new IResourceVisitor() { @Override public boolean visit(IResource resource) throws CoreException { try { if (resource instanceof IFile) { IFile file = (IFile) resource; if ("xsd".equalsIgnoreCase(file.getFileExtension())) { InputStream is = null; try { URI nsURI = URI.createURI(getSchemaNsUri(file.getContents())); SchemaRecord record = new SchemaRecord(nsURI, project, null, file.getFullPath().makeRelativeTo(project.getFullPath()).toString(), null, file.getLocationURI().toURL(), null); schemaRecords.put(nsURI.toString(), record); namedSchemaRecords.put(name, nsURI.toString()); } finally { if (is != null) { is.close(); } } } } } catch (Exception e) { throw new CoreException(new org.eclipse.core.runtime.Status(IStatus.ERROR, "org.archstudio.dblgen.core", e.getMessage(), e)); } return true; } }); // Scan plugin for schemalocations. for (Xadl3SchemaLocation location : Xadl3SchemaLocation.parse(project)) { URL url = new URL(location.getUrl().toString()); URI nsURI = URI.createURI(getSchemaNsUri(url.openStream())); SchemaRecord record = new SchemaRecord(nsURI, project, null, null, url.toString(), url, location.getName()); schemaRecords.put(nsURI.toString(), record); namedSchemaRecords.put(record.name, nsURI.toString()); } } } } @Override public synchronized List<DataBindingGenerationStatus> generateBindings(List<String> schemaURIStrings, String projectName) { return generateBindings(schemaURIStrings, Collections.<Xadl3SchemaLocation> emptyList(), projectName); } // projectName = e.g., "org.archstudio.xadl3.bindings" public synchronized List<DataBindingGenerationStatus> generateBindings(List<String> schemaURIStrings, List<Xadl3SchemaLocation> schemaLocations, final String projectName) { List<DataBindingGenerationStatus> statusList = new ArrayList<DataBindingGenerationStatus>(); try { // Map available schema for offline use. for (SchemaRecord schemaRecord : schemaRecords.values()) { URIConverter.URI_MAP.put(schemaRecord.nsUri, URI.createURI(schemaRecord.xsdFileUrl.toURI().toString())); } final IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); XSDImporter importer = new XSDImporter() { /* * Note: XSDImporter seems to not support non-local files (e.g., projects imported from an external * folder, linked files, etc.). This is a problem because, in such cases, the generated resources are * saved in the wrong location. Later, when searching for the resources, they cannot be found and the * process fails. To resolve this, we extend the base class and move the resources to the correct * location before saving them. */ @Override protected List<Resource> computeResourcesToBeSaved() { List<Resource> resources = super.computeResourcesToBeSaved(); // Move these resources to the correct location. for (Resource resource : resources) { URI uri = resource.getURI(); IFile newFile = project.getFile(uri.lastSegment()); resource.setURI(URI.createURI(newFile.getLocationURI().toString())); } return resources; } }; importer.setUsePlatformURI(false); importer.setCreateEcoreMap(true); // We still have to assign some value here, even though it doesn't work. importer.setGenModelContainerPath(project.getFullPath()); importer.setGenModelFileName("xadl.genmodel"); String subfolder = "src"; final IPath subfolderPath = project.getFolder(subfolder).getFullPath(); importer.setModelPluginID(projectName); importer.setModelPluginDirectory("/" + projectName + "/" + subfolder); StringBuilder combinedModelURIs = new StringBuilder(); for (String modelURIString : schemaURIStrings) { combinedModelURIs.append(modelURIString); } for (Xadl3SchemaLocation schemaLocation : schemaLocations) { if (!schemaLocation.isCopyLocally()) { combinedModelURIs.append(schemaLocation.getUrl().toString()).append(" "); } } importer.setModelLocation(combinedModelURIs.toString()); boolean computePackagesSucceeded = false; try { importer.computeEPackages(emfMonitor); computePackagesSucceeded = true; // Fix names of external packages. Multimap<String, EPackage> packages = Multimaps.index(importer.getEPackages(), new Function<EPackage, String>() { @Override public String apply(EPackage input) { return input.getNsURI(); } }); for (SchemaRecord record : schemaRecords.values()) { if (record.packageName != null && packages.get(record.nsUri.toString()).size() > 0) { EPackage e = packages.get(record.nsUri.toString()).iterator().next(); e.setName(record.packageName); } } } catch (Exception e) { // Yes, in a remarkable display of programming good taste, computeEPackages does declare // that it throws "Exception" e.printStackTrace(); statusList.add(new DataBindingGenerationStatus(null, Status.FAILURE, "Error computing packages for schemas: " + importer.getModelLocation(), e)); return statusList; } if (!computePackagesSucceeded) { statusList.add(new DataBindingGenerationStatus(null, Status.FAILURE, "Computing packages unsuccessful for schema: " + importer.getModelLocation(), null)); return statusList; } // A list of EPackages that are referenced by the main schemas but for which we're not going // to generate bindings. We assume these are living in other schema projects. for (EPackage ePackage : importer.getEPackages()) { EPackageConvertInfo ePackageConvertInfo = importer.getEPackageConvertInfo(ePackage); if (ePackage.getNsURI().equals(EcorePackage.eNS_URI)) { // Don't convert the Ecore dependency; this seems to get included automagically. ePackageConvertInfo.setConvert(false); continue; } ePackageConvertInfo.setConvert(true); } // This causes the code to be generated with generics and such. GenModel genModel = importer.getGenModel(); genModel.setComplianceLevel(GenJDKLevel.JDK70_LITERAL); // Inscrutable EMF Magic: Note that this has to be done before the below loop through // referenced packages or it will throw a NullPointerException when adding packages to the // ResourceSet. importer.adjustEPackages(emfMonitor); importer.prepareGenModelAndEPackages(emfMonitor); boolean modelSaveSucceeded = false; try { importer.saveGenModelAndEPackages(emfMonitor); modelSaveSucceeded = true; } catch (Exception e) { // Another tasteful function that "throws Exception". e.printStackTrace(); statusList.add(new DataBindingGenerationStatus(null, Status.FAILURE, "Error saving generated content for schema: " + importer.getModelLocation(), e)); return statusList; } if (!modelSaveSucceeded) { statusList.add(new DataBindingGenerationStatus(null, Status.FAILURE, "Error saving generated content for schema: " + importer.getModelLocation(), null)); return statusList; } try { genModel.setCanGenerate(true); Generator codeGenerator = new Generator(); codeGenerator.setInput(genModel); // Find the gen package for the targeted schema. for (GenPackage genPackage : genModel.getGenPackages()) { // Only generate code for the schema in this project. if (namedSchemaRecords.get(projectName).contains(genPackage.getNSURI())) { codeGenerator.generate(genPackage, GenBaseGeneratorAdapter.MODEL_PROJECT_TYPE, emfMonitor); } } } catch (Exception e) { e.printStackTrace(); statusList.add(new DataBindingGenerationStatus(null, Status.FAILURE, "Error generating content for schema: " + importer.getModelLocation(), e)); return statusList; } // Update plugin's dependencies to include referenced schema. BundleContext context = Activator.getSingleton().getContext(); final IBundleProjectService service = OSGiUtils.getServiceReference(context, IBundleProjectService.class); IBundleProjectDescription description = service.getDescription(project); Map<String, IRequiredBundleDescription> requiredBundles = new HashMap<>(); for (IRequiredBundleDescription requiredBundle : SystemUtils .emptyIfNull(description.getRequiredBundles())) { requiredBundles.put(requiredBundle.getName(), requiredBundle); } requiredBundles.put("org.eclipse.emf.ecore", service.newRequiredBundle("org.eclipse.emf.ecore", null, false, true)); requiredBundles.put("org.eclipse.emf.ecore.xmi", service.newRequiredBundle("org.eclipse.emf.ecore.xmi", null, false, true)); requiredBundles.put("org.archstudio.dblgen", service.newRequiredBundle("org.archstudio.dblgen", null, false, true)); for (String nsUri : SystemUtils.emptyIfNull(namedSchemaRecords.get(projectName))) { if (schemaRecords.containsKey(nsUri)) { for (String importedNsUri : schemaRecords.get(nsUri).imports) { if (schemaRecords.containsKey(importedNsUri)) { String name = schemaRecords.get(importedNsUri).name; if (!projectName.equals(name)) { requiredBundles.put(name, service.newRequiredBundle(name, null, false, true)); } } } } } description.setRequiredBundles( requiredBundles.values().toArray(new IRequiredBundleDescription[requiredBundles.size()])); // Updated plugin's exported packages to include the java packages created. Actually, only // export created packages. final Map<String, IPackageExportDescription> packageExports = new HashMap<>(); project.getFolder(subfolder).accept(new IResourceVisitor() { @Override public boolean visit(IResource resource) throws CoreException { try { if (resource instanceof IFile) { IFile file = (IFile) resource; IPath path = file.getParent().getFullPath(); String packageName = path.makeRelativeTo(subfolderPath).toString().replace('/', '.'); packageExports.put(packageName, service.newPackageExport(packageName, null, true, null)); } } catch (Exception e) { throw new CoreException(new org.eclipse.core.runtime.Status(IStatus.ERROR, "org.archstudio.dblgen.core", "Error visiting " + resource.toString(), e)); } return true; } }); description.setPackageExports( packageExports.values().toArray(new IPackageExportDescription[packageExports.size()])); // Update plugin's bin includes to include the model folder. Set<IPath> binIncludes = Sets.newHashSet(SystemUtils.emptyIfNull(description.getBinIncludes())); binIncludes.add(new Path("model/")); List<IPath> binIncludesSorted = Lists.newArrayList(binIncludes); Collections.sort(binIncludesSorted, new Comparator<IPath>() { @Override public int compare(IPath o1, IPath o2) { return o1.toString().compareTo(o2.toString()); } }); description.setBinIncludes(binIncludesSorted.toArray(new IPath[binIncludesSorted.size()])); // Make sure that extensions are allowed. description.setExtensionRegistry(true); // Store the changes. description.apply(null); project.refreshLocal(IResource.DEPTH_INFINITE, null); // Add the package and parser extensions to the plugin. IFile manifestFile = project.getFile("META-INF/MANIFEST.MF"); manifestFile.refreshLocal(IResource.DEPTH_ONE, null); IFile pluginFile = project.getFile("plugin.xml"); pluginFile.refreshLocal(IResource.DEPTH_ONE, null); WorkspaceBundlePluginModel pluginModel = new WorkspaceBundlePluginModel(manifestFile, pluginFile); IExtensionsModelFactory pluginFactory = pluginModel.getFactory(); // The workspace extensions are not loaded by default, so manually copy them. IPluginModelBase existingPluginModel = PluginRegistry.findModel(project); if (existingPluginModel != null) { IExtensions extensions = existingPluginModel.getExtensions(); if (extensions != null) { for (IPluginExtension pluginExtension : extensions.getExtensions()) { pluginModel.getExtensions().add(copyPluginExtensions(pluginFactory, pluginExtension)); } } } // Remove existing generated extensions. for (IPluginExtension extension : Lists.newArrayList(pluginModel.getExtensions().getExtensions())) { if ("org.eclipse.emf.ecore.generated_package".equals(extension.getPoint())) { pluginModel.getExtensions().remove(extension); } if ("org.eclipse.emf.ecore.extension_parser".equals(extension.getPoint())) { pluginModel.getExtensions().remove(extension); } if ("org.archstudio.dblgen.processedSchema".equals(extension.getPoint())) { pluginModel.getExtensions().remove(extension); } } // Add the generated package extensions. for (GenPackage genPackage : genModel.getGenPackages()) { // Only generate code for the schema in this project. if (namedSchemaRecords.get(projectName).contains(genPackage.getNSURI())) { String nsURI = genPackage.getNSURI(); String packageClassName = "" + genPackage.getBasePackage() + "." + genPackage.getPackageName() + "." + genPackage.getPackageInterfaceName(); IPluginExtension extension = pluginModel.createExtension(); extension.setPoint("org.eclipse.emf.ecore.generated_package"); IPluginElement element = pluginModel.createElement(extension); element.setName("package"); element.setAttribute("uri", nsURI); element.setAttribute("class", packageClassName); extension.add(element); pluginModel.getExtensions().add(extension); } } // Add an entry for each processed schema. for (String nsUri : namedSchemaRecords.get(projectName)) { SchemaRecord schemaRecord = schemaRecords.get(nsUri); IPluginExtension extension = pluginModel.createExtension(); extension.setPoint("org.archstudio.dblgen.processedSchema"); IPluginElement element = pluginModel.createElement(extension); element.setName("Schema"); element.setAttribute("nsURI", nsUri); if (schemaRecord.schemaPath != null) { element.setAttribute("file", schemaRecord.schemaPath); } if (schemaRecord.schemaUrl != null) { element.setAttribute("url", schemaRecord.schemaUrl); } extension.add(element); pluginModel.getExtensions().add(extension); } // Save plug-in model. pluginModel.save(); // Format generated files. CodeGeneration.formatCode(project); SortManifests.sortManifest(project); } catch (Exception e) { e.printStackTrace(); statusList.add(new DataBindingGenerationStatus(null, Status.FAILURE, "Error processing schema: " + e.getMessage(), e)); return statusList; } return statusList; } }