/*******************************************************************************
* 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.core.Application;
import com.nomagic.magicdraw.core.Project;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.NamedElement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class ElementFinder {
/************************************************************
*
* MD Element Finding Methods
*
************************************************************/
/**
* Returns a list of elements under the indicated parent, inclusive of the
* parent (the first element in the list). No guarantee is made as to the
* editability of these elements.
*
* @param parent The top level element whose owned elements you want to select
*/
public static List<Element> findElements(Element parent) {
List<Element> elements = new ArrayList<>();
elements.add(parent);
elements.addAll(parent.getOwnedElement());
Element current;
for (int i = 0; i < elements.size(); i++) {
current = elements.get(i);
if (current.hasOwnedElement()) {
Collection<Element> owned = current.getOwnedElement();
for (Element elm : owned) {
if (!elements.contains(elm)) {
elements.add(elm);
}
}
}
}
return elements;
}
/**
* Returns a list of all elements in the model, inclusive of the data
* element (the first element in the list). No guarantee is made as to the
* editability of these elements.
*/
public static List<Element> findElements() {
return findElements(getModelRoot());
}
/**
* Retrieves all elements in the project with the specified human name that are
* owned by the specified element, inclusive of the parent (the first
* element in the list). No guarantee is made as to the editability of these
* elements.
*
* @param elementHumanName HumanName of element, i.e. "Package New Container" or (type + " " + name)
* @param parent The top level element whose owned elements you want to search
* through
*/
public static List<Element> findElementsByHumanName(String elementHumanName, Element parent) {
List<Element> elements = findElements(parent);
if (elements == null) {
return null;
}
List<Element> retrievedElements = new ArrayList<Element>();
for (Element elem : elements) {
if (elem.getHumanName().contains(elementHumanName)) {
retrievedElements.add(elem);
}
}
System.out.println("Found " + retrievedElements.size() + " Element(s) containing human name " + elementHumanName);
if (retrievedElements.size() > 0) {
return retrievedElements;
}
else {
return null;
}
}
/**
* Retrieves all elements in the project with the specified human name in the
* model inclusive of the root (the first element in the list). No guarantee
* is made as to the editability of these elements.
*
* @param elementHumanName HumanName of element, i.e. "Package New Container" or (type + " " + name)
*/
public static List<Element> findElementsByHumanName(String elementHumanName) {
return findElementsByHumanName(elementHumanName, getModelRoot());
}
/**
* Retrieves all named elements in the project with the specified name that are
* owned by the specified element, inclusive of the parent (the first
* element in the list). No guarantee is made as to the editability of these
* elements.
*
* @param elementName Name of element
* @param parent The top level element whose owned elements you want to search
* through
*/
public static List<NamedElement> findElementsByName(String elementName, Element parent) {
List<Element> elements = findElements(parent);
if (elements == null) {
return null;
}
List<NamedElement> retrievedElements = new ArrayList<>();
for (Element elem : elements) {
if (elem instanceof NamedElement && ((NamedElement) elem).getName().equals(elementName)) {
retrievedElements.add((NamedElement) elem);
}
}
System.out.println("Found " + retrievedElements.size() + " NamedElement(s) containing name " + elementName);
if (retrievedElements.size() > 0) {
return retrievedElements;
}
else {
return null;
}
}
public static Element findOwnedElementByName(Element owner, String name) {
for (Element e : owner.getOwnedElement()) {
if (e instanceof NamedElement) {
if (((NamedElement) e).getName().equals(name)) {
return e;
}
}
}
return null;
}
/**
* Retrieves all elements in the project with the specified name in the
* model inclusive of the root (the first element in the list). No guarantee
* is made as to the editability of these elements.
*
* @param elementName Name of element.
*/
public static List<NamedElement> findElementsByName(String elementName) {
return findElementsByName(elementName, getModelRoot());
}
/**
* Retrieves all elements in the project with the specified type that are
* owned by the specified parent, inclusive of parent (the first element in
* the list). No guarantee is made as to the editability of these elements.
*
* @param elementType Type of element. ie. Package or Document.
* @param parent The top level element whose owned elements you want to search
* through
*/
public static List<Element> findElementsByType(String elementType, Element parent) {
List<Element> elements = findElements(parent);
if (elements == null) {
return null;
}
List<Element> retrievedElements = new ArrayList<>();
for (Element elem : elements) {
if (elem.getHumanType().equals(elementType)) {
retrievedElements.add(elem);
}
}
System.out.println("Found " + retrievedElements.size() + " Element(s) of type " + elementType);
if (retrievedElements.size() > 0) {
return retrievedElements;
}
else {
return null;
}
}
/**
* Retrieves all elements in the project with the specified type, inclusive
* of root (the first element in the list). No guarantee is made as to the
* editability of these elements.
*
* @param elementType Type of element. ie. Package or Document.
*/
public static List<Element> findElementsByType(String elementType) {
return findElementsByType(elementType, getModelRoot());
}
/**
* Find the first occurrence of the listed element under the supplied owner,
* inclusive of the owner
*
* @param type Type of desired element
* @param name Name of desired element
* @param owner Element under which you search for the indicated element
*/
public static Element getElement(String type, String name, Element owner) {
if (owner == null) {
owner = getModelRoot();
}
ArrayList<Element> elements = new ArrayList<>();
elements.add(owner);
elements.addAll(owner.getOwnedElement());
Element current;
for (int i = 0; i < elements.size(); i++) {
current = elements.get(i);
if (current.getHumanName().equals(type + (name.isEmpty() ? "" : " " + name))) {
return current;
}
if (current.hasOwnedElement()) {
elements.addAll(current.getOwnedElement());
}
}
return null;
}
/**
* Find the first occurrence of the listed element anywhere in the model,
* inclusive of model root
*
* @param type Type of desired element
* @param name Name of desired element
*/
public static Element getElement(String type, String name) {
return getElement(type, name, getModelRoot());
}
/**
* Finds an element within the passed project's primary model. Does not search other modules loaded in project.
*
* @param qualifiedName in the format of magicdraw's qualified name: ex "Package::hello::world
* @param project project to search the primary model on
* @return found element, or null if not found
*/
@Deprecated
public static Element getElementByQualifiedName(String qualifiedName, Project project) {
String[] path = qualifiedName.split("::");
Element curElement = project.getPrimaryModel();
for (int i = 0; i < path.length; i++) {
curElement = findOwnedElementByName(curElement, path[i]);
if (curElement == null) {
return null;
}
}
return curElement;
}
/**
* Retrieves the model root element.
*/
public static Element getModelRoot() {
return Application.getInstance().getProject().getPrimaryModel();
}
/**
* Finds the first package that contains the target element
* Generally used to find a container that holds an element known directly,
* or in conjunction with getElementByID to find it's container.
*
* @param target Element contained within the returned package
* @return Element
*/
public static Element getPackageContainer(Element target) {
Element pkg = target.getOwner();
while (!pkg.getHumanType().equals("Package")) {
target = pkg;
pkg = target.getOwner();
}
return pkg;
}
/**
* @return
*/
public static int getEmptyDiagramCount() {
List<Element> diagrams = findElementsByType("Diagram");
List<Element> temp = new ArrayList<Element>();
for (Element e : diagrams) {
if (!e.isEditable()) {
temp.add(e);
}
}
for (Element e : temp) {
if (!e.isEditable()) {
diagrams.remove(e);
}
}
return diagrams.size();
}
}