blob: 65f01d793a427645e451516b7f56afc4ec9b9e22 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2013 CEA LIST.
*
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Ansgar Radermacher ansgar.radermacher@cea.fr
*
*****************************************************************************/
package org.eclipse.papyrus.designer.components.transformation.core;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.UniqueEList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.papyrus.designer.components.FCM.Assembly;
import org.eclipse.papyrus.designer.components.FCM.ContainerRule;
import org.eclipse.papyrus.designer.components.FCM.InteractionComponent;
import org.eclipse.papyrus.designer.components.FCM.Singleton;
import org.eclipse.papyrus.designer.components.transformation.core.preferences.PapyrusDesignerPreferenceConstants;
import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil;
import org.eclipse.uml2.uml.AggregationKind;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.InstanceSpecification;
import org.eclipse.uml2.uml.Interface;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Port;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Type;
import org.eclipse.uml2.uml.util.UMLUtil;
public class Utils {
public static final String QUOTE = "\""; //$NON-NLS-1$
/**
* Retrieve an element from a list of named elements via its name
*
* @param namedElementList
* @param name
* @return
*/
public static NamedElement getNamedElementFromList(
EList<? extends EObject> elementList, String name) {
for (EObject element : elementList) {
if (element instanceof NamedElement) {
NamedElement namedElement = (NamedElement) element;
if((namedElement.getName() != null) && namedElement.getName().equals(name)) {
return namedElement;
}
}
}
return null;
}
/**
* return the top-level owner of an element. This function returns the same
* value as getModel, if the top-level element is a model. While this is the
* case for models, model libraries have a top-level package (not a model).
* In this case, getTop returns the top-level package whereas getModel would
* return null.
*
* @param element
* @return the top-level owning package
* @deprecated Use getRootPackage method in oep.uml.tools.utils.PackageUtil
*/
@Deprecated
public static Package getTop(Element element) {
while (element != null) {
Element owner = element.getOwner();
if (owner == null) {
if (element instanceof Package) {
return (Package) element;
}
}
element = owner;
}
return null;
}
/**
* Return package at first level. Useful, since last model transformation
* will put elements under a new "root"
*
* @param element
* @return
*/
public static Package getFirstLevel(Element element) {
Element lastElement = element;
while (element != null) {
Element owner = element.getOwner();
if (owner == null) {
if (lastElement instanceof Package) {
return (Package) lastElement;
}
}
lastElement = element;
element = owner;
}
return null;
}
/**
* @param element
* an element which is owned by a model.
* @param subfolder
* the name of a sub-folder within root (created, if not
* existent)
* @return a reference to the sub folder within the root of the model that
* belongs to the passed element.
*/
public static Package getRoot(Element element, String subfolder) {
Package root = getTop(element);
if (root.getNestedPackage(subfolder) != null) {
return root.getNestedPackage(subfolder);
} else {
return root.createNestedPackage(subfolder);
}
}
/**
* Convenience method enabling to apply getOwnedOperation equally to classes
* and interfaces
*
* @param cl
* @param name
* @param paramNames
* @param paramTypes
* @return
*/
public static Operation createOwnedOperation(Classifier cl, String name,
EList<String> paramNames, EList<Type> paramTypes, Type retType) {
if (cl instanceof Class) {
return ((Class) cl).createOwnedOperation(name, paramNames,
paramTypes, retType);
} else if (cl instanceof Interface) {
return ((Interface) cl).createOwnedOperation(name, paramNames,
paramTypes, retType);
} else {
return null;
}
}
public static Operation getOwnedOperation(Classifier cl, String name,
EList<String> paramNames, EList<Type> paramTypes) {
if (cl instanceof Class) {
return ((Class) cl).getOwnedOperation(name, paramNames, paramTypes);
} else if (cl instanceof Interface) {
return ((Interface) cl).getOwnedOperation(name, paramNames,
paramTypes);
} else {
return null;
}
}
/**
* this method returns the component type of an implementation. It is based
* on the modeling convention that implementations inherit from types.
*/
public static Class componentType(Class implementation) {
if (Utils.isCompImpl(implementation)) {
Iterator<Class> superclasses = implementation.getSuperClasses()
.iterator();
while (superclasses.hasNext()) {
Class componentType = superclasses.next();
if (Utils.isCompType(componentType)) {
return componentType;
}
}
}
return null;
}
/**
* return true, if a component (implementation) is a composite, i.e. has
* inner parts
*/
public static boolean isComposite(Class implementation) {
return Utils.isCompImpl(implementation)
&& (getParts(implementation).size() > 0);
}
public static EList<Property> getParts(Class implementation) {
if (treatNoneAsComposite()) {
EList<Property> parts = new BasicEList<Property>();
for (Property part : implementation.getAttributes()) {
if (part.getAggregation() != AggregationKind.SHARED_LITERAL) {
parts.add(part);
}
}
return parts;
}
else {
return implementation.getParts();
}
}
/**
* @param attribute
* an attribute
* @return true, if the aggregation kind is considered as a composition
*/
public static boolean isComposition(Property attribute) {
if (treatNoneAsComposite()) {
return (attribute.getAggregation() != AggregationKind.SHARED_LITERAL);
}
else {
return (attribute.getAggregation() == AggregationKind.COMPOSITE_LITERAL);
}
}
/**
* return true, if an instance specification is a composite, i.e. has > 1
* slots TODO: distinguish parts and configuration attributes
*/
public static boolean isComposite(InstanceSpecification is) {
return (is.getSlots().size() > 0);
}
/**
* Get an element via its qualified name. Will find elements from the root
* model and elements in imported models. Also supports target model in
* which imports have been copied (while keeping the top-level name)
*
* @param root
* @param qualifiedName
* @return
*/
public static NamedElement getQualifiedElement(Package root,
String qualifiedName) {
NamedElement namedElement = null;
int index = qualifiedName.indexOf("::"); //$NON-NLS-1$
if (index != -1) {
// first try using a path without top element (since
// getQualifiedElement is typically used for
// imported elements)
String remainder = qualifiedName.substring(index + 2);
namedElement = getQualifiedElement(root, remainder, qualifiedName);
}
if (namedElement == null) {
// try with complete name as path name, but assume that the element
// has been copied into the model,
// i.e. qualifiedName is prefixed by model name
namedElement = getQualifiedElement(root, qualifiedName,
root.getName() + "::" + qualifiedName); //$NON-NLS-1$
}
return namedElement;
}
/**
* Retrieve an element via its qualified name within a package The segments
* of the package may be non unique due to imports
*
* @return the found element, if it exists
*/
public static NamedElement getQualifiedElement(Package root,
String remainingPath, String qualifiedName) {
if (root == null) {
return null;
}
if (!remainingPath.contains(NamedElement.SEPARATOR)) {
for (NamedElement candidate : root.getMembers()) {
String name = candidate.getName();
if ((name != null) && name.equals(remainingPath)) {
if (candidate.getQualifiedName().equals(qualifiedName)) {
return candidate;
}
}
}
} else {
String segment = remainingPath.split(NamedElement.SEPARATOR)[0];
String remainder = remainingPath.substring(segment.length() + 2);
for (Element element : root.getMembers()) {
if (element instanceof Package) {
if (((NamedElement) element).getName().equals(segment)) {
NamedElement foundElement = getQualifiedElement(
(Package) element, remainder, qualifiedName);
// return, if not found
if (foundElement != null) {
return foundElement;
}
}
}
}
}
return null;
}
/**
* Simple check whether an element is in a different model than the passed
* package It will return true, whenever the the top elements do not match.
* This is always true, if the 2nd belongs to a different model, whether
* imported or not. This distinction is however not required in our context.
*/
public static boolean isElementInDifferentModel(Package model,
NamedElement namedElement) {
return model != getTop(namedElement);
}
/**
* /**
* Check whether a class contains a non-port attribute of a given name
*
* @param cl
* @return
*/
public static boolean hasNonPortOwnedAttribute(Class cl, String name) {
for (Property p : cl.getOwnedAttributes()) {
if (!(p instanceof Port)) {
if (p.getName().equals(name)) {
return true;
}
}
}
return false;
}
public static <T extends EObject> EList<T> getAllElementsOfType(Element examineElement, java.lang.Class<T> clazz)
{
EList<Element> visitedPackages = new BasicEList<Element>();
return getAllElementsOfType(examineElement, clazz, visitedPackages);
}
@SuppressWarnings("unchecked")
public static <T extends EObject> EList<T> getAllElementsOfType(Element examineElement, java.lang.Class<T> clazz, EList<Element> visitedPackages)
{
EList<T> list = new UniqueEList<T>();
for (Element element : examineElement.allOwnedElements()) {
if (element instanceof Package) {
if (!visitedPackages.contains(element)) {
visitedPackages.add(element);
list.addAll(getAllElementsOfType(element, clazz,
visitedPackages));
}
} else if (clazz.isInstance(element)) {
list.add((T) element);
}
}
return list;
}
/**
* @param a
* potential implementation
* @return true, if passed classifier is an implementation (i.e. declared
* via stereotypes as component or connector implementation (a sub-type of component implementations,
* therefore no additional check is required)
*/
public static boolean isCompImpl(Classifier implementation) {
return !implementation.isAbstract();
}
/**
* Check whether the passed class is a component type (and not a component implementation).
* This includes connector and container types as well.
*
* @param component
* @return
*/
public static boolean isCompType(Class component) {
return component.isAbstract();
}
public static boolean isInteractionComponent(Classifier component) {
return StereotypeUtil.isApplied(component, InteractionComponent.class);
}
public static boolean isSingleton(Class component) {
return StereotypeUtil.isApplied(component, Singleton.class);
}
public static boolean isAssembly(Class component) {
return StereotypeUtil.isApplied(component, Assembly.class);
}
public static boolean treatNoneAsComposite() {
IPreferenceStore store = Activator.getDefault().getPreferenceStore();
return store.getBoolean(PapyrusDesignerPreferenceConstants.P_TREAT_NONE_AS_COMPOSITE);
}
public static boolean allAttributesAreConfigAttributs() {
IPreferenceStore store = Activator.getDefault().getPreferenceStore();
return store.getBoolean(PapyrusDesignerPreferenceConstants.P_ALL_ATTRIBUTES_ARE_CONFIG_ATTRIBUTES);
}
/**
* True, if either a component implementation or a type
*
* @param component
* @return
*/
public static boolean isComponent(Class component) {
return (isCompType(component) || isCompImpl(component));
}
/**
* Return the absolute file name to a file name given e.g. in the form platform:/plugin/xxx
*
* @param fileName
* the file name using eclipse elements such as platform:/plugin
* @return the absolute file name
*/
public static String getAbsoluteFN(String fileName) {
try {
URL absoluteURL = FileLocator.toFileURL(new URL(fileName));
return absoluteURL.getFile();
} catch (MalformedURLException e) {
} catch (IOException e) {
}
return null;
}
// TODO: need a generic utility function for getting all elements obeying a certain
// criteria from a model
public static EList<ContainerRule> getAllRules(Package pkg) {
EList<Package> visitedPackages = new BasicEList<Package>();
EList<ContainerRule> contRuleList = new BasicEList<ContainerRule>();
getAllRules(pkg, visitedPackages, contRuleList);
return contRuleList;
}
public static void getAllRules(Package pkg, EList<Package> visitedPackages, EList<ContainerRule> contRuleList) {
for (Element el : pkg.getMembers()) {
if (el instanceof Package) {
if (!visitedPackages.contains(el)) {
visitedPackages.add((Package) el);
getAllRules((Package) el, visitedPackages, contRuleList);
}
}
else if (el instanceof Class) {
if (StereotypeUtil.isApplied(el, ContainerRule.class)) {
ContainerRule rule = UMLUtil.getStereotypeApplication(el, ContainerRule.class);
contRuleList.add(rule);
}
}
}
}
/**
* Put quotes around a string, unless string already starts with a quote.
*
* @param str
* @return
*/
public static String quoteString(String str) {
if (str.startsWith(QUOTE)) {
return str;
}
else {
return QUOTE + str + QUOTE;
}
}
}