| /******************************************************************************* |
| * 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; |
| } |
| } |