/******************************************************************************* * Copyright (c) <2016>, California Institute of Technology ("Caltech"). * U.S. Government sponsorship acknowledged. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * - Neither the name of Caltech nor its operating division, the Jet Propulsion Laboratory, * nor the names of its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ package gov.nasa.jpl.mbee.mdk.api; import com.nomagic.magicdraw.copypaste.CopyPasting; import com.nomagic.magicdraw.core.Application; import com.nomagic.magicdraw.core.Project; import com.nomagic.magicdraw.core.project.ProjectDescriptor; import com.nomagic.magicdraw.core.project.ProjectDescriptorsFactory; import com.nomagic.magicdraw.core.project.ProjectsManager; import com.nomagic.magicdraw.openapi.uml.ModelElementsManager; import com.nomagic.magicdraw.openapi.uml.ReadOnlyElementException; import com.nomagic.magicdraw.openapi.uml.SessionManager; import com.nomagic.uml2.ext.jmi.helpers.ModelHelper; import com.nomagic.uml2.ext.jmi.helpers.StereotypesHelper; import com.nomagic.uml2.ext.magicdraw.classes.mddependencies.Dependency; import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.*; import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Class; import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Package; import com.nomagic.uml2.ext.magicdraw.components.mdbasiccomponents.Component; import com.nomagic.uml2.ext.magicdraw.mdprofiles.Stereotype; import com.nomagic.uml2.impl.ElementsFactory; import gov.nasa.jpl.mbee.mdk.api.incubating.convert.Converters; import gov.nasa.jpl.mbee.mdk.json.ReferenceException; import gov.nasa.jpl.mbee.mdk.util.Utils; import java.io.File; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * This class has functions that uses the MDK api to test the MDK actions. */ public class MagicDrawHelper { private static Project project; private static ElementsFactory ef; /** * Convenience method to ensure that we always have an ElementsFactory available. */ private static void initializeFactory() { if (ef != null) { return; } project = Application.getInstance().getProject(); ef = project.getElementsFactory(); } /***************************************************************************************** * * Project load / close functions * *****************************************************************************************/ public static ProjectDescriptor openProject(File file) throws IOException { return openProject(file.toURI()); } public static ProjectDescriptor openProject(URI uri) throws IOException { final ProjectDescriptor projectDescriptor = ProjectDescriptorsFactory.createProjectDescriptor(uri); if (projectDescriptor == null) { throw new IOException(uri.toString() + " could not generate a project descriptor."); } final ProjectsManager projectsManager = Application.getInstance().getProjectsManager(); projectsManager.loadProject(projectDescriptor, true); final Project project = projectsManager.getActiveProject(); if (project == null) { throw new IOException(uri.toString() + " could not be loaded into MagicDraw."); } return projectDescriptor; } public static void saveProject(String filename) { System.out.println(System.currentTimeMillis()); File file = new File(filename); ProjectDescriptor projectDescriptor = ProjectDescriptorsFactory.createLocalProjectDescriptor(Application.getInstance().getProject(), file); Application.getInstance().getProjectsManager().saveProject(projectDescriptor, false); System.out.println(System.currentTimeMillis()); } public static void closeProject() { Application.getInstance().getProjectsManager().closeProject(); } /***************************************************************************************** * * Session management functions * *****************************************************************************************/ /** * Creates a MagicDraw Session. All changes to be recorded in model programmatically * must occur after a session is opened, and will be recorded when the session is closed. * A cancelled session will cause the changes to be lost. * * @throws IllegalStateException */ public static void createSession() throws IllegalStateException { if (SessionManager.getInstance().isSessionCreated()) { throw new IllegalStateException("Unable to create session: a session is already open."); } SessionManager.getInstance().createSession("Programmatic changes"); initializeFactory(); } /** * Closes an open session, causing all programmatically completed changes in the current * session to be reflected in the model. * * @throws IllegalStateException */ public static void closeSession() throws IllegalStateException { if (!SessionManager.getInstance().isSessionCreated()) { throw new IllegalStateException("Unable to close session: no session has been created to close."); } SessionManager.getInstance().closeSession(); } /** * Cancels an open session, causing all programmatically completed changes in the current * session to be lost and not recorded in the model. * * @throws IllegalStateException */ public static void cancelSession() throws IllegalStateException { if (!SessionManager.getInstance().isSessionCreated()) { throw new IllegalStateException("Unable to cancel session: no session has been created to cancel."); } SessionManager.getInstance().cancelSession(); } /***************************************************************************************** * * Logging functions * *****************************************************************************************/ /** * Prints a message to console and MD log */ public static void generalMessage(String s) { Application instance = Application.getInstance(); instance.getGUILog().log(s); System.out.println(s); } /***************************************************************************************** * * Element positioning functions * *****************************************************************************************/ /** * Copies specific elements to a location * * @param elementToCopy * @param copyTarget */ public static Element copyElementToTarget(Element elementToCopy, Element copyTarget) { Element newCopy = null; if (elementToCopy != null && copyTarget != null) { newCopy = CopyPasting.copyPasteElement(elementToCopy, copyTarget, true); } return newCopy; } /** * Deletes all elements in a project under the indicated parent. * * @param parent Parent element under which you want to delete elements. */ public static void deleteEditableContainerChildren(Element parent) throws ReadOnlyElementException { Collection<Element> elements = parent.getOwnedElement(); ArrayList<Element> eList = new ArrayList<>(); for (Element e : elements) { if (e.canBeDeleted() && e.isEditable() && (e.getHumanName().startsWith("Diagram") || (e.getHumanName().startsWith("Package") && !(e.getHumanName().contains("__MMSSync__") || e.getHumanName().contains("Holding Bin"))))) { eList.add(e); } } for (Element elem : eList) { deleteMDElement(elem); } } /** * Deletes all editable container elements in a project. */ public static void clearModel() throws ReadOnlyElementException { if (ElementFinder.getModelRoot() == null) { System.out.println("Null root"); return; } deleteEditableContainerChildren(ElementFinder.getModelRoot()); } /** * Deletes selected element from Magic Draw, including children * Convenience method for the MD API. * * @param ele selected element to be deleted. */ public static void deleteMDElement(Element ele) throws ReadOnlyElementException { ModelElementsManager.getInstance().removeElement(ele); } /** * Returns the element's documentation, stripped of HTML wrapper * * @param target The level element whose comment you want to return */ public static String getElementDocumentation(Element target) { return Utils.stripHtmlWrapper(ModelHelper.getComment(target)); } /** * Returns the value of the passed property * * @param target The property whose value you wish to inspect * @return */ public static String getPropertyValue(Element target) { String value = null; if (target instanceof Property) { ValueSpecification vs = ((Property) target).getDefaultValue(); value = getSpecificationValue(vs); } return value; } /** * Returns the value stored in a ValueSpecification * * @param vs The ValueSpecification to extract a value from * @return the value in the ValueSpecification, expressed as a string. */ public static String getSpecificationValue(ValueSpecification vs) { String value = null; if (vs instanceof LiteralBoolean) { value = Boolean.toString(((LiteralBoolean) vs).isValue()); } else if (vs instanceof LiteralInteger) { value = Long.toString(((LiteralInteger) vs).getValue()); } else if (vs instanceof LiteralNull) { value = null; } else if (vs instanceof LiteralReal) { value = Double.toString(((LiteralReal) vs).getValue()); } else if (vs instanceof LiteralString) { value = Utils.stripHtmlWrapper(((LiteralString) vs).getValue()); } else if (vs instanceof LiteralUnlimitedNatural) { value = Long.toString(((LiteralUnlimitedNatural) vs).getValue()); } return value; } /** * Sets the comments of the target element, adding the necessary html * wrapper * * @param target The level element whose comment you want to change * @param documentation The new comments for the target element */ public static void setElementDocumentation(Element target, String documentation) { ModelHelper.setComment(target, documentation); } /** * Sets the name of the passed NamedElement. * * @param target The NamedElement to rename * @param newName The new name for the element */ public static void setElementName(NamedElement target, String newName) { target.setName(newName); } /***************************************************************************************** * * MMS Stereotype Functions * *****************************************************************************************/ //???? @Deprecated public static void prepareMMS(String url, String site) { String s; s = "Model Management System"; if (StereotypesHelper.hasStereotype(ElementFinder.getModelRoot(), s)) { System.out.println("Found " + s); } Stereotype mms = StereotypesHelper.getStereotype(project, s); if (mms != null) { System.out.println("Stereotype found " + s); } s = "ModelManagementSystem"; if (StereotypesHelper.hasStereotype(ElementFinder.getModelRoot(), s)) { System.out.println("Found " + s); } mms = StereotypesHelper.getStereotype(project, s); if (mms != null) { System.out.println("Stereotype found " + s); } System.out.println(StereotypesHelper.canApplyStereotype(ElementFinder.getModelRoot(), mms)); if (!StereotypesHelper.hasStereotype(ElementFinder.getModelRoot(), "ModelManagementSystem")) { StereotypesHelper.addStereotype(ElementFinder.getModelRoot(), mms); } StereotypesHelper.setStereotypePropertyValue(ElementFinder.getModelRoot(), mms, "MMS Site", site); StereotypesHelper.setStereotypePropertyValue(ElementFinder.getModelRoot(), mms, "MMS URL", url); } //???? @Deprecated private static Property getTagProperty(String name, Stereotype ster) { List<Element> ste = StereotypesHelper.getExtendedElements(ster); for (Element elem : ste) { if (ster.hasOwnedAttribute()) { List<Property> attribs = ster.getOwnedAttribute(); for (Property tag : attribs) { System.out.println(tag.getName()); if (tag.getName().equals(name)) { List<?> value = StereotypesHelper.getStereotypePropertyValue(elem, ster, tag.getName()); for (Object val : value) { if (val instanceof LiteralString) { System.out.println(((LiteralString) val).getValue() + " " + ((LiteralString) val).isEditable()); } } return tag; } } } } System.out.println(name + " not found"); return null; } /***************************************************************************************** * * Element Creation Functions * *****************************************************************************************/ public static Association createAssociation(Element owner, Element source, Element target) { Association newAssoc = ef.createAssociationInstance(); finishElement(newAssoc, null, owner); Property sourceProp = createProperty(((NamedElement) target).getName(), source, null, target, "none", "", ""); Property targetProp = createProperty(((NamedElement) source).getName(), target, null, source, "none", "", ""); newAssoc.getMemberEnd().clear(); newAssoc.getMemberEnd().add(0, sourceProp); newAssoc.getMemberEnd().add(targetProp); return newAssoc; } public static Class createBlock(String name, Element owner) { Class newBlock = createClass(name, owner); Element stereo = Converters.getIdToElementConverter() .apply("_11_5EAPbeta_be00301_1147424179914_458922_958", Project.getProject(owner)); if (!(stereo instanceof Stereotype)) { return null; } Stereotype block = (Stereotype) stereo; StereotypesHelper.addStereotype(newBlock, block); return newBlock; } public static Class createClass(String name, Element owner) { Class newClass = ef.createClassInstance(); finishElement(newClass, name, owner); return newClass; } public static Component createComponent(String name, Element owner) { Component comp = ef.createComponentInstance(); finishElement(comp, name, owner); return comp; } public static Constraint createConstraint(String name, Element owner, ValueSpecification spec) { Constraint newConstraint = ef.createConstraintInstance(); finishElement(newConstraint, name, owner); if (spec != null) { newConstraint.setSpecification(spec); } return newConstraint; } public static Association createDirectedComposition(Element document, Element view) { Association assoc = ef.createAssociationInstance(); finishElement(assoc, null, document.getOwner()); Property source = createProperty(((NamedElement) view).getName(), document, null, view, "composite", "1", "1"); Property target = createProperty("", assoc, null, document, "none", "1", "1"); assoc.getMemberEnd().clear(); assoc.getMemberEnd().add(0, source); assoc.getMemberEnd().add(target); assoc.getOwnedEnd().add(0, target); return assoc; } public static Dependency createDependency(String name, Element owner, Element source, Element target) { Dependency depd = ef.createDependencyInstance(); setRelationshipEnds(depd, source, target); finishElement(depd, null, owner); return depd; } public static Class createDocument(String name, Element owner) { Class newDocument = createClass(name, owner); Stereotype sysmlDocument = Utils.getDocumentStereotype(Project.getProject(owner)); StereotypesHelper.addStereotype(newDocument, sysmlDocument); return newDocument; } public static Generalization createGeneralization(String name, Element owner, Element source, Element target) { Generalization genr = ef.createGeneralizationInstance(); setRelationshipEnds(genr, source, target); finishElement(genr, null, owner); return genr; } public static Package createPackage(String name, Element owner) { Package newPackage = ef.createPackageInstance(); finishElement(newPackage, name, owner); return newPackage; } public static Property createPartProperty(String name, Element owner) { Property newProp = createProperty(name, owner, null, null, null, null, null); Element stereo = Converters.getIdToElementConverter() .apply("_15_0_be00301_1199377756297_348405_2678", Project.getProject(owner)); if (!(stereo instanceof Stereotype)) { return null; } Stereotype partProp = (Stereotype) stereo; StereotypesHelper.addStereotype(newProp, partProp); return newProp; } public static Property createProperty(String name, Element owner, ValueSpecification defaultValue, Element typeElement, String aggregation, String multMin, String multMax) { Property prop = ef.createPropertyInstance(); finishElement(prop, name, owner); prop.setVisibility(VisibilityKindEnum.PUBLIC); if (defaultValue != null) { prop.setDefaultValue(defaultValue); } if (typeElement != null) { prop.setType((Type) typeElement); } if (aggregation != null) { prop.setAggregation(AggregationKindEnum.getByName(aggregation)); } if (multMin != null) { try { Long spmin = new Long(multMin); ValueSpecification pmin = prop.getLowerValue(); if (pmin == null) { pmin = ef.createLiteralIntegerInstance(); } else if (pmin instanceof LiteralInteger) { ((LiteralInteger) pmin).setValue(spmin.intValue()); } else if (pmin instanceof LiteralUnlimitedNatural) { ((LiteralUnlimitedNatural) pmin).setValue(spmin.intValue()); } prop.setLowerValue(pmin); } catch (NumberFormatException ignored) { } } if (multMax != null) { try { Long spmax = new Long(multMax); ValueSpecification pmax = prop.getLowerValue(); if (pmax == null) { pmax = ef.createLiteralIntegerInstance(); } else if (pmax instanceof LiteralInteger) { ((LiteralInteger) pmax).setValue(spmax.intValue()); } else if (pmax instanceof LiteralUnlimitedNatural) { ((LiteralUnlimitedNatural) pmax).setValue(spmax.intValue()); } prop.setLowerValue(pmax); } catch (NumberFormatException en) { } } return prop; } public static Component createSiteCharComponent(String name, Element owner) { Component comp = createComponent(name, owner); Component genTarget = Utils.getSiteCharacterizationComponent(Project.getProject(owner)); createGeneralization("", comp, comp, genTarget); createDependency("", comp, comp, owner); return comp; } @SuppressWarnings("unchecked") @Deprecated public static ValueSpecification createValueSpec(String type, String value) throws ReferenceException { return null; } public static Class createView(String name, Element owner) { Class newView = createClass(name, owner); Stereotype sysmlView = Utils.getViewStereotype(Project.getProject(owner)); StereotypesHelper.addStereotype(newView, sysmlView); return newView; } /****************************************************************************************************** * * Helper methods for element creation functions * ******************************************************************************************************/ /** * Convenience method to fill element properties name and owner. * * @param newElement The element to be finished. * @param name The name of the NamedElement. This will be applied to a NamedElement * unless name is null. This parameter will be ignored if the element is not * a NamedElement. * @param owner The owner of the element to be finished. * @return The finished newElement. */ private static Element finishElement(Element newElement, String name, Element owner) { if (newElement instanceof NamedElement && !(name == null || name.isEmpty())) { ((NamedElement) newElement).setName(name); } newElement.setOwner(owner); return newElement; } /** * Convenience method to set or update relationship ends * * @param dr * @param source * @param target */ private static void setRelationshipEnds(DirectedRelationship dr, Element source, Element target) { ModelHelper.setClientElement(dr, source); ModelHelper.setSupplierElement(dr, target); } }