/******************************************************************************* * Copyright (c) 2013 Obeo. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Obeo - initial API and implementation *******************************************************************************/ package org.eclipselabs.emf.loophole.internal.generator; import java.io.IOException; import java.io.OutputStream; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.eclipse.emf.codegen.ecore.generator.GeneratorAdapterFactory; import org.eclipse.emf.codegen.ecore.genmodel.GenBase; import org.eclipse.emf.codegen.ecore.genmodel.GenClass; import org.eclipse.emf.codegen.ecore.genmodel.generator.GenClassGeneratorAdapter; import org.eclipse.emf.codegen.ecore.genmodel.generator.GenEnumGeneratorAdapter; import org.eclipse.emf.codegen.ecore.genmodel.generator.GenModelGeneratorAdapter; import org.eclipse.emf.codegen.ecore.genmodel.generator.GenModelGeneratorAdapterFactory; import org.eclipse.emf.codegen.ecore.genmodel.generator.GenPackageGeneratorAdapter; import org.eclipse.emf.codegen.util.ImportManager; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.common.util.WrappedException; import org.eclipse.emf.ecore.resource.URIConverter; import org.eclipselabs.emf.loophole.internal.model.GenGapModel; import org.eclipselabs.emf.loophole.internal.model.GenGapPackage; /** * @author Mikaël Barbero - Remove any MWE dependencies */ public class LoopholeGeneratorAdapterDescriptor implements GeneratorAdapterFactory.Descriptor { private final GenGapModel genGapModel; public LoopholeGeneratorAdapterDescriptor(GenGapModel genGapModel) { this.genGapModel = genGapModel; } protected Map<String, String> createModelMapper(GenGapModel genGapModel) { Map<String, String> qNameToCustomQName = new HashMap<String, String>(); for(GenGapPackage genGapPackage: genGapModel.getGenGapPackages()) { for (GenClass genClass : genGapPackage.getGenPackage().getGenClasses()) { qNameToCustomQName.put( genClass.getQualifiedClassName(), genGapPackage.getCustomQualifiedClassName(genClass)); } } return Collections.unmodifiableMap(qNameToCustomQName); } protected Map<String, String> createEditMapper(GenGapModel genGapModel) { Map<String, String> qNameToCustomQName = new HashMap<String, String>(); for(GenGapPackage genGapPackage: genGapModel.getGenGapPackages()) { for (GenClass genClass : genGapPackage.getGenPackage().getGenClasses()) { qNameToCustomQName.put( genClass.getQualifiedProviderClassName(), genGapPackage.getCustomQualifiedProviderClassName(genClass)); } } return Collections.unmodifiableMap(qNameToCustomQName); } public GeneratorAdapterFactory createAdapterFactory() { return new LoopholeGenModelGeneratorAdapterFactory(); } protected void generateCustomClass(String className, String customClassName, URI path) { StringBuilder sb =new StringBuilder(); sb.append("/**\n"); if (genGapModel.getGenModel().getCopyrightText() != null) { sb.append(genGapModel.getGenModel().getCopyright(" *")).append("\n"); } sb.append(" */\n"); int lastIndexOfDot = className.lastIndexOf('.'); int customLastIndexOfDot = customClassName.lastIndexOf('.'); sb.append("package ").append(customClassName.substring(0, customLastIndexOfDot)).append(";\n\n"); sb.append("import ").append(className).append(";\n\n"); sb.append("public class ").append(customClassName.substring(customLastIndexOfDot+1)).append(" extends ").append(className.substring(lastIndexOfDot+1)).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 void generateCustomProvider(String className, String customClassName, URI path) { StringBuilder sb =new StringBuilder(); sb.append("/**\n"); if (genGapModel.getGenModel().getCopyrightText() != null) { sb.append(genGapModel.getGenModel().getCopyright(" *")).append("\n"); } sb.append(" */\n"); int lastIndexOfDot = className.lastIndexOf('.'); int customLastIndexOfDot = customClassName.lastIndexOf('.'); sb.append("package ").append(customClassName.substring(0, customLastIndexOfDot)).append(";\n\n"); sb.append("import org.eclipse.emf.common.notify.AdapterFactory;\n"); sb.append("import ").append(className).append(";\n\n"); sb.append("public class ").append(customClassName.substring(customLastIndexOfDot+1)).append(" extends ").append(className.substring(lastIndexOfDot+1)).append(" {\n\n"); sb.append("\tpublic ").append(customClassName.substring(customLastIndexOfDot+1)).append("(AdapterFactory adapterFactory) {\n"); sb.append("\t\tsuper(adapterFactory);\n"); sb.append("\t}\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); } } /** * @author Sebastian Zarnekow - Initial contribution and API * @author Mikaël Barbero - Remove any MWE dependencies */ protected class LoopholeGenModelGeneratorAdapterFactory extends GenModelGeneratorAdapterFactory { private Map<String, String> editQNameToCustomQName; private Map<String, String> modelQNameToCustomQName; @Override public void initialize(Object input) { super.initialize(input); modelQNameToCustomQName = createModelMapper(genGapModel); editQNameToCustomQName = createEditMapper(genGapModel); } @Override public Adapter createGenClassAdapter() { if (genClassGeneratorAdapter == null) { genClassGeneratorAdapter = new GenClassGeneratorAdapter(this) { @Override protected void createImportManager(String packageName, String className) { importManager = new LoopholeImportManager(packageName); importManager.addMasterImport(packageName, className); if (generatingObject != null) ((GenBase) generatingObject).getGenModel().setImportManager(importManager); } }; } return genClassGeneratorAdapter; } @Override public Adapter createGenEnumAdapter() { if (genEnumGeneratorAdapter == null) { genEnumGeneratorAdapter = new GenEnumGeneratorAdapter(this) { @Override protected void createImportManager(String packageName, String className) { importManager = new LoopholeImportManager(packageName); importManager.addMasterImport(packageName, className); if (generatingObject != null) ((GenBase) generatingObject).getGenModel().setImportManager(importManager); } }; } return genEnumGeneratorAdapter; } @Override public Adapter createGenModelAdapter() { if (genModelGeneratorAdapter == null) { genModelGeneratorAdapter = new GenModelGeneratorAdapter(this) { @Override protected void createImportManager(String packageName, String className) { importManager = new LoopholeImportManager(packageName); importManager.addMasterImport(packageName, className); if (generatingObject != null) ((GenBase) generatingObject).getGenModel().setImportManager(importManager); } }; } return genModelGeneratorAdapter; } @Override public Adapter createGenPackageAdapter() { if (genPackageGeneratorAdapter == null) { genPackageGeneratorAdapter = new GenPackageGeneratorAdapter(this) { @Override protected void createImportManager(String packageName, String className) { importManager = new LoopholeImportManager(packageName); importManager.addMasterImport(packageName, className); if (generatingObject != null) ((GenBase) generatingObject).getGenModel().setImportManager(importManager); } /** * {@inheritDoc} * @see org.eclipse.emf.codegen.ecore.genmodel.generator.GenPackageGeneratorAdapter#getJETEmitterDescriptors() */ @Override protected JETEmitterDescriptor[] getJETEmitterDescriptors() { JETEmitterDescriptor[] descriptors = new JETEmitterDescriptor[super.getJETEmitterDescriptors().length]; System.arraycopy(super.getJETEmitterDescriptors(), 0, descriptors, 0, super.getJETEmitterDescriptors().length); for (JETEmitterDescriptor descriptor : descriptors) { if ("org.eclipse.emf.codegen.ecore.templates.edit.ItemProviderAdapterFactory".equals(descriptor.className)) { try { //test if the class is available in a fragment, if not, we are working with an emf version that fixes known bugs. Class<?> gen = Class.forName("org.eclipselabs.emf.loophole.internal.generator.edit.ItemProviderAdapterFactory", false, this.getClass().getClassLoader()); descriptor.className = gen.getName(); } catch (ClassNotFoundException cnfe) { } } } return descriptors; } }; } return genPackageGeneratorAdapter; } protected class LoopholeImportManager extends ImportManager { public LoopholeImportManager(String compilationUnitPackage) { super(compilationUnitPackage); } @Override public String getImportedName(String importQualifiedName, boolean autoImport) { String customImportQualifiedName = getModelImportedName(importQualifiedName); if (customImportQualifiedName == null) { customImportQualifiedName = getEditImportedName(importQualifiedName); } if (customImportQualifiedName != null) { return super.getImportedName(customImportQualifiedName, autoImport); } else { return super.getImportedName(importQualifiedName, autoImport); } } protected String getModelImportedName(String importQualifiedName) { String customImportQualifiedName = modelQNameToCustomQName.get(importQualifiedName); if (customImportQualifiedName != null) { boolean exists = URIConverter.INSTANCE.exists(createURI(genGapModel.getCustomModelDirectory(), customImportQualifiedName), null); if (!exists) { if (genGapModel.isGenerateCustomClasses()) { generateCustomClass(importQualifiedName,customImportQualifiedName,createURI(genGapModel.getCustomModelDirectory(), customImportQualifiedName)); } else { customImportQualifiedName = null; } } } return customImportQualifiedName; } protected String getEditImportedName(String importQualifiedName) { String customImportQualifiedName = editQNameToCustomQName.get(importQualifiedName); if (customImportQualifiedName != null) { boolean exists = URIConverter.INSTANCE.exists(createURI(genGapModel.getCustomEditDirectory(), customImportQualifiedName), null); if (!exists) { if (genGapModel.isGenerateCustomProviders()) { generateCustomProvider(importQualifiedName,customImportQualifiedName,createURI(genGapModel.getCustomEditDirectory(), customImportQualifiedName)); } else { customImportQualifiedName = null; } } } return customImportQualifiedName; } protected URI createURI(String path, String customImportQualifiedName) { return URI.createURI(path+"/"+customImportQualifiedName.replace('.', '/')+".java"); } } } }