/** * Copyright (c) 2016 committers of YAKINDU and others. * 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: * Axel Terfloth - initial API and implementation */ package org.yakindu.sct.model.sgraph.util; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.eclipse.emf.ecore.EObject; import org.yakindu.base.base.NamedElement; import org.yakindu.sct.model.sgraph.Region; import org.yakindu.sct.model.sgraph.Transition; import org.yakindu.sct.model.sgraph.Vertex; /** * Provides a collection of static functions that perform set operations and calculate derived properties based on the sgraph structure. * * @author terfloth */ public class SGgraphUtil { /** * Calculates the common ancestor of to EObjects * * @param o1 * @param o2 * @return */ public static EObject commonAncestor(EObject o1, EObject o2) { List<EObject> o1Anchestors = collectAncestors(o1, new ArrayList<EObject>()); List<EObject> o2Anchestors = collectAncestors(o2, new ArrayList<EObject>()); return findCommonAncestor(o1Anchestors, o2Anchestors); } /** * Calculates the common ancestor of to EObjects based on two ancestor list. The lists are compareredstarting from the root. * The last same element is the common ancestor. * * @param o1Anchestors * @param o2Anchestors * @return */ public static EObject findCommonAncestor(List<EObject> o1Anchestors, List<EObject> o2Anchestors) { int max = Math.min(o1Anchestors.size(), o2Anchestors.size()); EObject commonAncestor = null; for (int i=0; i<max; i++) { if (o1Anchestors.get(i) == o2Anchestors.get(i)) { commonAncestor = o1Anchestors.get(i); } else { break; // do not continue if we came across different amcestors. } } return commonAncestor; } /** * Adds all ancestors of an EObject to the provided list. Ancestors are all eContainers starting from the specified element. The ancestors are added starting with the root. * * @param o1 The EObject instance for which we want to get the ancestors. * @param al A list where the ancestors are added. * @return The list with ancestors (same as @param al) */ public static List<EObject> collectAncestors(EObject o1, List<EObject> al) { if ( o1 != null ) { if ( o1.eContainer() != null ) { collectAncestors(o1.eContainer(), al); al.add(o1.eContainer()); } } return al; } /** * Checks if all provided vertices are orthogonal to each other. * * @param vertices * @return true if the vertices are orthogonal to each other. */ public static boolean areOrthogonal(List<Vertex> vertices) { if (vertices == null || vertices.isEmpty()) return true; List<List<EObject>> ancestorLists = new ArrayList<List<EObject>>(); for (Vertex vertex : vertices) { ancestorLists.add(collectAncestors(vertex, new ArrayList<EObject>())); } // check all pairs of verices for orthogonality ... for ( int i=0; i<vertices.size()-1; i++) { for ( int j=i+1; j<vertices.size(); j++) { // ... by checking their common ancestor. f it is a region then the pair of vertices are not orthogonal. EObject commonAncestor = findCommonAncestor(ancestorLists.get(i), ancestorLists.get(j)); if ( commonAncestor instanceof Region ) { return false; } } } return true; } /** * Provides a list of Vertex objects that are source of the provided transitions. * * @param transitions * @return */ public static List<Vertex> sources(List<Transition> transitions) { List<Vertex> vertices = new ArrayList<Vertex>(); for (Transition transition : transitions) { vertices.add(transition.getSource()); } return vertices; } /** * Provides a list of Vertex objects that are target of the provided transitions. * * @param transitions * @return */ public static List<Vertex> targets(List<Transition> transitions) { List<Vertex> vertices = new ArrayList<Vertex>(); for (Transition transition : transitions) { vertices.add(transition.getTarget()); } return vertices; } /** * Returns the first NamedElement from the specified collection that matches the specified name. * * @param coll * @param name * @return */ public static <T extends NamedElement> T firstNamed(Collection<T> coll, String name) { for (T t : coll) { if (name.equals(t.getName())) return t; } return null; } }