blob: 8509ccec72948ab6815caf6e3a6c7c21b3f95b01 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2020 CEA LIST
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Ansgar Radermacher - Initial API and implementation
*******************************************************************************/
package org.eclipse.papyrus.designer.languages.common.codegen.ui.handlers;
import java.util.regex.Pattern;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.papyrus.designer.deployment.tools.DepUtils;
import org.eclipse.papyrus.designer.languages.common.base.ClassUtils;
import org.eclipse.papyrus.designer.languages.common.codegen.ui.ChooseGenerator;
import org.eclipse.papyrus.designer.languages.common.extensionpoints.ILangCodegen;
import org.eclipse.papyrus.designer.languages.common.extensionpoints.LanguageCodegen;
import org.eclipse.papyrus.designer.languages.common.profile.Codegen.GeneratorHint;
import org.eclipse.papyrus.uml.diagram.common.handlers.CmdHandler;
import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.PackageableElement;
/**
* Common code generation handler
*/
public class GenerateCodeHandler extends CmdHandler {
// ------------------------------------------------------------------------
// Execution
// ------------------------------------------------------------------------
/**
* Name for stereotypes to avoid. Use strings instead of names of static profile
* to avoid dependencies to transformation and deployment profile
*/
private static final String DEPLOYMENT_PLAN = "Deployment::DeploymentPlan"; //$NON-NLS-1$
private static final String EXECUTE_TRAFO_CHAIN = "Transformation::ExecuteTrafoChain"; //$NON-NLS-1$
@Override
public boolean isEnabled() {
updateSelectedEObject();
if (selectedEObject instanceof Package || selectedEObject instanceof Classifier) {
boolean deploymentPlanOrTrafoChain =
StereotypeUtil.isApplied((Element) selectedEObject, EXECUTE_TRAFO_CHAIN) ||
StereotypeUtil.isApplied((Element) selectedEObject, DEPLOYMENT_PLAN);
if (!deploymentPlanOrTrafoChain) {
URI uri = selectedEObject.eResource().getURI();
// URIConverter uriConverter = resource.getResourceSet().getURIConverter();
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
if (uri.segmentCount() < 2) {
return false;
}
IProject modelProject = root.getProject(URI.decode(uri.segment(1)));
return modelProject.exists();
}
}
return false;
}
/**
* Generate code for a passed packageable element and the elements required by it (in the sense of #included statements)
*
* @param codeGen
* a code generator
* @param genProject
* the project to write into
* @param pe
* the element that should be generated
* @param alreadyHandled
* list of packageable elements for which code has already been generated.
* @param recurse
* if the passed packageableElement is a package, generate code for its contents (recursively).
*/
public void generate(ILangCodegen codeGen, IProject genProject, PackageableElement pe, EList<PackageableElement> alreadyHandled, boolean recurse) {
alreadyHandled.add(pe);
// Eventual refresh is done in createPackageableElement
codeGen.generateCode(genProject, pe, null);
// if recursion is active, go into all sub-elements
if (pe instanceof Package && recurse) {
for (PackageableElement subPe : ((Package) pe).getPackagedElements()) {
if (!alreadyHandled.contains(subPe)) {
generate(codeGen, genProject, subPe, alreadyHandled, recurse);
}
}
}
// add required classifiers
if (pe instanceof Classifier) {
EList<Classifier> requiredClassifiers = ClassUtils.requiredClassifiers((Classifier) pe);
for (Classifier requiredClassifier : requiredClassifiers) {
if (!alreadyHandled.contains(requiredClassifier)) {
generate(codeGen, genProject, requiredClassifier, alreadyHandled, false);
}
}
}
// owning package is required by generated code.
Package owningPackage = pe.getNearestPackage();
if ((owningPackage != null) && (owningPackage != pe)) {
if (!alreadyHandled.contains(owningPackage)) {
generate(codeGen, genProject, owningPackage, alreadyHandled, false);
}
}
}
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
if (selectedEObject instanceof PackageableElement) {
PackageableElement pe = (PackageableElement) selectedEObject;
GeneratorHint hint = DepUtils.getGeneratorHintFromElement(pe);
ILangCodegen codeGen = null;
if (hint == null) {
codeGen = ChooseGenerator.choose(Pattern.compile(".*"), pe); //$NON-NLS-1$
}
else {
codeGen = LanguageCodegen.getGenerator(hint.getLanguage().getBase_Class().getName(), hint.getGeneratorID());
}
if (codeGen != null) {
IProject genProject = codeGen.getTargetProject(pe, true);
generate(codeGen, genProject, pe, new BasicEList<PackageableElement>(), true);
}
}
return null;
}
}