/** * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. */ /** * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3, 29 June 2007; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.gnu.org/licenses/lgpl-3.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sintef.thingml.constraints; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; import org.sintef.thingml.*; import org.sintef.thingml.helpers.ActionHelper; import org.sintef.thingml.helpers.ThingHelper; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.Stack; public class ThingMLHelpers { /* *********************************************************** * Resolution of containers * ***********************************************************/ public static <C> C findContainer(EObject eObject, Class<C> cClass) { while (eObject != null && !cClass.isAssignableFrom(eObject.getClass())) { eObject = eObject.eContainer(); } return (C) eObject; } public static ThingMLModel findContainingModel(EObject object) { return findContainer(object, ThingMLModel.class); } public static Function findContainingFunction(EObject object) { return findContainer(object,Function.class); } public static ThingMLElement findContainingElement(EObject object) { return findContainer(object,ThingMLElement.class); } public static ActionBlock findContainingActionBlock(EObject object) { return findContainer(object,ActionBlock.class); } public static Thing findContainingThing(EObject object) { return findContainer(object,Thing.class); } public static Instance findContainingInstance(EObject object) { return findContainer(object,Instance.class); } public static Configuration findContainingConfiguration(EObject object) { return findContainer(object,Configuration.class); } public static State findContainingState(EObject object) { return findContainer(object,State.class); } public static Region findContainingRegion(EObject object) { return findContainer(object,Region.class); } public static Handler findContainingHandler(EObject object) { return findContainer(object,Handler.class); } public static StartSession findContainingStartSession(EObject object) { return findContainer(object, StartSession.class); } /* *********************************************************** * Type checking and expressions * ***********************************************************/ //public static TypeChecker typerchecker = new TypeChecker(); /*public static Type getExpressionType(Expression exp) { return typerchecker.computeTypeOf(exp); }*/ /* *********************************************************** * Resolution of imported models / All available Things and Types * ***********************************************************/ public static ArrayList<ThingMLModel> allThingMLModelModels(ThingMLModel model) { ArrayList<ThingMLModel> result = new ArrayList<ThingMLModel>(); result.add(model); ArrayList<ThingMLModel> temp = new ArrayList<ThingMLModel>(); int prevSize = result.size(); int newSize = prevSize; do { for (ThingMLModel m : result) { for(ThingMLModel m2 : m.getImports()) { if (!temp.contains(m2)) { temp.add(m2); } } } for (ThingMLModel m : temp) { if (!result.contains(m)) { result.add(m); } } prevSize = newSize; newSize = result.size(); } while (newSize > prevSize); return result; } public static ArrayList<Type> allTypes(ThingMLModel model) { ArrayList<Type> result = new ArrayList<Type>(); for (ThingMLModel m : allThingMLModelModels(model)) { for (Type t : m.getTypes()) { if (!result.contains(t)) result.add(t); } } return result; } /** * Returns the list of all types that are actually used in the model * A type is used if: * - it exists a property (in a thing or in a state machine) of this type, or * - it exists a message with a parameter of this type * @param model * @return */ public static Set<Type> allUsedTypes(ThingMLModel model) { Set<Type> result = new HashSet<Type>(); for(Type t : allTypes(model)) { for(Thing thing : allThings(model)) { for(Type tt : ThingHelper.allUsedTypes(thing)) { if (EcoreUtil.equals(tt, t)) { result.add(t); } } } } return result; } public static Set<Type> allUsedSimpleTypes(ThingMLModel model) { Set<Type> result = new HashSet<Type>(); for(Type t : allSimpleTypes(model)) { for(Thing thing : allThings(model)) { for(Type tt : ThingHelper.allUsedTypes(thing)) { if (EcoreUtil.equals(tt, t)) { result.add(t); } } } } return result; } public static ArrayList<Type> allSimpleTypes(ThingMLModel model) { ArrayList<Type> result = new ArrayList<Type>(); for (ThingMLModel m : allThingMLModelModels(model)) { for (Type t : m.getTypes()) { if ( (t instanceof ObjectType || t instanceof PrimitiveType || t instanceof Enumeration) && !result.contains(t)) result.add(t); } } return result; } public static ArrayList<Enumeration> allEnnumerations(ThingMLModel model) { ArrayList<Enumeration> result = new ArrayList<Enumeration>(); for (ThingMLModel m : allThingMLModelModels(model)) { for (Type t : m.getTypes()) { if ( (t instanceof Enumeration) && !result.contains(t)) result.add((Enumeration)t); } } return result; } public static ArrayList<Thing> allThings(ThingMLModel model) { ArrayList<Thing> result = new ArrayList<Thing>(); for (ThingMLModel m : allThingMLModelModels(model)) { for (Type t : m.getTypes()) { if ( (t instanceof Thing) && !result.contains(t)) result.add((Thing)t); } } return result; } public static ArrayList<Enumeration> findEnumeration(ThingMLModel model, String name, boolean fuzzy) { ArrayList<Enumeration> result = new ArrayList<Enumeration>(); for (Enumeration t : allEnnumerations(model)) { if (t.getName().startsWith(name)) { if (fuzzy) result.add(t); else if (t.getName().equals(name)) result.add(t); } } return result; } public static ArrayList<EnumerationLiteral> findEnumerationLiteral(Enumeration e, String name, boolean fuzzy) { ArrayList<EnumerationLiteral> result = new ArrayList<EnumerationLiteral>(); for (EnumerationLiteral t : e.getLiterals()) { if (t.getName().startsWith(name)) { if (fuzzy) result.add(t); else if (t.getName().equals(name)) result.add(t); } } return result; } public static ArrayList<Type> findSimpleType(ThingMLModel model, String name, boolean fuzzy) { ArrayList<Type> result = new ArrayList<Type>(); for (Type t : allSimpleTypes(model)) { if (t.getName() != null) { if (t.getName().startsWith(name)) { if (fuzzy) result.add(t); else if (t.getName().equals(name)) result.add(t); } } } return result; } public static ArrayList<Thing> findThing(ThingMLModel model, String name, boolean fuzzy) { ArrayList<Thing> result = new ArrayList<Thing>(); for (Thing t : allThings(model)) { if (t.getName().startsWith(name)) { if (fuzzy) result.add(t); else if (t.getName().equals(name)) result.add(t); } } return result; } /* *********************************************************** * Resolution for Things: Ports, Properties, StateMachines, Messages * ***********************************************************/ public static ArrayList<Thing> allThingFragments(Thing thing) { ArrayList<Thing> result = new ArrayList<Thing>(); result.add(thing); for (Thing t : thing.getIncludes()) if (t != thing) { for (Thing c : allThingFragments(t)) if (!result.contains(c)) result.add(c); } return result; } public static ArrayList<Property> allProperties(Thing thing) { ArrayList<Property> result = new ArrayList<Property>(); for (Thing t : allThingFragments(thing)) { result.addAll(t.getProperties()); } return result; } public static ArrayList<PlatformAnnotation> allAnnotations(Thing thing) { ArrayList<PlatformAnnotation> result = new ArrayList<PlatformAnnotation>(); for (Thing t : allThingFragments(thing)) { result.addAll(t.getAnnotations()); } return result; } public static ArrayList<Function> allFunctions(Thing thing) { ArrayList<Function> result = new ArrayList<Function>(); for (Thing t : allThingFragments(thing)) { result.addAll(t.getFunctions()); } return result; } public static ArrayList<Message> allMessages(Thing thing) { ArrayList<Message> result = new ArrayList<Message>(); for (Thing t : allThingFragments(thing)) { for (Message msg : t.getMessages()) { boolean isPresent = false; for(Message m : result) { if (EcoreUtil.equals(msg, m)) { isPresent = true; break; } } if (!isPresent) result.add(msg); } } return result; } public static ArrayList<Port> allPorts(Thing thing) { ArrayList<Port> result = new ArrayList<Port>(); for (Thing t : allThingFragments(thing)) { result.addAll(t.getPorts()); } return result; } public static ArrayList<ProvidedPort> allProvidedPorts(Thing thing) { ArrayList<ProvidedPort> result = new ArrayList<ProvidedPort>(); for (Port p : allPorts(thing)) { if (p instanceof ProvidedPort) result.add((ProvidedPort)p); } return result; } public static ArrayList<RequiredPort> allRequiredPorts(Thing thing) { ArrayList<RequiredPort> result = new ArrayList<RequiredPort>(); for (Port p : allPorts(thing)) { if (p instanceof RequiredPort) result.add((RequiredPort)p); } return result; } public static ArrayList<Message> allIncomingMessages(Thing thing) { ArrayList<Message> result = new ArrayList<Message>(); for (Port p : allPorts(thing)) { for (Message m : p.getReceives()) { if (!result.contains(m)) result.add(m); } } return result; } public static ArrayList<Message> allOutgoingMessages(Thing thing) { ArrayList<Message> result = new ArrayList<Message>(); for (Port p : allPorts(thing)) { for (Message m : p.getSends()) { if (!result.contains(m)) result.add(m); } } return result; } public static ArrayList<StateMachine> allStateMachines(Thing thing) { ArrayList<StateMachine> result = new ArrayList<StateMachine>(); for (Thing t : allThingFragments(thing)) { result.addAll(t.getBehaviour()); } return result; } public static ArrayList<Variable> allVariables(Thing thing) { //TODO: Does this get absolutely all variables? ArrayList<Variable> result = new ArrayList<Variable>(); for (Thing t : allThingFragments(thing)) { for (Action a : ActionHelper.getAllActions(t, VariableAssignment.class)) { VariableAssignment assignment = (VariableAssignment)a; result.add(assignment.getProperty()); } } return result; } public static ArrayList<Property> findProperty(Thing thing, String name, boolean fuzzy) { ArrayList<Property> result = new ArrayList<Property>(); for (Property t : allProperties(thing)) { if (t.getName().startsWith(name)) { if (fuzzy) result.add(t); else if (t.getName().equals(name)) result.add(t); } } return result; } public static ArrayList<Function> findFunction(Thing thing, String name, boolean fuzzy) { ArrayList<Function> result = new ArrayList<Function>(); for (Function t : allFunctions(thing)) { if (t.getName().startsWith(name)) { if (fuzzy) result.add(t); else if (t.getName().equals(name)) result.add(t); } } return result; } public static ArrayList<Message> findMessage(Thing thing, String name, boolean fuzzy) { ArrayList<Message> result = new ArrayList<Message>(); for (Message msg : allMessages(thing)) { if (msg.getName().startsWith(name)) { if (fuzzy) result.add(msg); else if (msg.getName().equals(name)) result.add(msg); } } return result; } public static ArrayList<Port> findPort(Thing thing, String name, boolean fuzzy) { ArrayList<Port> result = new ArrayList<Port>(); for (Port t : allPorts(thing)) { if (t.getName().startsWith(name)) { if (fuzzy) result.add(t); else if (t.getName().equals(name)) result.add(t); } } return result; } public static ArrayList<RequiredPort> findRequiredPort(Thing thing, String name, boolean fuzzy) { ArrayList<RequiredPort> result = new ArrayList<RequiredPort>(); for (RequiredPort t : allRequiredPorts(thing)) { if (t.getName().startsWith(name)) { if (fuzzy) result.add(t); else if (t.getName().equals(name)) result.add(t); } } return result; } public static ArrayList<ProvidedPort> findProvidedPort(Thing thing, String name, boolean fuzzy) { ArrayList<ProvidedPort> result = new ArrayList<ProvidedPort>(); for (ProvidedPort t : allProvidedPorts(thing)) { if (t.getName().startsWith(name)) { if (fuzzy) result.add(t); else if (t.getName().equals(name)) result.add(t); } } return result; } public static ArrayList<StateMachine> findStateMachine(Thing thing, String name, boolean fuzzy) { ArrayList<StateMachine> result = new ArrayList<StateMachine>(); for (StateMachine t : allStateMachines(thing)) { if (t.getName().startsWith(name)) { if (fuzzy) result.add(t); else if (t.getName().equals(name)) result.add(t); } } return result; } /* *********************************************************** * Resolution for Ports: Incoming/Outgoing Messages * ***********************************************************/ public static ArrayList<Message> findIncomingMessage(Port port, String name, boolean fuzzy) { ArrayList<Message> result = new ArrayList<Message>(); for (Message t : port.getReceives()) { if (t.getName().startsWith(name)) { if (fuzzy) result.add(t); else if (t.getName().equals(name)) result.add(t); } } return result; } public static ArrayList<Message> findOutgoingMessage(Port port, String name, boolean fuzzy) { ArrayList<Message> result = new ArrayList<Message>(); for (Message t : port.getSends()) { if (t.getName().startsWith(name)) { if (fuzzy) result.add(t); else if (t.getName().equals(name)) result.add(t); } } return result; } /* *********************************************************** * Resolution for State Machines, States, Regions * ***********************************************************/ public static ArrayList<State> allContainingStates(State state) { ArrayList<State> result = new ArrayList<State>(); EObject current = state; while(current != null) { if (current instanceof State) result.add((State)current); current = current.eContainer(); } return result; } public static ArrayList<Property> allProperties(State state) { ArrayList<Property> result = new ArrayList<Property>(); // Properties from the states for (State s : allContainingStates(state)) { result.addAll(s.getProperties()); } // Properties from the thing result.addAll(allProperties(findContainingThing(state))); return result; } public static ArrayList<Variable> allVisibleVariables (EObject container) { ArrayList<Variable> result = new ArrayList<Variable>(); if (container instanceof LocalVariable) { if (container.eContainer() instanceof Stream) { return allVisibleVariables(container.eContainer()); } } // Add the variables of the block if we are in a block ActionBlock b = findContainingActionBlock(container); if (b != null) { for (Action a : b.getActions()) { if (a == container || a.eContents().contains(container)) continue; // ignore variables defined after the current statement if (a instanceof Variable) result.add((Variable)a); } result.addAll(allVisibleVariables(b.eContainer())); return result; } // Add the variables of the state if we are in a state State s = findContainingState(container); if (s != null) { result.addAll(allProperties(s)); return result; } // Add parameters of the function if we are in a function Function f = findContainingFunction(container); if (f != null) { result.addAll(f.getParameters()); result.addAll(allVisibleVariables(f.eContainer())); } Stream stream = findContainingStream(container); if (stream != null) { result.addAll(stream.getSelection()); } // Only the variables of the thing if we are in a thing: Thing t = findContainingThing(container); if (t != null) { // Properties from the thing result.addAll(allProperties(t)); return result; } return result; } public static ArrayList<Variable> findVisibleVariables(EObject container, String name, boolean fuzzy) { ArrayList<Variable> result = new ArrayList<Variable>(); for (Variable t : allVisibleVariables(container)) { if (t.getName() != null && t.getName().startsWith(name)) { if (fuzzy) result.add(t); else if (t.getName().equals(name)) result.add(t); } } return result; } public static ArrayList<Property> findProperty(State state, String name, boolean fuzzy) { ArrayList<Property> result = new ArrayList<Property>(); for (Property t : allProperties(state)) { if (t.getName().startsWith(name)) { if (fuzzy) result.add(t); else if (t.getName().equals(name)) result.add(t); } } return result; } public static ArrayList<State> allValidTargetStates(State state) { ArrayList<State> result = new ArrayList<State>(); if (state instanceof CompositeState) result.addAll(findContainingRegion(state.eContainer()).getSubstate()); else result.addAll(findContainingRegion(state).getSubstate()); return result; } public static ArrayList<State> findValidTargetState(State state, String name, boolean fuzzy) { ArrayList<State> result = new ArrayList<State>(); for (State t : allValidTargetStates(state)) { if (t.getName().startsWith(name)) { if (fuzzy) result.add(t); else if (t.getName().equals(name)) result.add(t); } } return result; } /* *********************************************************** * Resolution for Configurations, Instances and Connectors * ***********************************************************/ public static ArrayList<Configuration> allConfigurations(ThingMLModel model) { ArrayList<Configuration> result = new ArrayList<Configuration>(); for (ThingMLModel m : allThingMLModelModels(model)) { for (Configuration c : m.getConfigs()) { if (!result.contains(c)) result.add(c); } } return result; } public static ArrayList<Configuration> findConfiguration(ThingMLModel model, String name, boolean fuzzy) { ArrayList<Configuration> result = new ArrayList<Configuration>(); for (Configuration c : allConfigurations(model)) { if (c.getName().startsWith(name)) { if (fuzzy) result.add(c); else if (c.getName().equals(name)) result.add(c); } } return result; } /* public static ArrayList<Configuration> allConfigurationFragments(Configuration config) { ArrayList<Configuration> result = new ArrayList<Configuration>(); result.add(config); for (Configuration t : config.getIncludes()) for (Configuration c : allConfigurationFragments(t)) if (!result.contains(c))result.add(c); return result; } */ /* public static ArrayList<ConfigInclude> allConfigurationFragments(Configuration config) { ArrayList<Configuration> result = new ArrayList<Configuration>(); result.add(config); for (Configuration t : config.getIncludes()) for (Configuration c : allConfigurationFragments(t)) if (!result.contains(c))result.add(c); return result; } public static ArrayList<Instance> allInstances(Configuration config) { ArrayList<Instance> result = new ArrayList<Instance>(); for (Configuration t : allConfigurationFragments(config)) { result.addAll(t.getInstances()); } return result; } public static ArrayList<Connector> allConnectors(Configuration config) { ArrayList<Connector> result = new ArrayList<Connector>(); for (Configuration t : allConfigurationFragments(config)) { result.addAll(t.getConnectors()); } return result; } public static ArrayList<Instance> findInstance(Configuration config, String name, boolean fuzzy) { ArrayList<Instance> result = new ArrayList<Instance>(); for (Instance i : allInstances(config)) { if (i.getName().startsWith(name)) { if (fuzzy) result.add(i); else if (i.getName().equals(name)) result.add(i); } } return result; } public static ArrayList<Connector> findConnector(Configuration config, String name, boolean fuzzy) { ArrayList<Connector> result = new ArrayList<Connector>(); for (Connector i : allConnectors(config)) { if (i.getName().startsWith(name)) { if (fuzzy) result.add(i); else if (i.getName().equals(name)) result.add(i); } } return result; } */ /* *********************************************************** * Resolution for Specific Actions / Expressions * ***********************************************************/ public static List<ReceiveMessage> allReceiveMessages(Source input) { List<ReceiveMessage> result = new ArrayList<>(); getAllReceiveMessages(input,result); return result; } private static void getAllReceiveMessages(Source input, List<ReceiveMessage> result) { if(input instanceof SimpleSource) { result.add(((SimpleSource)input).getMessage()); } else if (input instanceof SourceComposition) { SourceComposition composition = (SourceComposition) input; for(Source s : composition.getSources()) { getAllReceiveMessages(s,result); } } } public static Stream findContainingStream(EObject eObject) { return findContainer(eObject,Stream.class); } public static List<SimpleSource> allSimpleSources(Source input) { List<SimpleSource> result = new ArrayList<>(); if(input instanceof SimpleSource) { result.add((SimpleSource)input); } else if(input instanceof SourceComposition) { SourceComposition composition = (SourceComposition) input; for(Source s : composition.getSources()) { result.addAll(allSimpleSources(s)); } } return result; } public static ThingMLElement findReferenceContainer(Reference container) { EObject parent = container.eContainer(); List<String> parents = new ArrayList<String>(); while (parent !=null && !(parent instanceof Handler || parent instanceof Stream || parent instanceof SourceComposition || parent instanceof SimpleSource)) { parents.add(parent.getClass().getName()); parent = parent.eContainer(); } if (parent == null) { for(String p : parents) { System.out.println("Parent:" + parent); } } return (ThingMLElement) parent; } public static Expression findRootExpressions(Expression expression) { Expression result = expression; EObject parent = expression.eContainer(); while(parent != null && parent instanceof Expression) { result = (Expression) parent; parent = parent.eContainer(); } return result; } public static TypedElement findContainingFuncOp(EObject eObject) { while(eObject != null && !(eObject instanceof Function)) { eObject = eObject.eContainer(); } return (TypedElement) eObject; } public static List<Expression> getAllExpressions(ThingMLElement self, Class clazz) { List<Expression> result = new ArrayList<Expression>(); TreeIterator<EObject> it = self.eAllContents(); while(it.hasNext()) { EObject o = it.next(); if (clazz.isInstance(o)) result.add((Expression) o); } if (clazz.isInstance(self))result.add((Expression)self); return result; } public static List<Expression> getAllExpressions(ThingMLElement self) { return getAllExpressions(self, Expression.class); } public Set<Message> allMessages(ThingMLModel self) { Set<Message> msg = new HashSet<Message>(); for(Thing t : allThings(self)) { msg.addAll(ThingMLHelpers.allMessages(t)); } return msg; } }