package com.sap.furcas.ide.projectwizard.util; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.emf.codegen.ecore.generator.Generator; import org.eclipse.emf.codegen.ecore.generator.GeneratorAdapterFactory; 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.GenModelGeneratorAdapterFactory; import org.eclipse.emf.codegen.ecore.genmodel.presentation.GeneratorUIUtil; import org.eclipse.emf.common.util.BasicMonitor; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.ENamedElement; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; 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.xmi.XMLResource; import org.eclipse.swt.widgets.Shell; import com.sap.furcas.ide.projectwizard.wizards.FurcasWizard; /** * This class is able to generate a java project with a fresh .ecore metamodel. The metamodel already contains a class. The name * of this class is chosen by the user of the wizard. It also creates a .genmodel file for the metamodel and generates the model * code for it. So in the end there should be a complete metamodel project with successfully building java classes. This class is * only called when the user choosen to connect his language project to a new metamodel! * <p> * The class gets help from the class {@link WizardProjectHelper}, which generates the fundamental parts of the project. * * @author Frederik Petersen (D054528) * */ public class CreateMMProject { /** * Keeps all the user input */ protected static ProjectInfo pi; /** * Is used to get user input, shell etc. */ protected static FurcasWizard wizard; /** * The singleton instance of the EcorePackage. It's used in the process of creating a new EPackage. */ protected static EcorePackage ecorePackage = EcorePackage.eINSTANCE; /** * The EcoreFactory of the singleton instance of the EcorePackage. */ protected static EcoreFactory ecoreFactory = ecorePackage.getEcoreFactory(); /** * This shell represents the wizard window. */ protected static Shell shell; /** * The progressmonitor used for all the different creation processes in this class. */ protected static IProgressMonitor progressMonitor; /** * This class is called in the <code>doAdditional()</code> method of the {@link}FurcasWizard to start the generation of the * metamodel project. * * @param wiz * See global variable <code>wizard</code> for information * @throws CodeGenerationException */ public static void create(FurcasWizard wiz, IProgressMonitor monitor, ProjectInfo pInfo) throws CodeGenerationException { pi = pInfo; wizard = wiz; progressMonitor = monitor; List<String> srcFolders = new ArrayList<String>(); srcFolders.add("src"); List<String> nonSrcFolders = new ArrayList<String>(); nonSrcFolders.add("model"); shell = wizard.getShell(); WizardProjectHelper.createPlugInProject(pi, srcFolders, nonSrcFolders, null, progressMonitor, true); createNewModel(); } /** * Creates the metamodels .ecore and .genmodel files. It also creates the first class in the metamodel. * * @throws CodeGenerationException */ protected static void createNewModel() throws CodeGenerationException { ResourceSet resourceSet = new ResourceSetImpl(); resourceSet.getURIConverter().getURIMap().putAll(EcorePlugin.computePlatformURIMap()); URI fileURI = getModelURI(pi); Resource resource = resourceSet.createResource(fileURI); EPackage ePackage = createEPackage(); addFirstClass(ePackage); resource.getContents().add(ePackage); Map<Object, Object> options = new HashMap<Object, Object>(); options.put(XMLResource.OPTION_ENCODING, "UTF-8"); try { resource.save(options); } catch (IOException e) { throw new CodeGenerationException("Error while saving resource for the new model", e.getCause()); } IFile file = createGenmodelFile(pi); URI newURI = URI.createPlatformResourceURI(file.getProject().getName() + "/" + file.getProjectRelativePath().toString(), true); generateModelCode(newURI); } private static IFile createGenmodelFile(ProjectInfo pi) throws CodeGenerationException { IFile file = null; IWorkspace workspace = ResourcesPlugin.getWorkspace(); IProject project = workspace.getRoot().getProject(pi.getProjectName() + ".metamodel"); file = WizardProjectHelper.createGenmodel(progressMonitor, project, pi); return file; } private static void addFirstClass(EPackage ePackage) throws CodeGenerationException { EClass eClass = ecoreFactory.createEClass(); eClass.setName(pi.getClassName()); ePackage.getEClassifiers().add(eClass); } private static URI getModelURI(ProjectInfo pi) { String mmprojectpath = pi.getProjectName() + ".metamodel/model/" + CreateProject.capitalizeFirstChar(pi.getLanguageName()) + ".ecore"; URI fileURI = URI.createPlatformResourceURI(mmprojectpath, true); return fileURI; } private static EPackage createEPackage() throws CodeGenerationException { EPackage ePackage; EClass eClass = (EClass) ecorePackage.getEClassifier("EPackage"); EObject rootObject = ecoreFactory.create(eClass); if (rootObject instanceof ENamedElement && rootObject instanceof EPackage) { ((ENamedElement) rootObject).setName(CreateProject.capitalizeFirstChar(pi.getLanguageName())); ePackage = (EPackage) rootObject; ePackage.setNsPrefix(pi.getLanguageName()); ePackage.setNsURI(pi.getNsURI()); } else { throw new CodeGenerationException("Failed to create the new Model!"); } return ePackage; } /** * Generates the model code for the model. As one would be clicking Generate->Generate Model code in the UI, when .genmodel is * loaded in workspace. * * @param uri * nsURI of the model. */ private static void generateModelCode(URI uri) { List<URI> uris = new ArrayList<URI>(); uris.add(uri); List<GenModel> gms = GeneratorUIUtil.loadGenModels(progressMonitor, uris, shell); GeneratorAdapterFactory.Descriptor.Registry.INSTANCE.addDescriptor(GenModelPackage.eNS_URI, GenModelGeneratorAdapterFactory.DESCRIPTOR); Generator generator = new Generator(); generator.setInput(gms.get(0)); generator.generate(gms.get(0), GenBaseGeneratorAdapter.MODEL_PROJECT_TYPE, new BasicMonitor.Printing(System.out)); } }