/*******************************************************************************
* Copyright (c) 2015-2016 Obeo, Inria
* 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:
* William Piers <william.piers@obeo.fr>
* Philippe Merle <philippe.merle@inria.fr>
*******************************************************************************/
package org.occiware.clouddesigner.occi.emfgen.ui.popup.actions;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.codegen.ecore.genmodel.GenModel;
import org.eclipse.emf.codegen.ecore.genmodel.GenPackage;
import org.eclipse.emf.codegen.ecore.genmodel.presentation.GeneratorUIUtil;
import org.eclipse.emf.codegen.ecore.genmodel.util.GenModelUtil;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.Diagnostician;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ocl.pivot.utilities.LabelUtil;
import org.eclipse.pde.internal.core.project.PDEProject;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IActionDelegate;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.occiware.clouddesigner.occi.Extension;
import org.occiware.clouddesigner.occi.OCCIRegistry;
import org.occiware.clouddesigner.occi.emfgen.ConverterUtils;
import org.occiware.clouddesigner.occi.emfgen.OCCIExtension2Ecore;
public class ConvertAction implements IObjectActionDelegate {
private static final String ECORE_PLATFORM_URI = "platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore";
private static final String CORE_GEN_PACKAGE_URI = "platform:/plugin/org.occiware.clouddesigner.occi/model/OCCI.genmodel";
private ISelection selection;
private ResourceSet resourceSet = new ResourceSetImpl();
private Shell shell = PlatformUI.getWorkbench().getDisplay().getActiveShell();;
/**
* Constructor for Action1.
*/
public ConvertAction() {
super();
}
/**
* @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
*/
@Override
public void setActivePart(IAction action, IWorkbenchPart targetPart) {
}
/**
* @see IActionDelegate#run(IAction)
*/
@Override
public void run(IAction action) {
IFile occieFile = (IFile) ((IStructuredSelection) selection).getFirstElement();
try {
EPackage.Registry.INSTANCE.put(ECORE_PLATFORM_URI, EcorePackage.eINSTANCE);
resourceSet = new ResourceSetImpl();
Extension ext = (Extension) ConverterUtils.getRootElement(resourceSet,
"file:" + occieFile.getLocation().toString());
Map<Object, Object> validationContext = LabelUtil.createDefaultContext(Diagnostician.INSTANCE);
BasicDiagnostic diagnostics = Diagnostician.INSTANCE.createDefaultDiagnostic(ext);
if (!Diagnostician.INSTANCE.validate(ext, diagnostics, validationContext)) {
StringBuilder message = null;
for (Diagnostic diagnostic : diagnostics.getChildren()) {
if (message == null) {
message = new StringBuilder();
} else {
message.append("\n");
}
message.append(diagnostic.getMessage());
}
if (message != null) {
MessageDialog.openError(shell, "Invalid Extension", message.toString());
return;
}
}
// set a base package if necessary
String basePackage = "";
String projectName = occieFile.getProject().getName();
String extensionName = ext.getName();
if (projectName.toLowerCase().endsWith(extensionName.toLowerCase())
&& projectName.length() > extensionName.length()) {
basePackage = projectName.substring(0, projectName.length() - (extensionName.length() + 1))
.toLowerCase();
}
try {
generateEMFModels(ext,
occieFile,
basePackage);
} catch (IllegalArgumentException e) {
MessageDialog.openError(shell, "Invalid Extension", e.getMessage());
return;
}
occieFile.getParent().refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
generateEMFCode(occieFile.getLocation().removeFileExtension().addFileExtension("genmodel").toString());
IFile build = PDEProject.getBuildProperties(occieFile.getProject());
if(!build.exists()) {
String buildContent = "bin.includes = .,\\\n model/,\\\n META-INF/,\\\n plugin.xml,\\\n plugin.properties\njars.compile.order = .\nsource.. = src-gen/\noutput.. = bin/\n";
build.setContents(new ByteArrayInputStream(buildContent.getBytes()), true, false,
new NullProgressMonitor());
}
} catch (InvocationTargetException e) {
Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));
} catch (IOException e) {
Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));
} catch (InterruptedException e) {
Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));
} catch (CoreException e) {
Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));
}
}
/**
* @see IActionDelegate#selectionChanged(IAction, ISelection)
*/
@Override
public void selectionChanged(IAction action, ISelection selection) {
this.selection = selection;
}
private void generateEMFModels(Extension ext, IFile occieFile, String basePackage) throws IOException {
/*
* OCCIE => Ecore conversion
*/
EPackage ePackage = new OCCIExtension2Ecore().convertExtension(ext);
resourceSet.getPackageRegistry().put(ePackage.getNsURI(), ePackage);
ConverterUtils.persistMetamodel(resourceSet, ePackage, occieFile.getLocation().removeFileExtension().addFileExtension("ecore").toString());
// Reset the URI of the generated EPackage in order to have related href when saving the genmodel file.
ePackage.eResource().setURI(URI.createURI(occieFile.getName().replaceAll(".occie", ".ecore")));
/*
* Fetching ext genmodels
*/
Collection<GenPackage> usedPackages = new ArrayList<GenPackage>();
for (Extension extension : ext.getImport()) {
if (!extension.getName().equals("core")) {
String extensionFileUri = OCCIRegistry.getInstance().getFileURI(extension.getScheme());
GenModel genModel = (GenModel) resourceSet
.getResource(
URI.createURI(
extensionFileUri.replaceAll(".occie", ".genmodel")),
true)
.getContents().get(0);
usedPackages.add(genModel.getGenPackages().get(0));
}
}
/*
* Create genmodel
*/
GenPackage coreGenPackage = (GenPackage) ConverterUtils.getRootElement(resourceSet, CORE_GEN_PACKAGE_URI)
.eContents().get(1);
usedPackages.add(coreGenPackage);
GenUtils.createGenModel(ePackage, occieFile.getLocation().removeFileExtension().addFileExtension("ecore").toString(), basePackage, usedPackages);
}
/**
* TODO merge monitor
*/
private void generateEMFCode(String genModelPath) throws InvocationTargetException, InterruptedException {
/*
* Generate model & edit
*/
List<URI> uris = new ArrayList<URI>();
uris.add(URI.createFileURI(genModelPath));
List<GenModel> genModels = GeneratorUIUtil.loadGenModels(new NullProgressMonitor(), uris, shell);
GeneratorUIUtil.GeneratorOperation editOp = new GeneratorUIUtil.GeneratorOperation(shell);
editOp.addGeneratorAndArguments(GenModelUtil.createGenerator(genModels.get(0)), genModels.get(0),
"org.eclipse.emf.codegen.ecore.genmodel.generator.EditProject", "Edit");
editOp.addGeneratorAndArguments(GenModelUtil.createGenerator(genModels.get(0)), genModels.get(0),
"org.eclipse.emf.codegen.ecore.genmodel.generator.ModelProject", "Model");
ProgressMonitorDialog progressMonitorDialog = new ProgressMonitorDialog(shell);
progressMonitorDialog.run(true, true, editOp);
}
}