package org.eclipse.emf.mwe2.ecore; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import org.eclipse.emf.codegen.ecore.generator.Generator; import org.eclipse.emf.codegen.ecore.generator.GeneratorAdapterFactory; import org.eclipse.emf.codegen.ecore.genmodel.GenBase; import org.eclipse.emf.codegen.ecore.genmodel.GenModel; import org.eclipse.emf.codegen.ecore.genmodel.GenModelPackage; import org.eclipse.emf.codegen.ecore.genmodel.generator.GenBaseGeneratorAdapter; import org.eclipse.emf.codegen.ecore.genmodel.generator.GenModelGeneratorAdapter; import org.eclipse.emf.codegen.merge.java.JControlModel; import org.eclipse.emf.codegen.util.ImportManager; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.common.util.BasicMonitor; import org.eclipse.emf.common.util.Diagnostic; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.common.util.WrappedException; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.URIConverter; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.mwe.utils.GenModelHelper; import org.eclipse.emf.mwe2.runtime.Mandatory; import org.eclipse.emf.mwe2.runtime.workflow.IWorkflowComponent; import org.eclipse.emf.mwe2.runtime.workflow.IWorkflowContext; import com.google.common.base.Function; public class EcoreGenerator implements IWorkflowComponent { private static Logger log = Logger.getLogger(EcoreGenerator.class); static { EcorePackage.eINSTANCE.getEFactoryInstance(); GenModelPackage.eINSTANCE.getEFactoryInstance(); } private boolean generateEdit = false; private boolean generateEditor = false; private boolean generateCustomClasses = false; private String lineDelimiter = System.getProperty("line.separator"); /** * @since 2.7 */ public String getLineDelimiter() { return lineDelimiter; } /** * @since 2.7 */ public void setLineDelimiter(String lineDelimiter) { this.lineDelimiter = lineDelimiter; } protected List<String> srcPaths = new ArrayList<String>(); private String genModel; private ResourceSet resourceSet; public void setGenerateEdit(boolean generateEdit) { this.generateEdit = generateEdit; } public void setGenerateEditor(boolean generateEditor) { this.generateEditor = generateEditor; } public void setGenerateCustomClasses(boolean generateCustomClasses) { this.generateCustomClasses = generateCustomClasses; } @Mandatory public void addSrcPath(String srcPath) { this.srcPaths.add(srcPath); } @Mandatory public void setGenModel(String genModel) { this.genModel = genModel; } public void setResourceSet(ResourceSet resourceSet) { this.resourceSet = resourceSet; } public void preInvoke() { getResourceSet().getResource(URI.createURI(genModel), true); } public void postInvoke() { } protected GenModelHelper createGenModelSetup() { return new GenModelHelper(); } public void invoke(IWorkflowContext ctx) { ResourceSet resSet = getResourceSet(); Resource resource = resSet.getResource(URI.createURI(genModel), true); final GenModel genModel = (GenModel) resource.getContents().get(0); genModel.setCanGenerate(true); genModel.reconcile(); createGenModelSetup().registerGenModel(genModel); Generator generator = new Generator() { @Override public JControlModel getJControlModel() { return new JControlModel(){ @Override public boolean canMerge() { return false; } }; } }; log.info("generating EMF code for "+this.genModel); generator.getAdapterFactoryDescriptorRegistry().addDescriptor(GenModelPackage.eNS_URI, new GeneratorAdapterDescriptor(getTypeMapper(), getLineDelimiter())); generator.setInput(genModel); Diagnostic diagnostic = generator.generate(genModel, GenBaseGeneratorAdapter.MODEL_PROJECT_TYPE, new BasicMonitor()); if (diagnostic.getSeverity() != Diagnostic.OK) log.info(diagnostic); if (generateEdit) { Diagnostic editDiag = generator.generate(genModel, GenBaseGeneratorAdapter.EDIT_PROJECT_TYPE, new BasicMonitor()); if (editDiag.getSeverity() != Diagnostic.OK) log.info(editDiag); } if (generateEditor) { Diagnostic editorDiag = generator.generate(genModel, GenBaseGeneratorAdapter.EDITOR_PROJECT_TYPE, new BasicMonitor()); if (editorDiag.getSeverity() != Diagnostic.OK) log.info(editorDiag); } } private ResourceSet getResourceSet() { return resourceSet == null ? new ResourceSetImpl() : resourceSet; } protected Function<String, String> getTypeMapper() { return new mapper(); } protected final class mapper implements Function<String, String> { public String apply(String from) { if (from.startsWith("org.eclipse.emf.ecore")) return null; String customClassName = from+"Custom"; String fromPath = from.replace('.', '/'); for(String srcPath: srcPaths) { URI createURI = URI.createURI(srcPath+"/"+fromPath+"Custom.java"); if (URIConverter.INSTANCE.exists(createURI, null)) { return customClassName; } if (from.endsWith("Impl") && generateCustomClasses) { generate(from,customClassName,createURI); return customClassName; } } if (getClass().getClassLoader().getResourceAsStream(fromPath + "Custom.class") != null) { return customClassName; } return null; } } public void generate(String from,String customClassName, URI path) { StringBuilder sb =new StringBuilder(); sb.append(copyright()).append("\n"); int lastIndexOfDot = customClassName.lastIndexOf('.'); sb.append("package ").append(customClassName.substring(0, lastIndexOfDot)).append(";\n\n\n"); sb.append("public class ").append(customClassName.substring(lastIndexOfDot+1)).append(" extends ").append(from).append(" {\n\n"); sb.append("}\n"); try { OutputStream stream = URIConverter.INSTANCE.createOutputStream(path); stream.write(sb.toString().getBytes()); stream.close(); } catch (IOException e) { throw new WrappedException(e); } } protected String copyright() { return "/*******************************************************************************\n"+ "* Copyright (c) 2008 - 2010 itemis AG (http://www.itemis.eu) and others.\n"+ "* All rights reserved. This program and the accompanying materials\n"+ "* are made available under the terms of the Eclipse Public License v1.0\n"+ "* which accompanies this distribution, and is available at\n"+ "* http://www.eclipse.org/legal/epl-v10.html\n"+ "*******************************************************************************/"; } /** * @author Sven Efftinge - Initial contribution and API */ protected static class GeneratorAdapterDescriptor extends CvsIdFilteringGeneratorAdapterFactoryDescriptor { /** * @author Sebastian Zarnekow - Initial contribution and API */ private final class CustomImplAwareGeneratorAdapterFactory extends IdFilteringGenModelGeneratorAdapterFactory { @Override public Adapter createGenClassAdapter() { return new IdFilteringGenClassAdapter(this) { @Override protected void createImportManager(String packageName, String className) { importManager = new ImportManagerHack(packageName, typeMapper); importManager.addMasterImport(packageName, className); if (generatingObject != null) ((GenBase) generatingObject).getGenModel().setImportManager(importManager); } }; } @Override public Adapter createGenEnumAdapter() { return new IdFilteringGenEnumAdapter(this) { @Override protected void createImportManager(String packageName, String className) { importManager = new ImportManagerHack(packageName, typeMapper); importManager.addMasterImport(packageName, className); if (generatingObject != null) ((GenBase) generatingObject).getGenModel().setImportManager(importManager); } }; } @Override public Adapter createGenModelAdapter() { if (genModelGeneratorAdapter == null) { genModelGeneratorAdapter = new GenModelGeneratorAdapter(this) { @Override protected void createImportManager(String packageName, String className) { importManager = new ImportManagerHack(packageName, typeMapper); importManager.addMasterImport(packageName, className); if (generatingObject != null) ((GenBase) generatingObject).getGenModel().setImportManager( importManager); } }; } return genModelGeneratorAdapter; } @Override public Adapter createGenPackageAdapter() { return new IdFilteringGenPackageAdapter(this) { @Override protected void createImportManager(String packageName, String className) { importManager = new ImportManagerHack(packageName, typeMapper); importManager.addMasterImport(packageName, className); if (generatingObject != null) ((GenBase) generatingObject).getGenModel().setImportManager(importManager); } }; } } private Function<String, String> typeMapper; protected GeneratorAdapterDescriptor(Function<String,String> typeMapper) { this.typeMapper = typeMapper; } public GeneratorAdapterDescriptor(Function<String,String> typeMapper, String lineDelimiter) { super(lineDelimiter); this.typeMapper = typeMapper; } @Override public GeneratorAdapterFactory createAdapterFactory() { return new CustomImplAwareGeneratorAdapterFactory(); } } protected static class ImportManagerHack extends ImportManager { private Function<String, String> typeMapper; public ImportManagerHack(String compilationUnitPackage, Function<String,String> typeMapper) { super(compilationUnitPackage); this.typeMapper = typeMapper; } @Override public String getImportedName(String qualifiedName, boolean autoImport) { String mapped = typeMapper.apply(qualifiedName); if (mapped != null) { log.debug("mapping " + qualifiedName + " to " + mapped); return super.getImportedName(mapped, autoImport); } else return super.getImportedName(qualifiedName, autoImport); } } }