/* * Copyright (c) 2002 No Magic, Inc. All Rights Reserved. */ package com.nomagic.magicdraw.examples.csharpproperty; import com.nomagic.actions.AMConfigurator; import com.nomagic.actions.ActionsManager; import com.nomagic.magicdraw.actions.ActionsConfiguratorsManager; import com.nomagic.magicdraw.actions.BrowserContextAMConfigurator; import com.nomagic.magicdraw.actions.MDActionsCategory; import com.nomagic.magicdraw.core.Project; import com.nomagic.magicdraw.openapi.uml.ModelElementsManager; import com.nomagic.magicdraw.openapi.uml.ReadOnlyElementException; import com.nomagic.magicdraw.openapi.uml.SessionManager; import com.nomagic.magicdraw.plugins.Plugin; import com.nomagic.magicdraw.ui.browser.Node; import com.nomagic.magicdraw.ui.browser.Tree; import com.nomagic.magicdraw.ui.browser.actions.DefaultBrowserAction; import com.nomagic.uml2.UML2Constants; import com.nomagic.uml2.ext.jmi.helpers.ModelHelper; import com.nomagic.uml2.ext.jmi.helpers.StereotypesHelper; import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.*; import com.nomagic.uml2.ext.magicdraw.mdprofiles.Profile; import com.nomagic.uml2.ext.magicdraw.mdprofiles.Stereotype; import com.nomagic.uml2.impl.ElementsFactory; import java.awt.event.ActionEvent; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; /** * Plugin for generating C# property for the attributes. * Creates new operation-property for every attribute and sets specific stereotype and tagged values. * Such operation will be mapped into C# property on C# code generation. * @author Nerijus Jankevicius */ public class CSharpPropertyGenerator extends Plugin { /** * Action, that do all the work. */ private GenerateAction generateAction; /** * Initializing the plugin. */ @Override public void init() { generateAction = new GenerateAction(); // register action as containment tree context action. ActionsConfiguratorsManager.getInstance().addContainmentBrowserContextConfigurator(new BrowserContextAMConfigurator() { @Override public void configure(ActionsManager manager, Tree browser) { if (generateAction.canBeUsed(browser)) { MDActionsCategory category = new MDActionsCategory(); category.addAction(generateAction); manager.addCategory(category); } } @Override public int getPriority() { return AMConfigurator.MEDIUM_PRIORITY; } }); } /** * Action that generates accessors. */ static class GenerateAction extends DefaultBrowserAction { /** * Constructs action. */ public GenerateAction() { super("", "Create C# Property", null, null); } /** * Performs accessors generating. * @param evt the action event. */ @Override public void actionPerformed(ActionEvent evt) { Tree tree = getTree(); if (tree != null) { Collection properties = collectAttributes(tree); if (!properties.isEmpty()) { Project project = Project.getProject(properties.iterator().next()); // new session must be created. // All actions until session closing will be added into one command in CommandHistory. SessionManager.getInstance().createSession(project, "Create C# Properties"); try // because ReadOnlyElementException can occur. { // perform generation action for every selected attribute. // all created operations add into collection and later add into classifiers. for (Property property : properties) { generateProperty(property); } } catch (ReadOnlyElementException e) { e.printStackTrace(); } // close edit session (execute all commands). SessionManager.getInstance().closeSession(project); } } } /** * Creates accessors for given attribute. * @param at the attribute. */ public void generateProperty(Property at) throws ReadOnlyElementException { Classifier parent = (Classifier) at.getOwner(); // name of the C# Property. attribute name + "Property" String propertyName = at.getName() + "Property"; Project project = Project.getProject(at); ElementsFactory elementsFactory = project.getElementsFactory(); Operation op = elementsFactory.createOperationInstance(); op.setName(propertyName); // set specific stereotype and tagged values. Stereotype stereotype = StereotypesHelper.getStereotype(project, UML2Constants.UML_SETTER_STEREOTYPE, (Profile) null); if (stereotype != null) { StereotypesHelper.addStereotype(op, stereotype); StereotypesHelper.setStereotypePropertyValue(op, stereotype, UML2Constants.GETTER_SETTER_FOR_ATTRIBUTE, at); } // create return parameter. Parameter par = elementsFactory.createParameterInstance(); par.setType(at.getType()); par.setDirection(ParameterDirectionKindEnum.RETURN); // add parameter into operation. par.setOwner(op); ModelElementsManager.getInstance().addElement(par, op); boolean exists = false; if (parent != null) { for (Iterator opIterator = ModelHelper.operations(parent); opIterator.hasNext() && !exists; ) { exists = ModelHelper.isOperationEqual(opIterator.next(), op); } } if (exists) { op.dispose(); } else { //noinspection ConstantConditions ModelElementsManager.getInstance().addElement(op, parent); } } /** * Action can be used only if there are selected classifiers in the browser. */ public boolean canBeUsed(Tree tree) { return collectAttributes(tree).size() > 0; } /** * Updates menu item. */ @Override public void updateState() { boolean enable = false; Tree tree = getTree(); if (tree != null) { enable = canBeUsed(tree); } setEnabled(enable); } /** * Checks all selected browser nodes and collects only classifier interfaces. */ public Collection collectAttributes(Tree tree) { Collection attributes = new ArrayList<>(); // iterate selected nodes. for (Node node : Arrays.asList(tree.getSelectedNodes())) { // checks type of the node, because can be selected and code engineering sets. final Object userObject = node.getUserObject(); if (userObject instanceof Element) { Element element = (Element) userObject; // we need only attributes. // if selected classifier, add all attributes. if (element instanceof Classifier) { for (Iterator attr = ModelHelper.attributes((Classifier) element); attr.hasNext(); ) { attributes.add(attr.next()); } } else if (element instanceof Property) { attributes.add((Property) element); } } } return attributes; } } /** * Return true always, because this plugin does not have any close specific actions. */ @Override public boolean close() { return true; } /** * @see com.nomagic.magicdraw.plugins.Plugin#isSupported() */ @Override public boolean isSupported() { return true; } }