/** * */ package agg.xt_basis; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Vector; import java.util.Enumeration; import agg.attribute.AttrContext; import agg.attribute.AttrMapping; import agg.attribute.impl.CondMember; import agg.attribute.impl.CondTuple; import agg.attribute.impl.ContextView; import agg.attribute.impl.ValueMember; import agg.attribute.impl.ValueTuple; import agg.attribute.impl.VarMember; import agg.attribute.impl.VarTuple; import agg.cons.AtomApplConstraint; import agg.cons.EvalSet; import agg.cons.Evaluable; import agg.cons.Formula; import agg.util.Pair; import agg.util.Triple; import agg.xt_basis.csp.CompletionPropertyBits; /** * @author olga * */ public final class MatchHelper { protected static String errorMsg = ""; /** * Check whether each object of the target graph of the specified application * condition <code>cond</code> which does not have a pre-image in the source graph * can be mapped (domain is not empty) into the target graph of the specified match. * @param match * @param cond * @return true if domain is empty, otherwise false */ public static boolean isDomainOfApplCondEmpty(Match match, OrdinaryMorphism cond) { final Iterator<Node> en = cond.getTarget().getNodesSet().iterator(); while (en.hasNext()) { Node go = en.next(); if (!cond.getInverseImage(go).hasMoreElements()) { HashSet<GraphObject> v = match.getTarget().getTypeObjectsMap().get(go.convertToKey()); if (v == null || v.isEmpty()) return true; } } final Iterator<Arc> en1 = cond.getTarget().getArcsSet().iterator(); while (en1.hasNext()) { Arc go = en1.next(); if (!cond.getInverseImage(go).hasMoreElements()) { if (go.isArc()) { String keystr = go.convertToKey(); HashSet<GraphObject> v = match.getTarget().getTypeObjectsMap().get(keystr); if (v == null || v.isEmpty()) return true; } } } return false; } public static OrdinaryMorphism makeTestStep( final Match m2, boolean allowVariables, boolean similarVariableName) { // make test step to check post conditions: // - type graph constraints ( edge type multiplicity ) // - graph constraints errorMsg = ""; try { // final TestStep s = new TestStep(); final OrdinaryMorphism co_match = (OrdinaryMorphism) TestStep.execute(m2, allowVariables, similarVariableName); return co_match; } catch (TypeException e) { // System.out.println(e.getLocalizedMessage()); errorMsg = e.getMessage(); return null; } } public static boolean isDanglingPoint(final Match match, final GraphObject obj, final GraphObject img) { if (match.getCompletionStrategy().getProperties().get( CompletionPropertyBits.DANGLING)) { if (obj.isNode() && match.getRule().getImage(obj) == null) { if (((Node) obj).getNumberOfArcs() != ((Node) img).getNumberOfArcs()) { return true; } } } return false; } /** * Check Dangling condition for nodes to delete. * All edges of the image node must have a pre-image in the match. * @param match * @return error message if check failed, otherwise - empty string */ public static String isDanglingSatisfied(final Match match) { errorMsg = ""; if (match.getCompletionStrategy().getProperties().get( CompletionPropertyBits.DANGLING)) { final Iterator<Node> objects = match.getRule().getSource().getNodesSet().iterator(); while (objects.hasNext()) { final Node x = objects.next(); if (match.getRule().getImage(x) == null) { final Node y = (Node) match.getImage(x); if (y != null) { if (match.getCompletionStrategy().getProperties().get( CompletionPropertyBits.INJECTIVE)) { if (x.getNumberOfArcs() < y.getNumberOfArcs()) { errorMsg = "Dangling condition isn't satisfied! ( node: "+x.getType().getName()+" )"; return errorMsg; } } else { // match is non-injective Iterator<Arc> arcs = y.getIncomingArcs(); while (arcs.hasNext()) { Enumeration<GraphObject> en = match.getInverseImage(arcs.next()); if (!en.hasMoreElements()) { errorMsg = "Dangling condition isn't satisfied! ( node: "+x.getType().getName()+" )"; return errorMsg; } } arcs = y.getOutgoingArcs(); while (arcs.hasNext()) { Enumeration<GraphObject> en = match.getInverseImage(arcs.next()); if (!en.hasMoreElements()) { errorMsg = "Dangling condition isn't satisfied! ( node: "+x.getType().getName()+" )"; return errorMsg; } } } } } } } return ""; } /** * Check Identification condition for non-injective match objects. * They are must be preserved. * @param match * @return error message if check failed, otherwise - empty string */ public static String isIdentSatisfied(final Match match) { errorMsg = ""; if (!match.getCompletionStrategy().getProperties().get( CompletionPropertyBits.INJECTIVE) && match.getCompletionStrategy().getProperties().get( CompletionPropertyBits.IDENTIFICATION)) { final Rule itsRule = match.getRule(); // check nodes first final Iterator<Node> nodes = itsRule.getOriginal().getNodesSet().iterator(); while (nodes.hasNext()) { int k = 0; boolean preserved = true; final Enumeration<GraphObject> en = match.getInverseImage(match.getImage(nodes.next())); int del = 0; while (en.hasMoreElements()) { final GraphObject xx = en.nextElement(); k++; if (itsRule.getImage(xx) == null) { preserved = false; del++; } } if (k > 1 && !preserved && k > del) { errorMsg = "Identification condition isn't satisfied!"; return errorMsg; } } // now check arcs final Iterator<Arc> arcs = itsRule.getOriginal().getArcsSet().iterator(); while (arcs.hasNext()) { int k = 0; boolean preserved = true; final Enumeration<GraphObject> en = match.getInverseImage(match.getImage(arcs.next())); int del = 0; while (en.hasMoreElements()) { final GraphObject xx = en.nextElement(); k++; if (itsRule.getImage(xx) == null) { preserved = false; del++; } } if ((k > 1) && !preserved && k > del) { errorMsg = "Identification condition isn't satisfied!"; return errorMsg; } } } return ""; } /** * * @param rule * @param testComatch * @param testMatch * @return error message if check failed, otherwise - empty string */ public static String isConsistent(final Rule rule, final OrdinaryMorphism testComatch, final OrdinaryMorphism testMatch) { // check consistency errorMsg = ""; Vector<Formula> constraints = rule.getConstraints(); if (!constraints.isEmpty()) { boolean good = true; for (int i = 0; i < constraints.size(); i++) { Formula f = constraints.get(i); if (!f.isEnabled()) continue; Vector<Evaluable> vec = new Vector<Evaluable>(); String form = f.getAsString(vec); // do copy of vec into v Vector<Evaluable> v = new Vector<Evaluable>(); for (int j = 0; j < vec.size(); j++) { EvalSet evalset = (EvalSet) vec.get(j); Vector<Object> set = evalset.getSet(); Vector<Object> v1 = new Vector<Object>(); for (int k = 0; k < set.size(); k++) { Vector<Object> es = ((EvalSet) set.get(k)).getSet(); AtomApplConstraint aaConstr = new AtomApplConstraint(es); v1.add(aaConstr); } v.add(new EvalSet(v1)); } Formula f1 = new Formula(true); f1.setFormula(v, form); boolean b = f1.eval(new Pair<Morphism, Morphism>(testComatch, testMatch)); good &= b; if (!good) { errorMsg = "Post application condition of the rule " + rule.getName() +" failed"; break; } } return errorMsg; } return ""; } /** * * @param match * @return error message if check failed, otherwise - empty string */ public static String attributesOfGlueObjectsCorrect(final Match match) { errorMsg = ""; if (!match.getCompletionStrategy().getProperties().get( CompletionPropertyBits.INJECTIVE)){ // check attributes : // attributes of glue object must have the same value as of keep // object attrsOfGlueObjectsCorrect(match, match.getImage().getNodesSet().iterator()); attrsOfGlueObjectsCorrect(match, match.getImage().getArcsSet().iterator()); } return errorMsg; } private static String attrsOfGlueObjectsCorrect( final Match match, final Iterator<?> elems) { // check attributes : // attributes of glue object must have the same value as of keep // object while (elems.hasNext()) { GraphObject go = (GraphObject) elems.next(); if (go.getAttribute() == null) continue; final Enumeration<GraphObject> invers = match.getInverseImage(go); final Vector<GraphObject> origs = new Vector<GraphObject>(2); while (invers.hasMoreElements()) { origs.addElement(invers.nextElement()); } if (origs.size() <= 1) continue; final Vector<GraphObject> ruleImgs = new Vector<GraphObject>(2); for (int i = 0; i < origs.size(); i++) { GraphObject ruleImg = match.getRule().getImage(origs.elementAt(i)); if (ruleImg != null) ruleImgs.addElement(ruleImg); } if (ruleImgs.size() <= 1) continue; GraphObject ruleImg = ruleImgs.elementAt(0); if (ruleImg.getAttribute() == null) continue; ValueTuple imgAttrs = (ValueTuple) ruleImg.getAttribute(); GraphObject ruleOrig = match.getRule().getInverseImage(ruleImg).nextElement(); for (int i=1; i<ruleImgs.size(); i++) { GraphObject otherRuleImg = ruleImgs.elementAt(i); if (otherRuleImg.getAttribute() == null) continue; boolean replace1 = true; ValueTuple otherAttrs = (ValueTuple) otherRuleImg.getAttribute(); GraphObject otherOrig = match.getRule().getInverseImage(otherRuleImg).nextElement(); for (int j = 0; j < imgAttrs.getNumberOfEntries(); j++) { ValueMember vmImg = imgAttrs.getValueMemberAt(j); if (vmImg != null) { String attrName = vmImg.getName(); ValueMember vmOtherImg = otherAttrs.getValueMemberAt(attrName); if (vmOtherImg != null) { if (vmImg.getExpr() == null) continue; if (vmOtherImg.getExpr() != null) { if (!vmImg.getExprAsText().equals( vmOtherImg.getExprAsText())) { boolean attrFailed = vmImg.getExpr().isComplex() && vmOtherImg.getExpr().isComplex(); if (!attrFailed) { attrFailed = vmImg.getExpr().isConstant() && vmOtherImg.getExpr().isConstant(); if (attrFailed) { ValueMember govm = ((ValueTuple) go.getAttribute()).getValueMemberAt(attrName); if (!vmImg.getExprAsText().equals(govm.getExprAsText())) replace1 = false; else attrFailed = false; if (attrFailed && !vmOtherImg.getExprAsText().equals(govm.getExprAsText())) { replace1 = true; attrFailed = true; } else attrFailed = false; } } if (!attrFailed) { boolean varchanged1 = false; if (vmImg.getExpr().isVariable()) { ValueTuple origAttrs = (ValueTuple) ruleOrig.getAttribute(); if(origAttrs != null) { ValueMember vmRuleOrig = origAttrs.getValueMemberAt(attrName); if((vmRuleOrig != null) && vmRuleOrig.isSet() && vmRuleOrig.getExpr().isVariable() && !vmRuleOrig.getExprAsText().equals( vmImg.getExprAsText())) { if (!isVariableUsed(vmImg, origs)) { varchanged1 = true; replace1 = true; } } } } boolean varchanged2 = false; if (vmOtherImg.getExpr().isVariable()) { ValueTuple otherOrigAttrs = (ValueTuple) otherOrig.getAttribute(); if(otherOrigAttrs != null) { ValueMember vmOtherOrig = otherOrigAttrs.getValueMemberAt(attrName); if((vmOtherOrig != null) && vmOtherOrig.isSet() && vmOtherOrig.getExpr().isVariable() && !vmOtherOrig.getExprAsText().equals( vmOtherImg.getExprAsText())) { if (!isVariableUsed(vmOtherImg, origs)) { varchanged2 = true; replace1 = false; } } } } attrFailed = varchanged1 && varchanged2; } if (attrFailed) { errorMsg = "The rule <" + match.getRule().getName()+ "> " + "can produce an attr. conflict \nfor objects of the type " + "<"+ ruleImg.getType().getName()+ "> " + " and " + "<"+ otherRuleImg.getType().getName()+ "> " + " \nwhich change the value of the same attribute."; return errorMsg; } } } } } } if ((i<ruleImgs.size()) && replace1) { ruleImg = otherRuleImg; imgAttrs = (ValueTuple) ruleImg.getAttribute(); ruleOrig = match.getRule().getInverseImage(ruleImg).nextElement(); } } } return ""; } private static boolean isVariableUsed(final ValueMember vm, final Vector<GraphObject> objs) { boolean varUsed = false; for (int i = 1; i < objs.size(); i++) { GraphObject go = objs.elementAt(i); ValueTuple goAttr = (ValueTuple) go.getAttribute(); if (go.getAttribute() == null) continue; ValueMember goAttrvm = goAttr.getValueMemberAt(vm.getName()); if (goAttrvm != null && goAttrvm.isSet() && goAttrvm.getExprAsText().equals(vm.getExprAsText())) { varUsed = true; break; } } return varUsed; } /** * Checks multiplicity of node resp. edge types due to the type graph of * the given match. * @param match * @return Error string if check failed, otherwise - empty string. */ public static String isTypeMultiplicitySatisfied(final Match match) { errorMsg = ""; int tgchecklevel = match.getSource().getTypeSet().getLevelOfTypeGraphCheck(); if (tgchecklevel <= TypeSet.ENABLED) { return ""; } final Rule itsRule = match.getRule(); match.clearErrorMsg(); List<String> typesNeedMultiplicityCheck = itsRule.getTypesWhichNeedMultiplicityCheck(); if (typesNeedMultiplicityCheck.isEmpty()) { return ""; } final List<Node> nodestodelete = new Vector<Node>(); // LHS objects final List<Node> nodestocreate = new Vector<Node>(); // RHS objects final List<Arc> arcstodelete = new Vector<Arc>(); // LHS objects final List<Arc> arcstocreate = new Vector<Arc>(); // RHS objects final List<Arc> insOfDelNode = new Vector<Arc>(); // Host graph objects final List<Arc> outsOfDelNode = new Vector<Arc>(); // Host graph objects final List<GraphObject> nodestoglue = new Vector<GraphObject>(); // get nodes to delete: Iterator<?> en = itsRule.getLeft().getNodesSet().iterator(); while (en.hasNext()) { final Node go = (Node) en.next(); if (itsRule.getImage(go) == null) { nodestodelete.add(go); final Node n = (Node) match.getImage(go); insOfDelNode.addAll(n.getIncomingArcsSet()); outsOfDelNode.addAll(n.getOutgoingArcsSet()); } } // get arcs to delete only, source and target preserved en = itsRule.getLeft().getArcsSet().iterator(); while (en.hasNext()) { Arc go = (Arc) en.next(); if (itsRule.getImage(go) == null) { if (itsRule.getImage(go.getSource()) != null && itsRule.getImage(go.getTarget()) != null) { arcstodelete.add(go); } } } // get nodes to create: en = itsRule.getRight().getNodesSet().iterator(); while (en.hasNext()) { GraphObject go = (GraphObject) en.next(); if (!itsRule.getInverseImage(go).hasMoreElements()) { nodestocreate.add((Node)go); } } // get arcs (with preserved source or target) to create en = itsRule.getRight().getArcsSet().iterator(); while (en.hasNext()) { final Arc go = (Arc) en.next(); if (!itsRule.getInverseImage(go).hasMoreElements() && (itsRule.getInverseImage(go.getSource()).hasMoreElements() || itsRule.getInverseImage(go.getTarget()).hasMoreElements()) ) { arcstocreate.add(go); } } // check nodes to delete // check only node type multiplicity int vecSize = nodestodelete.size(); for (int i = 0; i < vecSize; i++) { final Node go = nodestodelete.get(i); if (go.isNode()) { if (!checkNodeMultiplicity( typesNeedMultiplicityCheck, match, go, i + 1, nodestodelete, nodestocreate, nodestoglue, tgchecklevel)) return errorMsg; vecSize = nodestodelete.size(); } } // check remained nodes to create vecSize = nodestocreate.size(); for (int i = 0; i < vecSize; i++) { final Node go = nodestocreate.get(i); if (!checkNodeMaxMultiplicity( typesNeedMultiplicityCheck, match, go, i + 1, nodestocreate, nodestoglue, tgchecklevel)) return errorMsg; vecSize = nodestocreate.size(); } // check edge multiplicity due to edge to delete if (!checkEdgeMultiplicityDueToEdgeToDelete( typesNeedMultiplicityCheck, match, insOfDelNode, outsOfDelNode, arcstodelete, arcstocreate, nodestoglue, tgchecklevel)) { return errorMsg; } // List<Arc> arcstocreatecopy = new Vector<Arc>(arcstocreate); // check remained arcs to create // these arcs must preserve source and target if (!checkEdgeTargetMaxMultiplicity( typesNeedMultiplicityCheck, match, arcstocreate, tgchecklevel)) { return errorMsg; } if (!checkEdgeSourceMaxMultiplicity( typesNeedMultiplicityCheck, match, arcstocreate, tgchecklevel)) { return errorMsg; } return ""; } private static boolean checkEdgeMultiplicityDueToEdgeToDelete( final List<String> typesNeedMultiplicityCheck, final Match match, final List<Arc> incomsofnodetodelete, // Host graph objects final List<Arc> outcomsofnodetodelete, // Host graph objects final List<Arc> arcstodelete, // LHS objects final List<Arc> arcstocreate, // RHS objects final List<GraphObject> nodestoglue, int tgchecklevel) { final Map<String, List<Arc>> type2newarcs = new Hashtable<String, List<Arc>>(); // type2newarcs contains RHS arcs // sorted by Arc.convertToKey() string which contains // name of source and target type, too for (int i=0; i<arcstocreate.size(); i++) { // Arc of RHS final Arc a = arcstocreate.get(i); // final String typekey = a.convertToKey(); final List<String> typekeys = a.convertToKeyParentExtended(); for (int l=0; l<typekeys.size(); l++) { final String typekey = typekeys.get(l); List<Arc> list = type2newarcs.get(typekey); if (list == null) { list = new Vector<Arc>(); type2newarcs.put(typekey, list); } list.add(a); } } final Map<String, List<Arc>> type2delarcs = new Hashtable<String, List<Arc>>(); final Map<String, List<Arc>> type2delarcs2 = new Hashtable<String, List<Arc>>(); // type2delarcs will contain edges of the HostGraph // sorted by type.convertToKey() which contains // name of source and target type, too // arcs to delete with source and target to preserve for (int i=0; i<arcstodelete.size(); i++) { // Arc of LHS final Arc da = arcstodelete.get(i); final String typekey = da.convertToKey(); // Arc of Host Graph final Arc a = (Arc) match.getImage(da); // final List<String> typekeys = da.convertToKeyParentExtended(); // for (int l=0; l<typekeys.size(); l++) { // final String typekey = typekeys.get(l); if (typesNeedMultiplicityCheck.contains(typekey)) { List<Arc> list = type2delarcs.get(typekey); if (list == null) { list = new Vector<Arc>(); type2delarcs.put(typekey, list); } list.add(a); List<Arc> list2 = type2delarcs2.get(typekey); if (list2 == null) { list2 = new Vector<Arc>(); type2delarcs2.put(typekey, list2); } list2.add(a); } // } } for (int i=0; i<incomsofnodetodelete.size(); i++) { // Arc of Host Graph final Arc a = incomsofnodetodelete.get(i); final String typekey = a.convertToKey(); if (typesNeedMultiplicityCheck.contains(typekey)) { List<Arc> list = type2delarcs.get(typekey); if (list == null) { list = new Vector<Arc>(); type2delarcs.put(typekey, list); } list.add(a); } } // check the edge type target multiplicity if (!checkEdgeTargetMinMaxMultiplicity(match, type2delarcs, type2newarcs, arcstocreate, tgchecklevel)) { return false; } for (int i=0; i<outcomsofnodetodelete.size(); i++) { // Arc of Host Graph final Arc a = outcomsofnodetodelete.get(i); final String typekey = a.convertToKey(); if (typesNeedMultiplicityCheck.contains(typekey)) { List<Arc> list = type2delarcs2.get(typekey); if (list == null) { list = new Vector<Arc>(); type2delarcs2.put(typekey, list); } list.add(a); } } // check the edge type source multiplicity if (!checkEdgeSourceMinMaxMultiplicity(match, type2delarcs2, type2newarcs, arcstocreate, tgchecklevel)) { return false; } return true; } private static boolean checkEdgeTargetMinMaxMultiplicity( final Match match, final Map<String, List<Arc>> type2delarcs, final Map<String, List<Arc>> type2newarcs, final List<Arc> arcstocreate, int tgchecklevel) { errorMsg = ""; final List<Triple<Node, Type, Type>> srcNodes = new Vector<Triple<Node, Type, Type>>(); final List<Integer> ndel = new Vector<Integer>(); final List<Pair<Integer,Integer>> tarMinMax = new Vector<Pair<Integer,Integer>>(); Iterator<String> iter = type2delarcs.keySet().iterator(); while (iter.hasNext()) { final String typekey = iter.next(); final List<Arc> incoms = type2delarcs.get(typekey); for (int j = 0; j<incoms.size(); j++) { final Arc a = incoms.get(j); // edge in host graph int indx = getIndexOfNode(srcNodes, (Node)a.getSource(), a.getType(), a.getTargetType()); if (indx >= 0) { int nn = ndel.get(indx).intValue()+1; ndel.add(indx, new Integer(nn)); ndel.remove(indx+1); } else { final List<Arc> newarcs = type2newarcs.get(typekey); int nn = 0; if (newarcs != null) { if (match.getInverseImage(a.getSource()).hasMoreElements()) { nn = getCountOfArcsWithTypeAndSource(typekey, match.getRule().getImage(match.getInverseImage(a.getSource()).nextElement()), newarcs, arcstocreate); } } srcNodes.add(new Triple<Node, Type, Type>((Node)a.getSource(), a.getType(), a.getTargetType())); indx = srcNodes.size()-1; if (nn > 0) nn--; else nn = 1; ndel.add(new Integer(nn)); int tarMin = a.getType().getTargetMin(a.getSource().getType(), a.getTarget().getType()); int tarMax = a.getType().getTargetMax(a.getSource().getType(), a.getTarget().getType()); tarMinMax.add(new Pair<Integer,Integer>(new Integer(tarMin), new Integer(tarMax))); } Type targetNodeType = a.getTarget().getType(); Vector<Arc> vec = match.getTarget().getTypeSet().getTypeGraph().getArcs(a.getType()); if (vec != null) { if (vec.size() == 1) { Arc typeArc = vec.get(0); targetNodeType = typeArc.getTarget().getType(); } else { for (int k=0; k<vec.size(); k++) { Arc typeArc = vec.get(k); if (typeArc.getSourceType().isParentOf(a.getSourceType()) && typeArc.getTargetType().isParentOf(a.getTargetType())) { targetNodeType = typeArc.getTarget().getType(); break; } } } } int nn = ndel.get(indx).intValue(); final Node src = srcNodes.get(indx).first; int outs = src.getNumberOfOutgoingArcs(a.getType(), targetNodeType); if (tgchecklevel > TypeSet.ENABLED_MAX && tarMinMax.get(indx).first.intValue() > 0 && (outs - nn) < tarMinMax.get(indx).first.intValue()) { if (match.getRule().getImage(match.getInverseImage(a.getSource()).nextElement()) != null) { // source node preserved, the edge deleted errorMsg = "Target multiplicity of edge type failed!" + "\nType \"" + a.getType().getName() + "\"" + " - target minimum failed."; return false; } } else if (tarMinMax.get(indx).second.intValue() != TypeSet.UNDEFINED && (outs - nn) > tarMinMax.get(indx).second.intValue()) { errorMsg = "Target multiplicity of edge type failed!" + "\nType \"" + a.getType().getName() + "\"" + " - target maximum failed."; return false; } } srcNodes.clear(); ndel.clear(); tarMinMax.clear(); } return true; } private static boolean checkEdgeSourceMinMaxMultiplicity( final Match match, final Map<String, List<Arc>> type2delarcs, final Map<String, List<Arc>> type2newarcs, final List<Arc> arcstocreate, int tgchecklevel) { errorMsg = ""; final List<Triple<Node, Type, Type>> tarNodes = new Vector<Triple<Node, Type, Type>>(); final List<Integer> ndel = new Vector<Integer>(); final List<Pair<Integer,Integer>> srcMinMax = new Vector<Pair<Integer,Integer>>(); Iterator<String> iter = type2delarcs.keySet().iterator(); while (iter.hasNext()) { final String typekey = iter.next(); final List<Arc> outcoms = type2delarcs.get(typekey); for (int j = 0; j<outcoms.size(); j++) { final Arc a = outcoms.get(j); int indx = getIndexOfNode(tarNodes, (Node)a.getTarget(), a.getType(), a.getSourceType()); if (indx >= 0) { int nn = ndel.get(indx).intValue()+1; ndel.set(indx, new Integer(nn)); } else { final List<Arc> newarcs = type2newarcs.get(typekey); int nn = 0; if (newarcs != null && newarcs.size() > 0) { // check inverse image of a match object because dangling condition can be OFF if (match.getInverseImage(a.getTarget()).hasMoreElements()) { nn = getCountOfArcsWithTypeAndTarget(typekey, match.getRule().getImage(match.getInverseImage(a.getTarget()).nextElement()), newarcs, arcstocreate); } } tarNodes.add(new Triple<Node,Type,Type>((Node)a.getTarget(), a.getType(), a.getSourceType())); indx = tarNodes.size()-1; if (nn > 0) nn--; else nn = 1; ndel.add(new Integer(nn)); int srcMin = a.getType().getSourceMin(a.getSource().getType(), a.getTarget().getType()); int srcMax = a.getType().getSourceMax(a.getSource().getType(), a.getTarget().getType()); srcMinMax.add(new Pair<Integer,Integer>(new Integer(srcMin), new Integer(srcMax))); } Type sourceNodeType = a.getSource().getType(); final Vector<Arc> vec = match.getTarget().getTypeSet().getTypeGraph().getArcs(a.getType()); if (vec != null) { if (vec.size() == 1) { Arc typeArc = vec.get(0); sourceNodeType = typeArc.getSource().getType(); } else { for (int k=0; k<vec.size(); k++) { Arc typeArc = vec.get(k); if (typeArc.getSourceType().isParentOf(a.getSourceType()) && typeArc.getTargetType().isParentOf(a.getTargetType())) { sourceNodeType = typeArc.getSource().getType(); break; } } } } int nn = ndel.get(indx).intValue(); final Node tar = tarNodes.get(indx).first; int ins = tar.getNumberOfIncomingArcs(a.getType(), sourceNodeType); if (tgchecklevel > TypeSet.ENABLED_MAX && srcMinMax.get(indx).first.intValue() > 0 && (ins - nn) < srcMinMax.get(indx).first.intValue()) { if (match.getRule().getImage(match.getInverseImage(a.getTarget()).nextElement()) != null) { // target node is preserved, the edge will be deleted errorMsg = "Source multiplicity of edge type failed!" + "\nType \"" + a.getType().getName() + "\"" + " - source minimum failed."; return false; } } else if (srcMinMax.get(indx).second.intValue() != TypeSet.UNDEFINED && (ins - nn) > srcMinMax.get(indx).second.intValue()) { errorMsg = "Source multiplicity of edge type failed!" + "\nType \"" + a.getType().getName() + "\"" + " - source maximum failed."; return false; } } tarNodes.clear(); ndel.clear(); srcMinMax.clear(); } return true; } private static int getCountOfArcsWithTypeAndSource( final String typekey, final GraphObject source, final List<Arc> newarcs, final List<Arc> allnewarcs) { int nn = 0; if (newarcs != null && source != null) { for (int k=0; k<newarcs.size(); k++) { final Arc arc = newarcs.get(k); if (arc.getSource() == source // || arc.getSource().compareTo(source) ) { if (allnewarcs.contains(arc)) { nn++; } } } } return nn; } private static int getCountOfArcsWithTypeAndTarget( final String typekey, final GraphObject target, final List<Arc> newarcs, final List<Arc> allnewarcs) { int nn = 0; if (newarcs != null && target != null) { for (int k=0; k<newarcs.size(); k++) { final Arc arc = newarcs.get(k); if (arc.getTarget() == target // || arc.getTarget().compareTo(target) ) { if (allnewarcs.contains(arc)) { nn++; } } } } return nn; } private static boolean checkEdgeTargetMaxMultiplicity( final List<String> typesNeedMultiplicityCheck, final Match match, final List<Arc> arcstocreate, int tgchecklevel) { errorMsg = ""; final List<Triple<Node, Type, Type>> srcNodes = new Vector<Triple<Node, Type, Type>>(); final List<Integer> nnew = new Vector<Integer>(); final List<Integer> tarMax = new Vector<Integer>(); final Map<String, List<Arc>> type2newarcs = new Hashtable<String, List<Arc>>(); // RHS objects // type2newarcs contains arcs sorted by type.convertToKey() string which contains // name of source and target type, too for (int i=0; i<arcstocreate.size(); i++) { final Arc a = arcstocreate.get(i); final String typekey = a.convertToKey(); List<Arc> list = type2newarcs.get(typekey); if (list == null) { list = new Vector<Arc>(); type2newarcs.put(typekey, list); } list.add(a); } for (int i=0; i<arcstocreate.size(); i++) { final Arc a = arcstocreate.get(i); // Arc a must preserve its source or target if (!match.getRule().getInverseImage(a.getSource()).hasMoreElements() || !typesNeedMultiplicityCheck.contains(a.convertToKey()) ) { continue; } // final String typekey = a.convertToKey(); final Node src = (Node) match.getImage( match.getRule().getInverseImage(a.getSource()).nextElement()); if (src == null) { continue; } int indx = getIndexOfNode(srcNodes, src, a.getType(), a.getTargetType()); if (indx >= 0) { int nn = nnew.get(indx).intValue()+1; nnew.set(indx, new Integer(nn)); } else { // final List<Arc> newarcs = type2newarcs.get(typekey); // int nn = getCountOfArcsWithTypeAndSource(typekey, // a.getSource(), // newarcs, arcstocreate); srcNodes.add(new Triple<Node, Type, Type>(src, a.getType(), a.getTargetType())); indx = srcNodes.size()-1; nnew.add(new Integer(1)); //(nn)); int max = a.getType().getTargetMax(a.getSource().getType(), a.getTarget().getType()); tarMax.add(new Integer(max)); } Type targetNodeType = a.getTarget().getType(); Vector<Arc> vec = match.getTarget().getTypeSet().getTypeGraph().getArcs(a.getType()); if (vec != null) { if (vec.size() == 1) { Arc typeArc = vec.get(0); targetNodeType = typeArc.getTarget().getType(); } else { for (int k=0; k<vec.size(); k++) { Arc typeArc = vec.get(k); if (typeArc.getSourceType().isParentOf(a.getSourceType()) && typeArc.getTargetType().isParentOf(a.getTargetType())) { targetNodeType = typeArc.getTarget().getType(); break; } } } } int nn = nnew.get(indx).intValue(); List<Arc> outarcs = src.getOutgoingArcs(a.getType(), targetNodeType); int outs = outarcs.size(); for (int k=0; k<outarcs.size(); k++) { Arc outarc = outarcs.get(k); if (match.getInverseImage(outarc).hasMoreElements() && match.getRule().getImage(match.getInverseImage(outarc).nextElement()) == null) { outs--; } else if (match.getTarget().getTypeSet().isOutgoingArcOfClan( src.getType(), outarc.getType(), outarc.getTarget().getType())) { if (match.getInverseImage(outarc).hasMoreElements() && match.getRule().getImage(match.getInverseImage(outarc).nextElement()) == null) { outs--; } } } // System.out.println("MatchHelper: Target Max: " // +src.getType().getName()+" " // +a.getType().getName()+" "+outs+" "+nn); if (tarMax.get(indx).intValue() != TypeSet.UNDEFINED && (outs + nn) > tarMax.get(indx).intValue()) { errorMsg = "Target multiplicity of edge type failed!" + "\nType \"" + a.getType().getName() + "\"" + " - target maximum failed."; return false; } if (i < 0) break; } return true; } private static boolean checkEdgeSourceMaxMultiplicity( final List<String> typesNeedMultiplicityCheck, final Match match, final List<Arc> arcstocreate, int tgchecklevel) { errorMsg = ""; final List<Triple<Node, Type, Type>> tarNodes = new Vector<Triple<Node, Type, Type>>(); final List<Integer> nnew = new Vector<Integer>(); final List<Integer> srcMax = new Vector<Integer>(); final Map<String, List<Arc>> type2newarcs = new Hashtable<String, List<Arc>>(); // RHS objects // type2newarcs will contain arcs by type.convertToKey() string // with name of source and target type, too // arcs of arcstocreate are arcs of the RHS of a rule for (int i=0; i<arcstocreate.size(); i++) { final Arc a = arcstocreate.get(i); final String typekey = a.convertToKey(); List<Arc> list = type2newarcs.get(typekey); if (list == null) { list = new Vector<Arc>(); type2newarcs.put(typekey, list); } list.add(a); } for (int i=0; i<arcstocreate.size(); i++) { final Arc a = arcstocreate.get(i); // Arc a must preserve its source and target if ( !match.getRule().getInverseImage(a.getTarget()).hasMoreElements() || !typesNeedMultiplicityCheck.contains(a.convertToKey()) ) { continue; } // final String typekey = a.convertToKey(); // target node in a host graph final Node tar = (Node) match.getImage( match.getRule().getInverseImage(a.getTarget()).nextElement()); if (tar == null) { continue; } // tarNodes, tar in a host graph, a in the RHS int indx = getIndexOfNode(tarNodes, tar, a.getType(), a.getSourceType()); if (indx >= 0) { int nn = nnew.get(indx).intValue()+1; nnew.set(indx, new Integer(nn)); } else { // final List<Arc> newarcs = type2newarcs.get(typekey); // int nn = getCountOfArcsWithTypeAndTarget(typekey, // a.getTarget(), // newarcs, arcstocreate); tarNodes.add(new Triple<Node, Type, Type>(tar, a.getType(), a.getSourceType())); indx = tarNodes.size()-1; nnew.add(new Integer(1)); //nn)); int max = a.getType().getSourceMax(a.getSource().getType(), a.getTarget().getType()); srcMax.add(new Integer(max)); } Type sourceNodeType = a.getSource().getType(); final Vector<Arc> vec = match.getTarget().getTypeSet().getTypeGraph().getArcs(a.getType()); if (vec != null) { if (vec.size() == 1) { Arc typeArc = vec.get(0); sourceNodeType = typeArc.getSource().getType(); } else { for (int k=0; k<vec.size(); k++) { Arc typeArc = vec.get(k); if (typeArc.getSourceType().isParentOf(a.getSourceType()) && typeArc.getTargetType().isParentOf(a.getTargetType())) { sourceNodeType = typeArc.getSource().getType(); break; } } } } int nn = nnew.get(nnew.size()-1).intValue(); List<Arc> inarcs = tar.getIncomingArcs(a.getType(), sourceNodeType); int ins = inarcs.size(); for (int k = 0; k<inarcs.size(); k++) { Arc inarc = inarcs.get(k); if (match.getInverseImage(inarc).hasMoreElements() && match.getRule().getImage(match.getInverseImage(inarc).nextElement()) == null) { ins--; } else if (match.getTarget().getTypeSet().isIncomingArcOfClan( tar.getType(), inarc.getType(), inarc.getSource().getType())) { if (match.getInverseImage(inarc).hasMoreElements() && match.getRule().getImage(match.getInverseImage(inarc).nextElement()) == null) { ins--; } } } // // System.out.println("MatchHelper: Source Max: " // +tar.getType().getName()+" " // +a.getType().getName()+" " +ins+" "+nn); if (srcMax.get(indx).intValue() != TypeSet.UNDEFINED && (ins + nn) > srcMax.get(indx).intValue()) { errorMsg = "Source multiplicity of edge type failed!" + "\nType \"" + a.getType().getName() + "\"" + " - source maximum failed."; return false; } if (i < 0) break; } return true; } private static int getIndexOfNode( final List<Triple<Node, Type, Type>>list, final Node nodeOfArc, final Type arcType, final Type otherType) { // if p.first is the source of an arc of type p.second == arcType, // then p.third is the target of the arc, or wise versa; // p.first and p.third are nodes inside of a host graph, // but in CPA - a graph which can be the LHS | RHS graph of a rule. for (int i=0; i<list.size(); i++) { final Triple<Node, Type, Type> p = list.get(i); if (p.first == nodeOfArc && p.second == arcType) { if (p.third.isInClanOf(otherType)) { return i; } // if (otherType.isParentOf(p.third)) { // return i; // } // // this is in CPA only! // else if (!p.first.getContext().isCompleteGraph() // && p.third.isParentOf(otherType)) { // return i; // } } } return -1; } private static boolean checkNodeMultiplicity( final List<String> typesNeedMultiplicityCheck, final Match match, final Node go, int startindex, final List<Node> todelete, final List<Node> tocreate, final List<GraphObject> nodestoglue, int tgchecklevel) { errorMsg = ""; if (!typesNeedMultiplicityCheck.contains(go.getType().convertToKey())) { return true; } int min = go.getType().getSourceMin(); int max = go.getType().getSourceMax(); int count = 0; if (match.getTarget().getTypeObjectsMap().get(go.getType().convertToKey()) != null) { count = match.getTarget().getTypeObjectsMap().get(go.getType().convertToKey()).size(); } count--; for (int j = startindex; j < todelete.size(); j++) { Node n = todelete.get(j); if (go.getType().isRelatedTo(n.getType())) { count--; todelete.remove(n); j--; } } for (int i = 0; i < tocreate.size(); i++) { Node n = tocreate.get(i); if (go.getType().isRelatedTo(n.getType())) { count++; tocreate.remove(n); i--; } } if (max != TypeSet.UNDEFINED && count > max) { errorMsg = "Node type multiplicity failed!" + "\nType \"" + go.getType().getName() + "\"" + " - maximum failed."; return false; } if (tgchecklevel > TypeSet.ENABLED_MAX && min > 0 && count < min) { errorMsg = "Node type multiplicity failed!" + "\nType \"" + go.getType().getName() + "\"" + " - minimum failed."; return false; } return true; } private static boolean checkNodeMaxMultiplicity( final List<String> typesNeedMultiplicityCheck, final Match match, final Node go, int startindex, final List<Node> tocreate, final List<GraphObject> nodesofglue, int tgchecklevel) { errorMsg = ""; if (!typesNeedMultiplicityCheck.contains(go.getType().convertToKey())) { return true; } int max = go.getType().getSourceMax(); if (max == TypeSet.UNDEFINED) return true; int count = 0; if (match.getTarget().getTypeObjectsMap().get(go.getType().convertToKey()) != null) { count = match.getTarget().getTypeObjectsMap().get(go.getType().convertToKey()).size(); } count++; for (int c = startindex; c < tocreate.size(); c++) { final Node goc = tocreate.get(c); if (go.getType().isRelatedTo(goc.getType())) { count++; tocreate.remove(goc); c--; } } if (count > max) { errorMsg = "Node type multiplicity failed!" + "\nType \"" + go.getType().getName() + "\"" + " - maximum failed."; return false; } return true; } @SuppressWarnings("unused") private static boolean checkConstValueWhenLeftAttrUnset( final OrdinaryMorphism match, final OrdinaryMorphism cond) { boolean result = true; final Enumeration<GraphObject> dom = cond.getDomain(); while (dom.hasMoreElements() && result) { final GraphObject goL = dom.nextElement(); final GraphObject imgC = cond.getImage(goL); final GraphObject imgG = match.getImage(goL); if (goL.getAttribute() != null && imgC.getAttribute() != null && imgG.getAttribute() != null) { final ValueTuple vtL = (ValueTuple) goL.getAttribute(); final ValueTuple vtC = (ValueTuple) imgC.getAttribute(); final ValueTuple vtG = (ValueTuple) imgG.getAttribute(); for (int i = 0; i < vtL.getNumberOfEntries(); i++) { final ValueMember vmL = vtL.getValueMemberAt(i); final ValueMember vmC = vtC.getValueMemberAt(vmL.getName()); final ValueMember vmG = vtG.getValueMemberAt(vmL.getName()); if (!vmL.isSet() && vmC.isSet() && vmC.getExpr().isConstant() && vmG.isSet() && vmG.getExpr().isConstant() && !vmG.getExprAsText().equals(vmC.getExprAsText())) { result = false; break; } } } } return result; } private static boolean checkConstantAttrValueFromSourceToTarget( final OrdinaryMorphism morph) { boolean result = true; final Enumeration<GraphObject> dom = morph.getDomain(); while (dom.hasMoreElements() && result) { final GraphObject go = dom.nextElement(); final GraphObject img = morph.getImage(go); if (go.getAttribute() != null && img.getAttribute() != null) { final ValueTuple vt1 = (ValueTuple) go.getAttribute(); final ValueTuple vt2 = (ValueTuple) img.getAttribute(); for (int i = 0; i < vt1.getNumberOfEntries(); i++) { final ValueMember vm1 = vt1.getValueMemberAt(i); final ValueMember vm2 = vt2.getValueMemberAt(vm1.getName()); if (vm1.isSet()) { if (vm1.getExpr().isConstant() && vm2 != null && vm2.isSet() && !vm1.getExprAsText().equals(vm2.getExprAsText())) { result = false; break; } } } } } return result; } public static boolean checkVariableToNullMappping(final Match match) { if (!match.getSource().isAttributed()) return true; final Rule itsRule = match.getRule(); final Vector<ValueMember> varToNull = new Vector<ValueMember>(2); final VarTuple vars = (VarTuple) match.getAttrContext().getVariables(); final Enumeration<GraphObject> en = match.getDomain(); while (en.hasMoreElements()) { final GraphObject obj = en.nextElement(); if (obj.getAttribute() == null) continue; final GraphObject img = match.getImage(obj); final ValueTuple vt = (ValueTuple) obj.getAttribute(); for (int i = 0; i < vt.getNumberOfEntries(); i++) { final ValueMember vmObj = vt.getEntryAt(i); if (vmObj.isSet() && vmObj.getExpr().isVariable()) { final ValueMember vmImg = ((ValueTuple) img.getAttribute()) .getEntryAt(i); String nullStr = "null"; if (vmImg.isSet() && vmImg.getExprAsText().equals(nullStr)) { varToNull.add(vars.getEntryAt(vmObj.getExprAsText())); } } } } final Iterator<Node> elems = itsRule.getRight().getNodesSet().iterator(); while (elems.hasNext()) { final GraphObject obj = elems.next(); if (obj.getAttribute() == null) continue; final ValueTuple vt = (ValueTuple) obj.getAttribute(); for (int j = 0; j < vt.getNumberOfEntries(); j++) { final ValueMember vm = vt.getEntryAt(j); if (vm.isSet() && vm.getExpr().isComplex()) { final Vector<String> exprVars = vm.getAllVariableNamesOfExpression(); for (int i = 0; i < varToNull.size(); i++) { final VarMember var = (VarMember) varToNull.get(i); if (exprVars.contains(var.getName())) { return false; } } } } } final Iterator<Arc> elems1 = itsRule.getRight().getArcsSet().iterator(); while (elems1.hasNext()) { final GraphObject obj = elems1.next(); if (obj.getAttribute() == null) continue; final ValueTuple vt = (ValueTuple) obj.getAttribute(); for (int j = 0; j < vt.getNumberOfEntries(); j++) { final ValueMember vm = vt.getEntryAt(j); if (vm.isSet() && vm.getExpr().isComplex()) { final Vector<String> exprVars = vm.getAllVariableNamesOfExpression(); for (int i = 0; i < varToNull.size(); i++) { final VarMember var = (VarMember) varToNull.get(i); if (exprVars.contains(var.getName())) { return false; } } } } } final CondTuple ct = (CondTuple) match.getAttrContext().getConditions(); for (int j = 0; j < ct.getNumberOfEntries(); j++) { final CondMember cm = (CondMember) ct.getEntryAt(j); final Vector<String> exprVars = cm.getAllVariables(); for (int i = 0; i < varToNull.size(); i++) { final VarMember var = (VarMember) varToNull.get(i); if ((cm.getExprAsText().indexOf(var.getName() + "==null") == -1) && exprVars.contains(var.getName())) { } } } return true; } public static void checkSourceTargetCompatibilityOfEdge( final Match match, final GraphObject orig, final GraphObject image) throws BadMappingException { if (orig.isArc()) { try { checkEdgeSourceTargetCompatibility(match, orig, image); } catch (BadMappingException ex) { throw ex; } // check : rule edge image is a loop and // match edge image is a loop - OK, // otherwise - FAILED! if (match.getRule().getImage(orig) != null) { if ((match.getRule().getImage(((Arc) orig).getSource()) == match.getRule().getImage(((Arc) orig).getTarget())) && (((Arc) image).getSource() != ((Arc) image).getTarget())) { errorMsg = "Edge loop: rule- and match-mapping must be source and target compatible."; System.out.println(errorMsg); System.out.println("required: "+(match.getRule().getImage(((Arc) orig).getSource()) +" == "+match.getRule().getImage(((Arc) orig).getTarget()))); System.out.println("required: "+(((Arc) image).getSource() +" == "+((Arc) image).getTarget())); throw new BadMappingException(errorMsg); } } } } public static void checkEdgeSourceTargetCompatibility( final OrdinaryMorphism morph, final GraphObject orig, final GraphObject image) throws BadMappingException { errorMsg = ""; if (orig.isArc() && ((Arc)orig).isDirected()) { // check compatibility of mapping with source and target functions: final GraphObject aSrc = ((Arc) orig).getSource(); final GraphObject aTar = ((Arc) orig).getTarget(); boolean mappingFailed = false; if (morph.getImage(aSrc) != null) { if (((Arc) image).getSource() != morph.getImage(aSrc)) { errorMsg = "Edge mapping must be source compatible."; // System.out.println(errorMsg); // System.out.println("required: "+ ((Arc) image).getSource() // +" == "+morph.getImage(aSrc)); throw new BadMappingException(errorMsg); } } else { mappingFailed = true; } if (morph.getImage(aTar) != null) { if (((Arc) image).getTarget() != morph.getImage(aTar)) { errorMsg = "Edge mapping must be target compatible."; // System.out.println(errorMsg); // System.out.println("required: "+ ((Arc) image).getTarget() // +" == "+morph.getImage(aTar)); throw new BadMappingException(errorMsg); } } else { mappingFailed = true; } if (mappingFailed){ errorMsg = "Edge mapping: source and target nodes of an edge must be mapped before."; throw new BadMappingException(errorMsg); } } } /* * Checks whether the parallel arcs of the given Type * and the specified source and target Node are possible.<br> * The nodes must be contained in the source graph of the given Match. * The rule of the given Match creates the specified arc.<br> */ public boolean isParallelArcAllowed( final Match m, final Type arct, final Node src, final Node tar) { if (!m.getOriginal().getTypeSet().isArcParallel() // && m.getRule().isArcCreating(src, arc.getType(), tar) ) { if (!src.hasArc(arct, tar)) { // check the graph m.getImage() already contains a such arc if (((Node)m.getImage(src)).hasArc(arct, (Node)m.getImage(tar))) { return false; } } else if (!m.getRule().isArcDeleting(src, arct, tar)) { return false; } } return true; } /* private int getCountOfNodesToGlue( final Rule rule, final Type nodetype, final Vector<GraphObject> nodesofglue) { int c = 0; for (int i = 0; i < nodesofglue.size(); i++) { GraphObject go = nodesofglue.get(i); if (go.getType().isRelatedTo(nodetype)) { c--; Enumeration<GraphObject> e = rule.getInverseImage(go); while (e.hasMoreElements()) { e.nextElement(); c++; } } } return c; } private int getCountOfEdgesToGlue(final Match match, final Arc rhsEdge) { int c = 0; final Vector<GraphObject> srcVec = new Vector<GraphObject>(2); final Enumeration<GraphObject> e = match.getRule().getInverseImage(rhsEdge.getSource()); while (e.hasMoreElements()) { srcVec.add(e.nextElement()); } final Vector<GraphObject> tarVec = new Vector<GraphObject>(2); final Enumeration<GraphObject> e1 = match.getRule().getInverseImage(rhsEdge.getTarget()); while (e.hasMoreElements()) { tarVec.add(e.nextElement()); } if (srcVec.size() == 1 && tarVec.size() == 1) { return 1; } if (srcVec.size() > 1) { for (int i = 0; i < srcVec.size(); i++) { GraphObject go = srcVec.get(i); c = c + ((Node)match.getImage(go)).getNumberOfOutgoingArcs( rhsEdge.getType(), rhsEdge.getTarget().getType()); } } // else if (srcVec.size() == 1 && tarVec.size() > 1) {} return c; } */ /** * Computes an overlapping set of the graphs: - this.source with * other.source if other instance of OrdinaryMorphism and left is true, or - * this.target with other.target if other instance of OrdinaryMorphism and * left is false, or - this.sorce with other if other instance of Graph and * left is true, or - this.target with other if other instance of Graph and * left is false, or with respect of the rules if this and other are * instances of Rule. * * @param union * If true - the overlappings contain disjunion, too. Enumeration * elements are of type <code>Pair</code>. * @return A set of overlappings. */ public static Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings( final OrdinaryMorphism morph, final Object other, boolean left, boolean union) { return getOverlappingsVector(morph, other, left, union).elements(); } public static Vector<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappingsVector( final OrdinaryMorphism morph, final Object other, boolean left, boolean union) { final Vector<Pair<OrdinaryMorphism, OrdinaryMorphism>> oSet = new Vector<Pair<OrdinaryMorphism, OrdinaryMorphism>>(); int minGraphSize = 1; if (union) minGraphSize = 0; Graph left2 = null; if ((other instanceof OrdinaryMorphism) && left) left2 = ((OrdinaryMorphism) other).getSource(); else if ((other instanceof OrdinaryMorphism) && !left) left2 = ((OrdinaryMorphism) other).getTarget(); else if (other instanceof Graph) left2 = (Graph) other; if (left2 != null) { int sizeOfInclusions = left2.getSize(); while ((sizeOfInclusions >= (minGraphSize))) { Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> overlapping = getOverlappings(morph, other, left, sizeOfInclusions, union); while (overlapping.hasMoreElements()) { oSet.addElement(overlapping.nextElement()); } sizeOfInclusions--; } } return oSet; } /** * Computes an overlapping set of the graphs: - this.source with * other.source if other instance of OrdinaryMorphism and left is true, or - * this.target with other.target if other instance of OrdinaryMorphism and * left is false, or - this.sorce with other if other instance of Graph and * left is true, or - this.target with other if other instance of Graph and * left is false, or with respect of the rules if this and other are * instances of Rule. * * @param sizeOfInclusions * The size of graph object inclusions. * @param union * If true - the overlappings contain disjunion, too. Enumeration * elements are of type <code>Pair</code>. * @return A set of overlappings. */ public static Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings( final OrdinaryMorphism morph, final Object other, boolean left, int sizeOfInclusions, boolean union) { return getOverlappingsVector(morph, other, left, sizeOfInclusions, union) .elements(); } public static Vector<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappingsVector( final OrdinaryMorphism morph, final Object otherObj, boolean left, int sizeOfInclusions, boolean union) { final Vector<Pair<OrdinaryMorphism, OrdinaryMorphism>> oSet = new Vector<Pair<OrdinaryMorphism, OrdinaryMorphism>>(); Graph other = null; if ((otherObj instanceof OrdinaryMorphism) && left) other = ((OrdinaryMorphism) otherObj).getSource(); else if ((otherObj instanceof OrdinaryMorphism) && !left) other = ((OrdinaryMorphism) otherObj).getTarget(); else if (otherObj instanceof Graph) other = (Graph) otherObj; if (other == null) return oSet; Vector<OrdinaryMorphism> subs = new Vector<OrdinaryMorphism>(); Enumeration<GraphObject> itsGOs = null; if (left) itsGOs = morph.getSource().getElements(); else itsGOs = morph.getTarget().getElements(); final Vector<GraphObject> itsGOSet = new Vector<GraphObject>(); boolean nextMatch = true; int minGraphSize; if (union) minGraphSize = 0; else minGraphSize = 1; while (itsGOs.hasMoreElements()) { itsGOSet.addElement(itsGOs.nextElement()); } if (sizeOfInclusions >= minGraphSize) { boolean withIsomorphicInclusions = true; subs = BaseFactory.theFactory().generateAllSubgraphsWithInclusionsOfSize( morph.getSource(), sizeOfInclusions, itsGOSet, subs, withIsomorphicInclusions, null, false); } else { itsGOSet.clear(); return oSet; } Completion_InjCSP strategy = new Completion_InjCSP(); for (int j = 0; j < subs.size(); j++) { OrdinaryMorphism h = subs.elementAt(j); Pair<Rule, Pair<OrdinaryMorphism, OrdinaryMorphism>> rulePair = (BaseFactory .theFactory()).constructIsomorphicRule(h); Rule hr = rulePair.first; OrdinaryMorphism isoRHShr = rulePair.second.second; MorphCompletionStrategy localStrategy = new Completion_InjCSP(); Match testm = (BaseFactory.theFactory()).createMatch(hr, other, true, "1"); testm.getTarget().setCompleteGraph(false); testm.setCompletionStrategy(localStrategy, true); OrdinaryMorphism rStar = null; Match m = null; nextMatch = true; while (nextMatch) { nextMatch = testm.nextCompletion(); if (nextMatch) { rStar = other.isomorphicCopy(); if (rStar != null) { m = (BaseFactory.theFactory()).createMatch(hr, rStar.getTarget()); m.doCompose(testm, rStar); m.adaptAttrContextValues(testm.getAttrContext()); // step.execute throws a TypeException when // resulting graph does broke the multiplicity condition // so we catch this exception and try another match try { // Variables in work graph are allowed OrdinaryMorphism ms = (OrdinaryMorphism) TestStep.execute(m, true); if (ms != null) { ms.getTarget().setCompleteGraph(false); OrdinaryMorphism mStar = isoRHShr.compose(ms); ms.dispose(); ms = null; if (mStar != null) { Rule r1 = null; Match m1 = null; Pair<OrdinaryMorphism, OrdinaryMorphism> p = null; if (morph instanceof Rule) { r1 = (Rule) morph; m1 = BaseFactory.theFactory().createMatch( r1, mStar.getTarget()); m1.setCompletionStrategy(strategy, true); if (!m1.nextCompletion() || !m1.isValid(true)) { BaseFactory.theFactory() .destroyMorphism(m1); m1 = null; } } Rule r2 = null; Match m2 = null; if (otherObj instanceof Rule) { r2 = (Rule) otherObj; m2 = BaseFactory.theFactory().createMatch( r2, mStar.getTarget()); m2.setCompletionStrategy(strategy, true); if (!m2.nextCompletion() || !m2.isValid(true)) { BaseFactory.theFactory() .destroyMorphism(m2); m2 = null; } } if ((morph instanceof Rule) && (otherObj instanceof Rule)) { if ((m1 != null) && (m2 != null)) { p = new Pair<OrdinaryMorphism, OrdinaryMorphism>( mStar, rStar); boolean isIsomorphic = false; if (!isIsomorphicOverlapping(oSet, p)) oSet.addElement(p); else isIsomorphic = true; BaseFactory.theFactory() .destroyMorphism(m1); m1 = null; BaseFactory.theFactory() .destroyMorphism(m2); m2 = null; if (isIsomorphic) p = null; } } else if (otherObj instanceof Rule) { if (m2 != null) { p = new Pair<OrdinaryMorphism, OrdinaryMorphism>( mStar, rStar); boolean isIsomorphic = false; if (!isIsomorphicOverlapping(oSet, p)) oSet.addElement(p); else isIsomorphic = true; BaseFactory.theFactory() .destroyMorphism(m2); m2 = null; if (isIsomorphic) p = null; } } else if (morph instanceof Rule) { if (m1 != null) { p = new Pair<OrdinaryMorphism, OrdinaryMorphism>( mStar, rStar); boolean isIsomorphic = false; if (!isIsomorphicOverlapping(oSet, p)) { oSet.addElement(p); } else isIsomorphic = true; BaseFactory.theFactory() .destroyMorphism(m1); m1 = null; if (isIsomorphic) p = null; } } else { p = new Pair<OrdinaryMorphism, OrdinaryMorphism>( mStar, rStar); if (!isIsomorphicOverlapping(oSet, p)) { oSet.addElement(p); } else p = null; } if (p == null) { BaseFactory.theFactory().destroyMorphism( mStar); mStar = null; BaseFactory.theFactory().destroyMorphism( rStar); rStar = null; } } else { BaseFactory.theFactory().destroyMorphism(rStar); rStar = null; } } } catch (TypeException e) {} } } } // while subs.removeElement(h); j--; testm.dispose(); testm = null; // dispose helpers localStrategy = null; OrdinaryMorphism h1 = rulePair.second.first; OrdinaryMorphism h2 = rulePair.second.second; Graph tmp3 = h.getSource(); h1.dispose(); h2.dispose(); hr.dispose(); h.dispose(); tmp3.dispose(); tmp3 = null; hr = null; h = null; h1 = null; h2 = null; rulePair = null; } deleteTransientContextVariables(morph, morph.getSource()); deleteTransientContextVariables(morph, morph.getTarget()); return oSet; } private static boolean isIsomorphicOverlapping( final Vector<Pair<OrdinaryMorphism,OrdinaryMorphism>> overlapGraphs, final Pair<OrdinaryMorphism,OrdinaryMorphism> overlapPair) { final Graph overlapGraph = overlapPair.first.getTarget(); for (int j = 0; j < overlapGraphs.size(); j++) { Pair<OrdinaryMorphism,OrdinaryMorphism> pj = overlapGraphs.elementAt(j); Graph gj = pj.first.getTarget(); if (gj.isIsomorphicTo(overlapGraph)) { if (pj.first.isIsomorphicTo(overlapPair.first) && pj.second.isIsomorphicTo(overlapPair.second)) return true; } } return false; } public static void deleteTransientContextVariables( final OrdinaryMorphism morph, final Graph g) { VarTuple vars = (VarTuple) morph.getAttrContext().getVariables(); Iterator<?> e = g.getNodesSet().iterator(); while (e.hasNext()) { GraphObject obj = (GraphObject) e.next(); if (obj.getAttribute() == null) continue; ValueTuple value = (ValueTuple) obj.getAttribute(); for (int i = 0; i < value.getNumberOfEntries(); i++) { ValueMember valuem = value.getValueMemberAt(i); if (valuem.isTransient()) { vars.getTupleType().deleteMemberAt(valuem.getExprAsText()); valuem.setExpr(null); } } } e = g.getArcsSet().iterator(); while (e.hasNext()) { GraphObject obj = (GraphObject) e.next(); if (obj.getAttribute() == null) continue; ValueTuple value = (ValueTuple) obj.getAttribute(); for (int i = 0; i < value.getNumberOfEntries(); i++) { ValueMember valuem = value.getValueMemberAt(i); if (valuem.isTransient()) { vars.getTupleType().deleteMemberAt(valuem.getExprAsText()); valuem.setExpr(null); } } } } public static Vector<CondMember> getConditionsOfNAC(final OrdinaryMorphism nacStar, final OrdinaryMorphism nac) { final Vector<CondMember> condsNAC = new Vector<CondMember>(); final VarTuple vart = (VarTuple) nacStar.getAttrContext().getVariables(); // vart.showVariables(); if (vart.getSize() == 0) return condsNAC; final CondTuple condt = (CondTuple) nacStar.getAttrContext().getConditions(); final Vector<String> varNames = nac.getImage().getVariableNamesOfAttributes(); final Vector<VarMember> varsOfNAC = new Vector<VarMember>(); for (int k = 0; k < vart.getSize(); k++) { final VarMember vm = vart.getVarMemberAt(k); if (varNames.contains(vm.getName())) { if (!varsOfNAC.contains(vm)) varsOfNAC.addElement(vm); } } for (int k = 0; k < condt.getSize(); k++) { final CondMember cm = condt.getCondMemberAt(k); final Vector<String> condVars = cm.getAllVariables(); for (int l = 0; l < varsOfNAC.size(); l++) { final VarMember vm = varsOfNAC.elementAt(l); if (((cm.getMark() == CondMember.NAC) || (cm.getMark() == CondMember.NAC_LHS)) && condVars.contains(vm.getName())) { if (!condsNAC.contains(cm)) { condsNAC.addElement(cm); } } } } return condsNAC; } public static Vector<CondMember> getConditionsOfPAC(final OrdinaryMorphism pacStar, final OrdinaryMorphism pac) { final Vector<CondMember> condsPAC = new Vector<CondMember>(); final VarTuple vart = (VarTuple) pacStar.getAttrContext().getVariables(); if (vart.getSize() == 0) return condsPAC; final CondTuple condt = (CondTuple) pacStar.getAttrContext().getConditions(); final Vector<String> varNames = pac.getImage().getVariableNamesOfAttributes(); final Vector<VarMember> varsOfPAC = new Vector<VarMember>(); for (int k = 0; k < vart.getSize(); k++) { VarMember vm = vart.getVarMemberAt(k); if (varNames.contains(vm.getName())) { if (!varsOfPAC.contains(vm)) varsOfPAC.addElement(vm); } } for (int k = 0; k < condt.getSize(); k++) { final CondMember cm = condt.getCondMemberAt(k); final Vector<String> condVars = cm.getAllVariables(); for (int l = 0; l < varsOfPAC.size(); l++) { final VarMember vm = varsOfPAC.elementAt(l); if (((cm.getMark() == CondMember.PAC) || (cm.getMark() == CondMember.PAC_LHS)) && condVars.contains(vm.getName())) { if (!condsPAC.contains(cm)) { condsPAC.addElement(cm); } } } } return condsPAC; } /** * @param nacStar * @param nac * @param condsNAC * @return * <code>true</code> if all attribute condition of the given NAC are satisfied, <code>false</code>. */ public static boolean isAttrConditionOfNACSatisfied(final NACStarMorphism nacStar, final OrdinaryMorphism nac, final Vector<CondMember> condsNAC) { // System.out.println("MatchHelper.isAttrConditionOfNACSatisfied "); // ((VarTuple)getAttrContext().getVariables()).showVariables(); ((VarTuple)nacStar.getAttrContext().getVariables()).propagateValueFromParent(); // ((VarTuple)nacStar.getAttrContext().getVariables()).showVariables(); errorMsg = "NAC \"" + nac.getName() + "\" failed."; boolean nacCondTrue = false; for (int k = 0; k < condsNAC.size(); k++) { CondMember cm = condsNAC.elementAt(k); if (cm.areVariablesSet()) { if (cm.isEnabled() && cm.isTrue()) { nacCondTrue = true; errorMsg = errorMsg + "\n(Attribute condition [ " + cm.getExprAsText() + " ] is satisfied.)"; } else { nacCondTrue = false; break; } } else { nacCondTrue = true; } } // System.out.println(nacCondTrue); if (!nacCondTrue) { errorMsg = ""; return false; } return true; } /** * @param pacStar * @param pac * @param condsPAC * @return * <code>true</code> if all attribute condition of the given PAC are satisfied, <code>false</code>. */ public static boolean isAttrConditionOfPACSatisfied(final PACStarMorphism pacStar, final OrdinaryMorphism pac, final Vector<CondMember> condsPAC) { // ((VarTuple)getAttrContext().getVariables()).showVariables(); ((VarTuple)pacStar.getAttrContext().getVariables()).propagateValueFromParent(); // ((VarTuple)pacStar.getAttrContext().getVariables()).showVariables(); errorMsg = "PAC \"" + pac.getName() + "\" failed."; boolean pacCondTrue = true; for (int k = 0; k < condsPAC.size(); k++) { CondMember cm = condsPAC.elementAt(k); if (cm.areVariablesSet()) { if (cm.isEnabled() && !cm.isTrue()) { pacCondTrue = false; errorMsg = errorMsg + "\n(Attribute condition [ " + cm.getExprAsText() + " ] is not satisfied.)"; break; } } } if (pacCondTrue) errorMsg = ""; return pacCondTrue; } public static final Morphism checkNACStar(final NACStarMorphism aNACstar, final OrdinaryMorphism nac, final Match match, boolean withVars) { // first add mapping of nodes and edges from match if (!makePartialNACStar(aNACstar, nac, match)) { return null; } // System.out.println("match:: context"); // ((VarTuple)match.getAttrContext().getVariables()).showVariables(); // System.out.println("NAC:: context"); // ((VarTuple)nac.getAttrContext().getVariables()).showVariables(); // aNACstar.adaptAttrContextValues(match.getAttrContext()); // System.out.println("NACstar:: context"); // ((VarTuple)aNACstar.getAttrContext().getVariables()).showVariables(); // now that we have a commuting nacstar, try to totalize it: Morphism result = null; if (aNACstar.tryToApplyAttrExpr()) { if (!withVars) result = makeNACStarCompletion(aNACstar, nac, match); else result = makeNACStarCompletionWithVars(aNACstar, nac, match); } else { errorMsg = "NAC \"" + nac.getName() + "\" cannot be checked.\n" +"An attribute expression of it is not avaluable."; } aNACstar.resetAttrValueAsExpr(); return result; } /* * If clan morphism of NAC morphism * into a graph exists, then NAC is found and match has failed. */ /* private boolean checkClanMorphismOfNACStar( final NACStarMorphism aNACstar, final OrdinaryMorphism nac, final Match match) { boolean result = true; Iterator<Node> nacNodes = nac.getSource().getNodesSet().iterator(); while (nacNodes.hasNext() && result) { GraphObject leftObj = nacNodes.next(); GraphObject nacObj = nac.getImage(leftObj); if (nacObj != null) { GraphObject nacObjImg = aNACstar.getImage(nacObj); GraphObject graphObj = match.getImage(leftObj); if (nacObjImg == graphObj) { if (leftObj.getType().isParentOf(nacObj.getType()) && leftObj.getType().isParentOf(graphObj.getType()) && !nacObj.getType().isParentOf(match.getImage(leftObj).getType())) { System.out.println("left: "+leftObj.getType().getName() +" nac: "+nacObj.getType().getName() +" graph: "+match.getImage(leftObj).getType().getName()); result = false; } } } } return result; } */ private static boolean makePartialNACStar( final NACStarMorphism aNACstar, final OrdinaryMorphism nac, final Match match) { // System.out.println(nac.getName()); // aNACstar.getCompletionStrategy().showProperties(); ((VarTuple)aNACstar.getAttrContext().getVariables()).propagateValueFromParent(); // ((VarTuple)aNACstar.getAttrContext().getVariables()).showVariables(); Iterator<Node> nacNodes = nac.getSource().getNodesSet().iterator(); while (nacNodes.hasNext()) { GraphObject leftObj = nacNodes.next(); GraphObject nacObj = nac.getImage(leftObj); if (nacObj != null) { GraphObject nacObjImg = aNACstar.getImage(nacObj); if (nacObjImg != null) { if (nacObjImg != match.getImage(leftObj)) return false; continue; } try { aNACstar.addMapping(nacObj, match.getImage(leftObj)); } catch (BadMappingException ex) { return false; } } } Iterator<Arc> nacArcs = nac.getSource().getArcsSet().iterator(); while (nacArcs.hasNext()) { GraphObject leftObj = nacArcs.next(); GraphObject src = ((Arc) leftObj).getSource(); GraphObject tar = ((Arc) leftObj).getTarget(); GraphObject nacObj = nac.getImage(leftObj); if (nacObj != null) { GraphObject nacObjSrc = nac.getImage(src); GraphObject nacObjTar = nac.getImage(tar); if (nacObjSrc != null && nacObjTar != null) { GraphObject nacObjImg = aNACstar.getImage(nacObj); if (nacObjImg != null) { if (nacObjImg != match.getImage(leftObj)) return false; continue; } try { aNACstar.addMapping(nacObj, match.getImage(leftObj)); } catch (BadMappingException ex) { return false; } } } } if (aNACstar.getSize() > 0) { if (!aNACstar.checkConstants()) { return false; } // ((VarTuple)match.getAttrContext().getVariables()).showVariables(); // ((VarTuple)aNACstar.getAttrContext().getVariables()).showVariables(); aNACstar.setPartialMorphismCompletion(true); } return true; } private static Morphism makeNACStarCompletion( final NACStarMorphism nacStar, final OrdinaryMorphism nac, final Match match) { errorMsg = ""; Morphism result = null; boolean attrCondsExist = !((CondTuple) match.getAttrContext() .getConditions()).isEmpty(); Vector<CondMember> condsNAC = getConditionsOfNAC(nacStar, nac); boolean attrCondsNacExist = !condsNAC.isEmpty(); if (nacStar.isTotal()) { // now check attribute conditions if (!attrCondsExist) { if (//checkConstValueWhenLeftAttrUnset(match, nac) && checkConstantAttrValueFromSourceToTarget(nacStar)) { result = nacStar; } } else if (!attrCondsNacExist || isAttrConditionOfNACSatisfied(nacStar, nac, condsNAC)) { result = nacStar; } unsetVariablesOfNAC(match.getAttrContext(), nac); unsetVariablesOfNAC(nacStar.getAttrContext(), nac); nacStar.propagateValueFromParentAsInputParameter((VarTuple) match.getAttrContext().getVariables(), false); return result; } // NACstar is NOT total, so next completion is needed while (nacStar.nextCompletion()) { // if (!nacStar.getCompletionStrategy().hasRelatedInstanceVarMap() // || match.getTarget().isAttributed()) { // if (checkNACStarCodomain(nacStar, nac, match)) { // result = nacStar; // } // } else { // result = nacStar; // } if (checkNACStarCodomain(nacStar, nac, match)) { result = nacStar; } if (result != null) { // now check attribute conditions if (!attrCondsExist || !attrCondsNacExist || isAttrConditionOfNACSatisfied(nacStar, nac, condsNAC)) { break; } else { result = null; } } unsetVariablesOfNAC(match.getAttrContext(), nac); unsetVariablesOfNAC(nacStar.getAttrContext(), nac); } unsetVariablesOfNAC(match.getAttrContext(), nac); unsetVariablesOfNAC(nacStar.getAttrContext(), nac); nacStar.propagateValueFromParentAsInputParameter((VarTuple) match.getAttrContext().getVariables(), false); return result; } private static Morphism makeNACStarCompletionWithVars( final NACStarMorphism nacStar, final OrdinaryMorphism nac, final Match match) { errorMsg = ""; Morphism result = null; boolean attrCondsExist = !((CondTuple) match.getAttrContext() .getConditions()).isEmpty(); Vector<CondMember> condsNAC = getConditionsOfNAC(nacStar, nac); boolean attrCondsNacExist = !condsNAC.isEmpty(); if (nacStar.isTotal()) { result = nacStar; // now check attribute conditions if (!attrCondsExist) { if (checkConstantAttrValueFromSourceToTarget(nacStar)) { result = nacStar; } } else if (!attrCondsNacExist || isAttrConditionOfNACSatisfied(nacStar, nac, condsNAC)) { result = nacStar; } unsetVariablesOfNAC(match.getAttrContext(), nac); unsetVariablesOfNAC(nacStar.getAttrContext(), nac); nacStar.propagateValueFromParentAsInputParameter((VarTuple) match.getAttrContext().getVariables(), false); return result; } // NACstar is NOT total, so next completion is needed while (nacStar.nextCompletion()) { if (checkNACStarCodomain(nacStar, nac, match)) { result = nacStar; } if (result != null) { // now check attribute conditions if (!attrCondsExist || !attrCondsNacExist || isAttrConditionOfNACSatisfied(nacStar, nac, condsNAC)) { break; } else { result = null; } } unsetVariablesOfNAC(match.getAttrContext(), nac); unsetVariablesOfNAC(nacStar.getAttrContext(), nac); } unsetVariablesOfNAC(match.getAttrContext(), nac); unsetVariablesOfNAC(nacStar.getAttrContext(), nac); nacStar.propagateValueFromParentAsInputParameter((VarTuple) match.getAttrContext().getVariables(), false); return result; } // check injectivity and commutativity of // NAC Star co-domain ( N -> G must be injective) private static boolean checkNACStarCodomain( final NACStarMorphism aNACstar, final OrdinaryMorphism nac, final Match match) { // List<GraphObject> gos = new Vector<GraphObject>(match.getSource().getNodesCount()); Iterator<?> e = aNACstar.getSource().getNodesSet().iterator(); while (e.hasNext()) { GraphObject nacObj = (GraphObject) e.next(); if (nac.hasInverseImage(nacObj)) { // check commutativity GraphObject leftObj = nac.getInverseImage(nacObj).nextElement(); GraphObject nacStarImgObj = aNACstar.getImage(nacObj); GraphObject graphObj = match.getImage(leftObj); if (nacStarImgObj != graphObj) { return false; } // else if (aNACstar.getInverseImageList(graphObj).size() > 1) { // return false; // } // gos.add(graphObj); } else { // check injectivity GraphObject nacStarImgObj = aNACstar.getImage(nacObj); if (match.hasInverseImage(nacStarImgObj)) { // co-domain of match contains additional nacStar obj return false; } } } // check injectivity of rest of m // Enumeration<GraphObject> mcodom = match.getCodomain(); // while (mcodom.hasMoreElements()) { // GraphObject go = mcodom.nextElement(); // if (go.isNode() && !gos.contains(go)) { // if (match.getInverseImageList(go).size() > 1) // return false; // } // } e = aNACstar.getSource().getArcsSet().iterator(); while (e.hasNext()) { GraphObject nacObj = (GraphObject) e.next(); if (nac.hasInverseImage(nacObj)) { // check commutativity GraphObject leftObj = nac.getInverseImage(nacObj).nextElement(); GraphObject nacStarImgObj = aNACstar.getImage(nacObj); GraphObject graphObj = match.getImage(leftObj); if (nacStarImgObj != graphObj) { return false; } } else { // check injectivity GraphObject nacStarImgObj = aNACstar.getImage(nacObj); if (match.hasInverseImage(nacStarImgObj)) { // co-domain of match contains additional nacStar obj return false; } } } return true; } public static final Morphism checkPACStar(final PACStarMorphism aPACstar, final OrdinaryMorphism pac, final Match match, boolean withVars) { // first add mapping of nodes and edges from match if (!makePartialPACStar(aPACstar, pac, match)) { return null; } // aPACstar.adaptAttrContextValues(match.getAttrContext()); // now that we have a commuting pacstar, try to totalize it: Morphism result = null; if (aPACstar.tryToApplyAttrExpr()) { if (!withVars) result = makePACStarCompletion(aPACstar, pac, match); else result = makePACStarCompletionWithVars(aPACstar, pac, match); } else { errorMsg = "PAC \"" + pac.getName() + "\" cannot be checked.\n" +"An attribute expression of it is not avaluable."; } aPACstar.resetAttrValueAsExpr(); return result; } // check injectivity and commutativity of // PAC Star co-domain ( P -> G must be injective) private static boolean checkPACStarCodomain( final PACStarMorphism aPACstar, final OrdinaryMorphism pac, final Match match) { // List<GraphObject> gos = new Vector<GraphObject>(match.getSource().getNodesCount()); Iterator<?> e = aPACstar.getSource().getNodesSet().iterator(); while (e.hasNext()) { GraphObject pacObj = (GraphObject) e.next(); if (pac.getInverseImage(pacObj).hasMoreElements()) { // check commutativity GraphObject leftObj = pac.getInverseImage(pacObj).nextElement(); GraphObject pacStarImgObj = aPACstar.getImage(pacObj); GraphObject graphObj = match.getImage(leftObj); if (pacStarImgObj != graphObj) { return false; } // else if (aPACstar.getInverseImageList(graphObj).size() > 1) { // return false; // } // gos.add(graphObj); } else { // check injectivity GraphObject pacStarImgObj = aPACstar.getImage(pacObj); if (match.getInverseImage(pacStarImgObj).hasMoreElements()) { return false; } } } // check injectivity of rest of m // Enumeration<GraphObject> mcodom = match.getCodomain(); // while (mcodom.hasMoreElements()) { // GraphObject go = mcodom.nextElement(); // if (go.isNode() && !gos.contains(go)) { // if (match.getInverseImageList(go).size() > 1) // return false; // } // } e = aPACstar.getSource().getArcsSet().iterator(); while (e.hasNext()) { GraphObject pacObj = (GraphObject) e.next(); if (pac.getInverseImage(pacObj).hasMoreElements()) { // check commutativity GraphObject leftObj = pac.getInverseImage(pacObj).nextElement(); GraphObject pacStarImgObj = aPACstar.getImage(pacObj); GraphObject graphObj = match.getImage(leftObj); if (pacStarImgObj != graphObj) { return false; } } else { // check injectivity GraphObject pacStarImgObj = aPACstar.getImage(pacObj); if (match.getInverseImage(pacStarImgObj).hasMoreElements()) { return false; } } } return true; } private static Morphism makePACStarCompletion( final PACStarMorphism pacStar, final OrdinaryMorphism pac, final Match match) { errorMsg = ""; Morphism result = null; // ((CondTuple) match.getAttrContext().getConditions()).showConditions(); boolean attrCondsExist = !((CondTuple) match.getAttrContext() .getConditions()).isEmpty(); Vector<CondMember> condsPAC = getConditionsOfPAC(pacStar, pac); boolean attrCondsPacExist = !condsPAC.isEmpty(); if (pacStar.isTotal()) { // now check attribute conditions if (!attrCondsExist) { if (checkConstantAttrValueFromSourceToTarget(pacStar)) { result = pacStar; } } else if (!attrCondsPacExist || isAttrConditionOfPACSatisfied(pacStar, pac, condsPAC)) { result = pacStar; } unsetVariablesOfPAC(match.getAttrContext(), pac); unsetVariablesOfPAC(pacStar.getAttrContext(), pac); pacStar.propagateValueFromParentAsInputParameter((VarTuple) match.getAttrContext().getVariables(), false); return result; } // PACstar is NOT total, so next completion is needed while (pacStar.nextCompletion()) { // if (!pacStar.getCompletionStrategy().hasRelatedInstanceVarMap() // || match.getTarget().isAttributed()) { // if (checkPACStarCodomain(pacStar, pac, match)) { // result = pacStar; // } // } else { // result = pacStar; // } if (checkPACStarCodomain(pacStar, pac, match)) { result = pacStar; } if (result != null) { // now check attribute conditions if (!attrCondsExist || !attrCondsPacExist || isAttrConditionOfPACSatisfied(pacStar, pac, condsPAC)) { break; } else { result = null; } } unsetVariablesOfPAC(match.getAttrContext(), pac); unsetVariablesOfPAC(pacStar.getAttrContext(), pac); } unsetVariablesOfPAC(match.getAttrContext(), pac); unsetVariablesOfPAC(pacStar.getAttrContext(), pac); pacStar.propagateValueFromParentAsInputParameter((VarTuple) match.getAttrContext().getVariables(), false); return result; } private static Morphism makePACStarCompletionWithVars(final PACStarMorphism pacStar, final OrdinaryMorphism pac, final Match match) { errorMsg = ""; Morphism result = null; boolean attrCondsExist = !((CondTuple) match.getAttrContext() .getConditions()).isEmpty(); Vector<CondMember> condsPAC = getConditionsOfPAC(pacStar, pac); boolean attrCondsPacExist = !condsPAC.isEmpty(); if (pacStar.isTotal()) { result = pacStar; // now check attribute conditions if (!attrCondsExist) { if (checkConstantAttrValueFromSourceToTarget(pacStar)) { result = pacStar; } } else if (!attrCondsPacExist || isAttrConditionOfPACSatisfied(pacStar, pac, condsPAC)) { result = pacStar; } unsetVariablesOfPAC(match.getAttrContext(), pac); unsetVariablesOfPAC(pacStar.getAttrContext(), pac); pacStar.propagateValueFromParentAsInputParameter((VarTuple) match.getAttrContext().getVariables(), false); return null; } // PACstar is NOT total, so next completion is need while (pacStar.nextCompletion()) { if (checkPACStarCodomain(pacStar, pac, match)) { result = pacStar; } if (result != null) { // now check attribute conditions if (!attrCondsExist || !attrCondsPacExist || isAttrConditionOfPACSatisfied(pacStar, pac, condsPAC)) { break; } else { result = null; } } unsetVariablesOfPAC(match.getAttrContext(), pac); unsetVariablesOfPAC(pacStar.getAttrContext(), pac); } unsetVariablesOfPAC(match.getAttrContext(), pac); unsetVariablesOfPAC(pacStar.getAttrContext(), pac); pacStar.propagateValueFromParentAsInputParameter((VarTuple) match.getAttrContext().getVariables(), false); return result; } private static boolean makePartialPACStar(final PACStarMorphism aPACstar, final OrdinaryMorphism pac, final Match match) { ((VarTuple)aPACstar.getAttrContext().getVariables()).propagateValueFromParent(); // ((VarTuple)aPACstar.getAttrContext().getVariables()).showVariables(); Iterator<Node> pacNodes = pac.getSource().getNodesSet().iterator(); while (pacNodes.hasNext()) { GraphObject leftObj = pacNodes.next(); GraphObject pacObj = pac.getImage(leftObj); if (pacObj != null) { GraphObject pacObjImg = aPACstar.getImage(pacObj); if (pacObjImg != null) { if (pacObjImg != match.getImage(leftObj)) return false; continue; } try { aPACstar.addMapping(pacObj, match.getImage(leftObj)); } catch (BadMappingException ex) { return false; } } } Iterator<Arc> pacArcs = pac.getSource().getArcsSet().iterator(); while (pacArcs.hasNext()) { GraphObject leftObj = pacArcs.next(); GraphObject src = ((Arc) leftObj).getSource(); GraphObject tar = ((Arc) leftObj).getTarget(); GraphObject pacObj = pac.getImage(leftObj); if (pacObj != null) { GraphObject pacObjSrc = pac.getImage(src); GraphObject pacObjTar = pac.getImage(tar); if (pacObjSrc != null && pacObjTar != null) { GraphObject pacObjImg = aPACstar.getImage(pacObj); if (pacObjImg != null) { if (pacObjImg != match.getImage(leftObj)) return false; continue; } try { aPACstar.addMapping(pacObj, match.getImage(leftObj)); } catch (BadMappingException ex) { return false; } } } } if (aPACstar.getSize() > 0) { if (!aPACstar.checkConstants()) { return false; } aPACstar.setPartialMorphismCompletion(true); } return true; } protected static void unsetVariablesOfNAC(final AttrContext attrContext, final OrdinaryMorphism nac) { final VarTuple vars = (VarTuple)attrContext.getVariables(); final Vector<String> nacVars = nac.getTarget().getVariableNamesOfAttributes(); for (int i = 0; i < vars.getSize(); i++) { VarMember vm = vars.getVarMemberAt(i); if (nacVars.contains(vm.getName()) && (vm.getMark() == VarMember.NAC) && !vm.isInputParameter()) { ((ContextView)attrContext).removeValue(vm.getName()); } } } protected static void unsetVariablesOfPAC(final AttrContext attrContext, final OrdinaryMorphism pac) { final VarTuple vars = (VarTuple)attrContext.getVariables(); final Vector<String> pacVars = pac.getTarget().getVariableNamesOfAttributes(); for (int i = 0; i < vars.getSize(); i++) { VarMember vm = vars.getVarMemberAt(i); if (pacVars.contains(vm.getName()) && (vm.getMark() == VarMember.PAC) && !vm.isInputParameter()) { ((ContextView)attrContext).removeValue(vm.getName()); } } } public static NACStarMorphism createNACstar(final OrdinaryMorphism nac, final Match match) { // System.out.println("Match.createNACstar ... // "+((Completion_NAC)this.getCompletionStrategy()).getSourceStrategy()); NACStarMorphism aNACstar = new NACStarMorphism(nac.getImage(), match .getImage(), match.getAttrManager().newContext( AttrMapping.MATCH_MAP, match.getAttrContext()), match); aNACstar.itsNAC = nac; aNACstar.setName("NACstar"); MorphCompletionStrategy strat = new Completion_InjCSP(); // strat.showProperties(); aNACstar.setCompletionStrategy(strat, true); return aNACstar; } public static NACStarMorphism createNACstar(final OrdinaryMorphism nac, final Match match, boolean withVars) { if (withVars) { // ((AttrTupleManager)AttrTupleManager.getDefaultManager()).setVariableContext(true); ContextView attrcontxt = (ContextView) match.getAttrManager() .newContext(AttrMapping.PLAIN_MAP, match.getAttrContext()); attrcontxt.setVariableContext(true); ((ContextView) ((CondTuple) attrcontxt.getConditions()) .getContext()).setVariableContext(true); NACStarMorphism aNACstar = new NACStarMorphism(nac.getImage(), match .getImage(), attrcontxt, match); aNACstar.itsNAC = nac; aNACstar.setName("NACstar"); MorphCompletionStrategy strat = new Completion_InjCSP(); // strat.showProperties(); aNACstar.setCompletionStrategy(strat, true); return aNACstar; } return createNACstar(nac, match); } public static PACStarMorphism createPACstar(final OrdinaryMorphism pac, final Match match) { final PACStarMorphism aPACstar = new PACStarMorphism(pac.getImage(), match .getImage(), match.getAttrManager().newContext( AttrMapping.MATCH_MAP, match.getAttrContext()), match); aPACstar.itsPAC = pac; aPACstar.setName("PACstar"); MorphCompletionStrategy strat = new Completion_InjCSP(); // strat.showProperties(); aPACstar.setCompletionStrategy(strat, true); return aPACstar; } public static PACStarMorphism createPACstar(final OrdinaryMorphism pac, final Match match, boolean withVars) { if (withVars) { // ((AttrTupleManager)AttrTupleManager.getDefaultManager()).setVariableContext(true); ContextView attrcontxt = (ContextView) match.getAttrManager() .newContext(AttrMapping.PLAIN_MAP, match.getAttrContext()); attrcontxt.setVariableContext(true); ((ContextView) ((CondTuple) attrcontxt.getConditions()) .getContext()).setVariableContext(true); PACStarMorphism aPACstar = new PACStarMorphism(pac.getImage(), match .getImage(), attrcontxt, match); aPACstar.itsPAC = pac; aPACstar.setName("PACstar"); MorphCompletionStrategy strat = new Completion_InjCSP(); // strat.showProperties(); aPACstar.setCompletionStrategy(strat, true); return aPACstar; } return createPACstar(pac, match); } public static PACStarMorphism createNestedACstar( final NestedApplCond ac, final OrdinaryMorphism relMorph) { final PACStarMorphism star = new PACStarMorphism(ac.getImage(), relMorph .getImage(), relMorph.getAttrManager().newContext( AttrMapping.MATCH_MAP, relMorph.getAttrContext()), relMorph); star.itsPAC = ac; star.setName("NestedACstar"); MorphCompletionStrategy strat = new Completion_InjCSP(); // strat.showProperties(); star.setCompletionStrategy(strat, true); return star; } public static final Morphism checkGACStar( final PACStarMorphism acStar, final NestedApplCond acMorph, final OrdinaryMorphism relatedMorph, boolean withVars) { if (!makePartialNestedACStar(acStar, acMorph, relatedMorph)) { return null; } // acStar.adaptAttrContextValues(match.getAttrContext()); // try to complete it Morphism result = null; if (acStar.tryToApplyAttrExpr()) { // if (!withVars) result = makeGACStarCompletion(acStar, acMorph, relatedMorph); // else // result = makeNestedACStarCompletionWithVars(acStar, ac, relatedMorph); } else { errorMsg = "Appl Cond \"" + acMorph.getName() + "\" cannot be checked.\n" +"An attribute expression of it is not avaluable."; } acStar.resetAttrValueAsExpr(); return result; } private static boolean makePartialNestedACStar( final PACStarMorphism acStar, final OrdinaryMorphism ac, final OrdinaryMorphism match) { ((VarTuple)acStar.getAttrContext().getVariables()).propagateValueFromParent(); // ((VarTuple)acStar.getAttrContext().getVariables()).showVariables(); Iterator<Node> pacNodes = ac.getSource().getNodesSet().iterator(); while (pacNodes.hasNext()) { GraphObject leftObj = pacNodes.next(); GraphObject pacObj = ac.getImage(leftObj); if (pacObj != null) { GraphObject pacObjImg = acStar.getImage(pacObj); if (pacObjImg != null) { if (pacObjImg != match.getImage(leftObj)) return false; continue; } try { acStar.addMapping(pacObj, match.getImage(leftObj)); } catch (BadMappingException ex) { return false; } } } Iterator<Arc> pacArcs = ac.getSource().getArcsSet().iterator(); while (pacArcs.hasNext()) { GraphObject leftObj = pacArcs.next(); GraphObject src = ((Arc) leftObj).getSource(); GraphObject tar = ((Arc) leftObj).getTarget(); GraphObject pacObj = ac.getImage(leftObj); if (pacObj != null) { GraphObject pacObjSrc = ac.getImage(src); GraphObject pacObjTar = ac.getImage(tar); if (pacObjSrc != null && pacObjTar != null) { GraphObject pacObjImg = acStar.getImage(pacObj); if (pacObjImg != null) { if (pacObjImg != match.getImage(leftObj)) return false; continue; } try { acStar.addMapping(pacObj, match.getImage(leftObj)); } catch (BadMappingException ex) { return false; } } } } if (acStar.getSize() > 0) { if (!acStar.checkConstants()) { return false; } acStar.setPartialMorphismCompletion(true); } return true; } private static Morphism makeGACStarCompletion( final PACStarMorphism acStar, final NestedApplCond acMorph, final OrdinaryMorphism relatedMorph) { errorMsg = ""; OrdinaryMorphism result = null; // boolean attrCondsExist = !((CondTuple) relatedMorph.getAttrContext() // .getConditions()).isEmpty(); Vector<CondMember> condsAC = getConditionsOfNestedAC(acStar, acMorph); boolean attrCondsACexist = !condsAC.isEmpty(); if (acStar.isTotal()) { // check attribute conditions and (nested) appl conds if (checkConstantAttrValueFromSourceToTarget(acStar) && (!attrCondsACexist || isAttrConditionOfNestedACSatisfied(acStar, acMorph, condsAC))) { acMorph.setCoMorphism(acStar); if (acMorph.evalFormula(relatedMorph.getTarget())) { // System.out.println(acMorph.getName()+" "+acMorph.getFormulaText()+" TRUE"); result = acStar; } else { // System.out.println(acMorph.getName()+" "+acMorph.getFormulaText()+" FALSE"); result = null; acMorph.setCoMorphism(null); } } unsetVariablesOfNestedAC(relatedMorph.getAttrContext(), acMorph); unsetVariablesOfNestedAC(acStar.getAttrContext(), acMorph); acStar.propagateValueFromParentAsInputParameter((VarTuple) relatedMorph.getAttrContext().getVariables(), false); return result; } boolean complFound = false; // ACstar is NOT total, so next completion is needed while (acStar.nextCompletion()) { if (checkGACStarCodomain(acStar, acMorph)) { // check attribute conditions and (nested) appl conds if ((!attrCondsACexist || isAttrConditionOfNestedACSatisfied(acStar, acMorph, condsAC))) { complFound = true; acMorph.setCoMorphism(acStar); if (acMorph.evalFormula(acStar.getTarget())) { // System.out.println(acMorph.getName()+" "+acMorph.getFormulaText()+" TRUE"); result = acStar; acMorph.setCoMorphism(result); if (!acMorph.forall) break; } else { // System.out.println(acMorph.getName()+" "+acMorph.getFormulaText()+" FALSE"); result = null; acMorph.setCoMorphism(null); if (acMorph.forall) break; } } unsetVariablesOfNestedAC(relatedMorph.getAttrContext(), acMorph); unsetVariablesOfNestedAC(acStar.getAttrContext(), acMorph); } } unsetVariablesOfNestedAC(relatedMorph.getAttrContext(), acMorph); unsetVariablesOfNestedAC(acStar.getAttrContext(), acMorph); acStar.propagateValueFromParentAsInputParameter((VarTuple) relatedMorph.getAttrContext().getVariables(), false); if (!complFound) { if (acMorph.forall) result = acStar; } return result; } public static Vector<CondMember> getConditionsOfNestedAC(final OrdinaryMorphism acStar, final OrdinaryMorphism ac) { final Vector<CondMember> condsAC = new Vector<CondMember>(); final VarTuple vart = (VarTuple) acStar.getAttrContext().getVariables(); if (vart.getSize() == 0) return condsAC; final CondTuple condt = (CondTuple) acStar.getAttrContext().getConditions(); final Vector<String> varNames = ac.getImage().getVariableNamesOfAttributes(); final Vector<VarMember> varsOfAC = new Vector<VarMember>(); for (int k = 0; k < vart.getSize(); k++) { VarMember vm = vart.getVarMemberAt(k); if (varNames.contains(vm.getName())) { if (!varsOfAC.contains(vm)) varsOfAC.addElement(vm); } } for (int k = 0; k < condt.getSize(); k++) { final CondMember cm = condt.getCondMemberAt(k); final Vector<String> condVars = cm.getAllVariables(); for (int l = 0; l < varsOfAC.size(); l++) { final VarMember vm = varsOfAC.elementAt(l); if (((cm.getMark() == CondMember.PAC) || (cm.getMark() == CondMember.PAC_LHS) || (cm.getMark() == CondMember.NAC) || (cm.getMark() == CondMember.NAC_LHS)) && condVars.contains(vm.getName())) { if (!condsAC.contains(cm)) { condsAC.addElement(cm); } } } } return condsAC; } public static boolean isAttrConditionOfNestedACSatisfied(final PACStarMorphism acStar, final OrdinaryMorphism ac, final Vector<CondMember> condsAC) { // ((VarTuple)getAttrContext().getVariables()).showVariables(); ((VarTuple)acStar.getAttrContext().getVariables()).propagateValueFromParent(); // ((VarTuple)pacStar.getAttrContext().getVariables()).showVariables(); errorMsg = "Appl Cond \"" + ac.getName() + "\" failed."; boolean acCondTrue = true; for (int k = 0; k < condsAC.size(); k++) { CondMember cm = condsAC.elementAt(k); if (cm.areVariablesSet()) { if (cm.isEnabled() && !cm.isTrue()) { acCondTrue = false; errorMsg = errorMsg + "\n(Attribute condition [ " + cm.getExprAsText() + " ] is not satisfied.)"; break; } } } if (acCondTrue) errorMsg = ""; return acCondTrue; } @SuppressWarnings("unused") private static boolean checkACStarCodomain( final PACStarMorphism acStar, final OrdinaryMorphism acMorph, final OrdinaryMorphism match) { Iterator<?> e = acStar.getSource().getNodesSet().iterator(); while (e.hasNext()) { GraphObject acObj = (GraphObject) e.next(); if (acMorph.getInverseImage(acObj).hasMoreElements()) { // check commutativity GraphObject leftObj = acMorph.getInverseImage(acObj).nextElement(); GraphObject acStarImgObj = acStar.getImage(acObj); GraphObject graphObj = match.getImage(leftObj); if (acStarImgObj != graphObj) { return false; } } else { // check injectivity GraphObject acStarImgObj = acStar.getImage(acObj); if (match.getInverseImage(acStarImgObj).hasMoreElements()) { return false; } } } e = acStar.getSource().getArcsSet().iterator(); while (e.hasNext()) { GraphObject pacObj = (GraphObject) e.next(); if (acMorph.getInverseImage(pacObj).hasMoreElements()) { // check commutativity GraphObject leftObj = acMorph.getInverseImage(pacObj).nextElement(); GraphObject acStarImgObj = acStar.getImage(pacObj); GraphObject graphObj = match.getImage(leftObj); if (acStarImgObj != graphObj) { return false; } } // else { // // check injectivity // GraphObject acStarImgObj = acStar.getImage(pacObj); // if (match.getInverseImage(acStarImgObj).hasMoreElements()) { // return false; // } // } } return true; } private static boolean checkElemOfNestedCodomain( final GraphObject go, final NestedApplCond acMorph, final PACStarMorphism acStar) { // check related co-domain if (acMorph.getRelatedMorphism().getCodomainObjects().contains(acStar.getImage(go))) { return false; } // check parent related co-domain NestedApplCond p = acMorph.getParent(); while (p != null) { if (p.getRelatedMorphism().getCodomainObjects().contains(acStar.getImage(go))) { return false; } p = p.getParent(); } return true; } private static boolean checkGACStarCodomain( final PACStarMorphism acStar, final NestedApplCond acMorph) { boolean result = true; // check nodes of ac(L)\L) at (G\match(L) Iterator<Node> elems = acMorph.getTarget().getNodesSet().iterator(); while(elems.hasNext() && result) { GraphObject go = elems.next(); if (!acMorph.getInverseImage(go).hasMoreElements()) { result = checkElemOfNestedCodomain(go, acMorph, acStar); } } // check edges of ac(L)\L) at (G\match(L) Iterator<Arc> elems1 = acMorph.getTarget().getArcsSet().iterator(); while(elems1.hasNext() && result) { GraphObject go = elems1.next(); if (!acMorph.getInverseImage(go).hasMoreElements()) { result = checkElemOfNestedCodomain(go, acMorph, acStar); } } return result; } protected static void unsetVariablesOfNestedAC(final AttrContext attrContext, final OrdinaryMorphism ac) { final VarTuple vars = (VarTuple)attrContext.getVariables(); final Vector<String> acVars = ac.getTarget().getVariableNamesOfAttributes(); for (int i = 0; i < vars.getSize(); i++) { VarMember vm = vars.getVarMemberAt(i); if (acVars.contains(vm.getName()) && ((vm.getMark() == VarMember.PAC) || (vm.getMark() == VarMember.NAC)) && !vm.isInputParameter()) { ((ContextView)attrContext).removeValue(vm.getName()); } } } }