/******************************************************************************* * Copyright (c) 2010-2015 Henshin developers. 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: * TU Berlin, University of Luxembourg, SES S.A. *******************************************************************************/ package de.tub.tfs.henshin.tggeditor.util; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.ECollections; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.henshin.model.BinaryFormula; import org.eclipse.emf.henshin.model.Formula; import org.eclipse.emf.henshin.model.Graph; import org.eclipse.emf.henshin.model.HenshinPackage; import org.eclipse.emf.henshin.model.Mapping; import org.eclipse.emf.henshin.model.Module; import org.eclipse.emf.henshin.model.NamedElement; import org.eclipse.emf.henshin.model.NestedCondition; import org.eclipse.emf.henshin.model.Node; import org.eclipse.emf.henshin.model.Rule; import org.eclipse.emf.henshin.model.UnaryFormula; import org.eclipse.emf.henshin.model.Unit; import de.tub.tfs.henshin.tgg.TGG; import de.tub.tfs.henshin.tgg.TGGRule; import de.tub.tfs.henshin.tgg.TggPackage; import de.tub.tfs.henshin.tgg.TripleGraph; import de.tub.tfs.henshin.tgg.interpreter.util.RuleUtil; /** * The Class ModelUtil. */ public class ModelUtil { /** * Gets the epackage references. * * @param model the model * @param parent the parent * @return the e package references */ public static EPackage getSourceModel(Module parent) { for (EPackage epackage : parent.getImports()) { if (epackage.getName().contains("source")) return epackage; } return null; } public static EPackage getTargetModel(Module parent) { for (EPackage epackage : parent.getImports()) { if (epackage.getName().contains("target")) return epackage; } return null; } public static EPackage getCorrespModel(Module parent) { for (EPackage epackage : parent.getImports()) { if (epackage.getName().contains("corresp")) return epackage; } return null; } public static String getEPackageReferences( EPackage model, TGG parent) { String errorMsg = ""; Set<EObject> referencedGraphs = new HashSet<EObject>(); Set<EObject> referencedRules = new HashSet<EObject>(); for (EClassifier clazz : model.getEClassifiers()) { referencedGraphs.addAll(getEObjectsWithReference(parent, clazz, TggPackage.TRIPLE_GRAPH)); referencedRules.addAll(getEObjectsWithReference(parent, clazz, HenshinPackage.RULE)); } for (EObject eObject : referencedGraphs) { if (! errorMsg.isEmpty()) { errorMsg += "\n"; } errorMsg += "\tGraph [" + ((Graph) eObject).getName() + "]"; } for (EObject eObject : referencedRules) { if (! errorMsg.isEmpty()) { errorMsg += "\n"; } errorMsg += "\tRule [" + ((Rule) eObject).getName() + "]"; } return errorMsg.isEmpty() ? null : errorMsg; } /** * Gets the eobjects with reference. * * @param transSys the trans sys * @param clazz the clazz * @param featureID the feature id * @return the e objects with reference */ private static Set<EObject> getEObjectsWithReference(TGG transSys, EClassifier clazz, int featureID) { Set<EObject> referencedEObjects = new HashSet<EObject>(); switch (featureID) { case HenshinPackage.GRAPH: for (Graph graph : transSys.getInstances()) { if (isReferenced(graph, clazz, transSys)) { referencedEObjects.add(graph); } } break; case HenshinPackage.RULE: for (Rule rule : ModelUtil.getRules(transSys)) { if (isReferenced(rule.getLhs(), clazz, transSys)) { referencedEObjects.add(rule); } if (isReferenced(rule.getRhs(), clazz, transSys)) { referencedEObjects.add(rule); } } break; default: break; } return referencedEObjects; } /** * Checks if is referenced. * * @param graph the graph * @param clazz the clazz * @param parent the parent * @return true, if is referenced */ private static boolean isReferenced(Graph graph, EClassifier clazz, Module parent) { for (Node node : graph.getNodes()) { String type = node.getType().getName(); if (clazz.getName().equals(type)) { return true; } } return false; } /** * Gets the new child distinct name. * * @param <Child_T> the generic type * @param obj the obj * @param childFeatureID the child feature id * @param nameBase the name base * @return the new child distinct name */ public static <Child_T extends NamedElement> String getNewChildDistinctName( EObject obj, int childFeatureID, String nameBase) { return getNewChildDistinctName(obj,childFeatureID,nameBase,""); } @SuppressWarnings("unchecked") public static <Child_T extends NamedElement> String getNewChildDistinctName( EObject obj, int childFeatureID, String nameBase,String nameAddition) { HashSet<String> forbiddenNames = new HashSet<String>(); final EStructuralFeature eStructuralFeature = obj.eClass().getEStructuralFeature( childFeatureID); for (Child_T instance : (Collection<Child_T>) obj.eGet(eStructuralFeature)) { forbiddenNames.add(instance.getName()); } // generates a new distinct name int id = 0; String newName; do { newName = nameBase + id++ +nameAddition; } while (forbiddenNames.contains(newName)); return newName; } public static List<Mapping> getMappings(final Formula formula) { if (formula != null) { if (formula instanceof NestedCondition) { return ((NestedCondition) formula).getMappings(); } else if (formula instanceof UnaryFormula) { return getMappings(((UnaryFormula) formula).getChild()); } else { final List<Mapping> result = new ArrayList<Mapping>(); result.addAll(getMappings(((BinaryFormula) formula).getLeft())); result.addAll(getMappings(((BinaryFormula) formula).getRight())); return result; } } return Collections.emptyList(); } /** * Gets the distinct nc name. * * @param graph the graph * @return the distinct nc name */ public static String getDistinctNCName(final Graph graph) { if (graph != null) { final Graph lhs = getLhs(graph); final Formula formula = lhs.getFormula(); final Set<String> forbiddenNames = getExistNames(formula, null); // Generates a distinct name final String nameBase = "AC"; int i = 0; String distinctName; do { distinctName = nameBase + i++; } while(forbiddenNames.contains(distinctName)); return distinctName; } throw new IllegalArgumentException("The given graph must not be null!"); } /** * Gets the exist names. * * @param formula the formula * @param existNames the exist names * @return the exist names */ static Set<String> getExistNames(Formula formula, Set<String> existNames) { if (existNames == null) { existNames = new HashSet<String>(); } if (formula instanceof NestedCondition) { NestedCondition ac = (NestedCondition) formula; Graph conclusion = ac.getConclusion(); if (conclusion != null) { existNames.add(conclusion.getName()); existNames.addAll(getExistNames(conclusion.getFormula(), null)); } } else if (formula instanceof UnaryFormula) { getExistNames(((UnaryFormula) formula).getChild(), existNames); } else if (formula instanceof BinaryFormula) { getExistNames(((BinaryFormula) formula).getLeft(), existNames); getExistNames(((BinaryFormula) formula).getRight(), existNames); } return existNames; } /** * Checks, if the given {@code graph} is a LHS. * @param graph The graph to check. * @return {@code true} if the given {@code graph} is a LHS, * {@code false} otherwise. */ public static boolean isLhs(final Graph graph) { if (graph != null) { final Rule rule = getRule(graph); if (rule != null) { return graph.equals(rule.getLhs()); } } return false; } /** * Gets a rule which contains the given {@code graph} * and returns the LHS. * @param graph A graph whose LHS is found. * @return A LHS of the given {@code graph}. */ private static Graph getLhs(Graph graph) { if (graph != null) { EObject parent = graph.eContainer(); while (parent != null && ! (parent instanceof Rule)) { parent = parent.eContainer(); } if (parent != null && parent instanceof Rule) { return ((Rule) parent).getLhs(); } } return null; } /** * Gets the all nacs. * * @param rule the rule * @return the all nacs */ public static List<NestedCondition> getAllNacs(Rule rule) { List<NestedCondition> result = new ArrayList<NestedCondition>(); Graph lhs = rule.getLhs(); Formula formula = lhs.getFormula(); getAllNacs(result, formula); return result; } /** * Gets the all nacs. * * @param nacs the nacs * @param formula the formula * @return the all nacs */ private static void getAllNacs(List<NestedCondition> nacs, Formula formula) { if (nacs == null) { nacs = new ArrayList<NestedCondition>(); } if (formula instanceof NestedCondition) { nacs.add((NestedCondition) formula); } else if (formula instanceof BinaryFormula) { BinaryFormula binaryFormula = (BinaryFormula) formula; getAllNacs(nacs, binaryFormula.getLeft()); getAllNacs(nacs, binaryFormula.getRight()); } } /** * Gets the trans system. * * @param eObject the e object * @return the trans system */ public static Module getTransSystem(EObject eObject){ EObject eo = eObject; while (! (eo instanceof Module)){ if (eo.eContainer() == null){ return null; } eo =eo.eContainer(); } return (Module) eo; } /** * Gets the rule. * * @param object the object * @return the rule */ public static Rule getRule(EObject object){ Rule rule=null; EObject f=object; while (!(f instanceof Rule) && f!=null){ f=f.eContainer(); } if (f!=null){ rule = (Rule) f; } return rule; } /** * @param rule Rule to check. * @param isLhs This value is only evaluated if the given rule is used * as multi rule in amalgamation unit. Otherwise, this value is not relevant. * @return The mapping list. */ /*public static List<Mapping> getMappings(final Rule rule, final boolean isLhs) { final AmalgamationUnit aUnit = getAmalgamationUnit(rule); if (aUnit == null) { return rule.getMappings(); } else { if (isLhs) { return aUnit.getLhsMappings(); } else { return aUnit.getRhsMappings(); } } }*/ /** * Checks, if the given {@code rule} is used as multi rule in amalgamation unit * and returns the unit or {@code null} otherwise. * @param rule Rule to check. * @return Amalgamation unit which use the given {@code rule} as multi rule. */ /*public static AmalgamationUnit getAmalgamationUnit(final Rule rule) { if (rule != null && rule.eContainer() instanceof Module) { final Module transSystem = (Module) rule.eContainer(); for (Unit unit : transSystem.getTransformationUnits()) { if (unit instanceof AmalgamationUnit) { final AmalgamationUnit aUnit = (AmalgamationUnit) unit; if (aUnit.getKernelRule() == rule) { return aUnit; } for (Rule multiRule : aUnit.getMultiRules()) { if (rule == multiRule) { return aUnit; } } } } } return null; }*/ /*public static AmalgamationUnit getAmalgamationUnit(final Graph graph) { if (graph != null && graph.eContainer() instanceof Rule) { final Rule rule = (Rule) graph.eContainer(); return getAmalgamationUnit(rule); } return null; }*/ /*public static boolean graphInKernelRule(final Graph graph) { if (graph != null && graph.eContainer() instanceof Rule) { final Rule rule = (Rule) graph.eContainer(); final AmalgamationUnit aUnit = getAmalgamationUnit(rule); if (aUnit != null) { final Rule kernelRule = aUnit.getKernelRule(); return kernelRule != null && (graph == kernelRule.getLhs() || graph == kernelRule.getRhs()); } } return false; }*/ /*public static boolean graphInMultiRule(final Graph graph) { if (graph != null && graph.eContainer() instanceof Rule) { final Rule rule = (Rule) graph.eContainer(); final AmalgamationUnit aUnit = getAmalgamationUnit(rule); if (aUnit != null) { for (Rule multiRule : aUnit.getMultiRules()) { if (graph == multiRule.getLhs() || graph == multiRule.getRhs()) { return true; } } } } return false; }*/ /*public static boolean nodeInKernelRule(final Node node) { if (node != null) { final Graph graph = (Graph) node.eContainer(); return graphInKernelRule(graph); } return false; }*/ /** * Checks, if the given {@code node} is an image node in multi rule * and the origin node in kernel rule. * @param node Node to check. * @return {@code true} if the given {@code node} is an image node * in multi rule with origin node in kernel rule, {@code false} otherwise. */ // public static boolean imageNodeInMultiRule(final Node node) { // if (node != null) { // final Graph graph = (Graph) node.eContainer(); // final AmalgamationUnit aUnit = getAmalgamationUnit(graph); // if (aUnit != null) { // for (Mapping mapping : aUnit.getLhsMappings()) { // if (mapping.getImage() == node) { // return true; // } // } // for (Mapping mapping : aUnit.getRhsMappings()) { // if (mapping.getImage() == node) { // return true; // } // } // } // } // return false; // } /** * Checks, if the given node is in multi rule and is not mapped with * a node in kernel rule. * @param node Node to check. * @return {@code true} if the given node is in multi rule and is not * mapped with a node in kernel rule, {@code false} otherwise. */ // public static boolean noMappedNodeInMultiRule( // final AmalgamationUnit aUnit, final Node node) { // if (aUnit != null) { // for (Mapping mapping : aUnit.getLhsMappings()) { // if (mapping.getOrigin() == node // || mapping.getImage() == node) { // return false; // } // } // // for (Mapping mapping : aUnit.getRhsMappings()) { // if (mapping.getOrigin() == node // || mapping.getImage() == node) { // return false; // } // } // } // return true; // } // // public static boolean mappingComplete(final AmalgamationUnit aUnit) { // final int kernelMultiNodeCount = getKernelMultiNodeCount(aUnit); // if (kernelMultiNodeCount != // aUnit.getLhsMappings().size() + aUnit.getRhsMappings().size()) { // return false; // } // // return true; // } // // private static int getKernelMultiNodeCount(final AmalgamationUnit aUnit) { // int size = 0; // for (Rule rule : aUnit.getMultiRules()) { // size += rule.getLhs().getNodes().size(); // size += rule.getRhs().getNodes().size(); // } // return size; // } // // public static List<Node> getImageNodesInMulti(final Node nodeInKernel) { // final List<Node> imageNodes = new ArrayList<Node>(); // if (nodeInKernel != null) { // final Graph graph = (Graph) nodeInKernel.eContainer(); // if (ModelUtil.graphInKernelRule(graph)) { // final AmalgamationUnit aUnit = ModelUtil // .getAmalgamationUnit(graph); // if (aUnit != null) { // List<Mapping> mappings = aUnit.getLhsMappings(); // if (!ModelUtil.isLhs(graph)) { // mappings = aUnit.getRhsMappings(); // } // // for (Mapping mapping : mappings) { // if (mapping.getOrigin() == nodeInKernel) { // imageNodes.add(mapping.getImage()); // } // } // } // } // } // return imageNodes; // } // // public static Node getOriginNodeFromKernel(final Node imageNode) { // if (imageNode != null) { // final Graph graph = (Graph) imageNode.eContainer(); // if (! nodeInKernelRule(imageNode)) { // final AmalgamationUnit aUnit = ModelUtil // .getAmalgamationUnit(graph); // if (aUnit != null) { // List<Mapping> mappings = aUnit.getLhsMappings(); // if (! ModelUtil.isLhs(graph)) { // mappings = aUnit.getRhsMappings(); // } // // for (Mapping mapping : mappings) { // if (mapping.getImage() == imageNode) { // return mapping.getOrigin(); // } // } // } // } // } // return null; // } public static boolean isOpRule(Rule rule) { if (rule instanceof TGGRule && !RuleUtil.TGG_RULE.equals(((TGGRule) rule).getMarkerType())) return true; return false; } public static EList<Rule> getRules(Module m) { EList<Rule> rules = new BasicEList<Rule>(); for (Unit unit : m.getUnits()) { if (unit instanceof Rule) { rules.add((Rule) unit); } } return ECollections.unmodifiableEList(rules); } }