/** * */ package agg.xt_basis.agt; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Vector; import agg.attribute.AttrContext; import agg.attribute.AttrMapping; import agg.attribute.handler.AttrHandlerException; import agg.attribute.handler.HandlerExpr; import agg.attribute.handler.HandlerType; import agg.attribute.handler.SymbolTable; import agg.attribute.handler.impl.javaExpr.JexExpr; import agg.attribute.impl.AttrTupleManager; import agg.attribute.impl.CondMember; import agg.attribute.impl.CondTuple; import agg.attribute.impl.ContextView; import agg.attribute.impl.DeclMember; import agg.attribute.impl.ValueMember; import agg.attribute.impl.ValueTuple; import agg.attribute.impl.VarMember; import agg.attribute.impl.VarTuple; import agg.attribute.parser.javaExpr.ASTId; import agg.attribute.parser.javaExpr.ASTPrimaryExpression; import agg.attribute.parser.javaExpr.SimpleNode; import agg.parser.CriticalPair; import agg.parser.SimpleExcludePair; import agg.util.Pair; import agg.xt_basis.Arc; import agg.xt_basis.BadMappingException; import agg.xt_basis.BaseFactory; import agg.xt_basis.ColimDiagram; import agg.xt_basis.Completion_InjCSP; import agg.xt_basis.Completion_NAC; import agg.xt_basis.GraGra; import agg.xt_basis.Graph; import agg.xt_basis.GraphObject; import agg.xt_basis.Match; import agg.xt_basis.MorphCompletionStrategy; import agg.xt_basis.Node; import agg.xt_basis.OrdinaryMorphism; import agg.xt_basis.Rule; import agg.xt_basis.TypeException; import agg.xt_basis.TypeSet; import agg.xt_basis.csp.CompletionPropertyBits; import agg.xt_basis.csp.Completion_CSP; /** * This class computes an amalgamated rule and amalgamated match based on * an interaction rule scheme and a host graph. * * @author olga * */ public class Covering { final private BaseFactory bf = BaseFactory.theFactory(); private GraGra gragra; /** current rule scheme */ private RuleScheme ruleScheme; /** enabled multi rules */ private List<Rule> multiRules; /** current host graph */ private Graph hostGraph; /** match completion strategy of the amalgamated match strategy: Completion_InjCSP */ final private MorphCompletionStrategy strategy = new Completion_InjCSP(); final private List<AmalgamationDataOfSingleKernelMatch> amalgamationData; final private Hashtable<GraphObject, GraphObject> amalgamLHS2kernelLHS; final private Hashtable<GraphObject, GraphObject> amalgamRHS2kernelRHS; /** left graph of the amalgamated rule (the graph of colim diagram) */ private Graph leftColimGraph; /** right graph of the amalgamated rule (the graph of colim diagram) */ private Graph rightColimGraph; final private List<List<GraphObject>> disjointObjects; /** amalgamated rule */ private AmalgamatedRule amalgamatedRule; /** amalgamated match */ protected Match amalgamatedMatch; /** kernel rule */ private Rule kernelRule; /** match of the kernel rule */ private Match kernelMatch; private List<GraphObject> localDisjointObjs; private String errorMsg=""; private AmalgamationRuleData lastKernelData; private AmalgamationDataOfSingleKernelMatch lastDataOfSKM; /** * Initialize a covering object with aim to compute an amalgamated rule * with amalgamated match based on the given * interaction rule scheme and host graph. */ public Covering(final RuleScheme rs, final Graph hostGraph, final MorphCompletionStrategy s){ this.ruleScheme = rs; this.kernelRule = this.ruleScheme.getKernelRule(); this.hostGraph = hostGraph; if (s != null) { this.strategy.getProperties().set(CompletionPropertyBits.INJECTIVE, s.getProperties().get(CompletionPropertyBits.INJECTIVE)); this.strategy.getProperties().set(CompletionPropertyBits.DANGLING, s.getProperties().get(CompletionPropertyBits.DANGLING)); this.strategy.getProperties().set(CompletionPropertyBits.IDENTIFICATION, s.getProperties().get(CompletionPropertyBits.IDENTIFICATION)); this.strategy.getProperties().set(CompletionPropertyBits.NAC, s.getProperties().get(CompletionPropertyBits.NAC)); this.strategy.getProperties().set(CompletionPropertyBits.PAC, s.getProperties().get(CompletionPropertyBits.PAC)); this.strategy.getProperties().set(CompletionPropertyBits.GAC, s.getProperties().get(CompletionPropertyBits.GAC)); // this.strategy.showProperties(); this.strategy.setRandomisedDomain(s.isRandomisedDomain()); // this.strategy.showProperties(); // because the strategy of an amalgamated rule is always INJECTIVE, // the IDENTIFICATION condition is already satisfied // this.strategy.getProperties().set(CompletionPropertyBits.IDENTIFICATION, // s.getProperties().get(CompletionPropertyBits.IDENTIFICATION)); } this.amalgamationData = new Vector<AmalgamationDataOfSingleKernelMatch>(); this.disjointObjects = new Vector<List<GraphObject>>(); this.amalgamRHS2kernelRHS = new Hashtable<GraphObject, GraphObject>(); this.amalgamLHS2kernelLHS = new Hashtable<GraphObject, GraphObject>(); } /** Returns constructed amalgamated rule. */ public AmalgamatedRule getAmalgamatedRule() { return this.amalgamatedRule; } /** Returns constructed amalgamated match. */ public Match getAmalgamatedMatch() { return this.amalgamatedMatch; } /** * Constructs amalgamated rule and match. * <code>getErrorMessage()</code> returns a short hint of the error occurred. * @return * true by success, otherwise false (see error message) */ @SuppressWarnings("unused") public boolean amalgamate() { boolean result = false; this.multiRules = getEnabledMultiRules(this.ruleScheme.getMultiRules()); boolean oneMultiRuleMatchExists = false; getKernelMatch(); boolean hasKernelMatchCompletion = true; while (hasKernelMatchCompletion) { boolean kernelsteps = false; while ((!result || this.ruleScheme.parallelKernelMatch()) && hasKernelMatchCompletion) { hasKernelMatchCompletion = this.kernelMatch.nextCompletionWithConstantsChecking(); if (hasKernelMatchCompletion) { if (this.kernelMatch.isValid()) { kernelsteps = true; result = this.createAmalgamationData(); if (result) { oneMultiRuleMatchExists = true; if (!this.ruleScheme.parallelKernelMatch()) { break; } clearMultiRuleMatches(); } else { clearMultiRuleMatches(); } } } } if (!result && this.ruleScheme.atLeastOneMultiMatchRequired()) { continue; } if (!kernelsteps // because partial match can be already total && this.kernelMatch.isTotal() && this.kernelMatch.isAttrConditionSatisfied() && this.kernelMatch.areNACsSatisfied() && this.kernelMatch.arePACsSatisfied() && this.kernelRule.evalFormula() && this.kernelMatch.isValid()) { result = this.createAmalgamationData(); if (!result && !this.ruleScheme.parallelKernelMatch()) { clearMultiRuleMatches(); } } if (!result && !this.ruleScheme.parallelKernelMatch() && this.kernelMatch.isValid() && this.lastDataOfSKM != null) { // use last valid match this.lastDataOfSKM.put(this.kernelRule, this.lastKernelData); this.amalgamationData.add(this.lastDataOfSKM); if (!this.multiRules.contains(this.kernelRule)) this.multiRules.add(this.kernelRule); result = true; } if (result) { createLkernLinst_RkernRinstMorphs(this.amalgamationData); createInstanceRules(this.amalgamationData); if (computeColimLeft() && computeColimRight() && constructAmalgamatedRule()) { this.amalgamatedMatch = constructAmalgamatedMatch(this.amalgamatedRule); if (this.amalgamatedMatch != null) { // ((VarTuple)this.amalgamatedMatch.getAttrContext().getVariables()).showVariables(); this.amalgamatedRule.adaptAttrContextValues(this.amalgamatedMatch.getAttrContext()); // ((VarTuple)this.amalgamatedRule.getAttrContext().getVariables()).showVariables(); // match is valid by construction this.ruleScheme.setAmalgamatedRule(this.amalgamatedRule); result = true; } else { this.amalgamatedRule.dispose(); this.amalgamatedRule = null; result = false; } } } if (result) { break; } this.clear(); clearMultiRuleMatches(); } this.ruleScheme.clearMatches(); this.clear(); return result; } private boolean createAmalgamationData() { boolean result = false; AmalgamationRuleData kernelData = createInstMatchDuetoKernelMatch(this.kernelMatch, this.kernelRule); if (kernelData == null) return false; AmalgamationDataOfSingleKernelMatch dataOfSKM = new AmalgamationDataOfSingleKernelMatch(kernelData); // store AmalgamationDataOfSingleKernelMatch to be used later, eventually this.lastKernelData = kernelData; this.lastDataOfSKM = dataOfSKM; this.localDisjointObjs = new Vector<GraphObject>(); boolean atLeastOneRule = false; //this.multiRules.isEmpty(); boolean matchValid = true; for (int i=0; i<this.multiRules.size(); i++) { final Rule rule = this.multiRules.get(i); if (rule instanceof KernelRule) continue; final Match multiMatch = getPartialMultiMatch((MultiRule) rule); if (multiMatch != null) matchValid = createInstMultiMatchesDuetoKernelMatch( multiMatch, (MultiRule) rule, dataOfSKM); atLeastOneRule = atLeastOneRule || (matchValid && !dataOfSKM.isEmpty(rule)); } // set result if (atLeastOneRule) { this.amalgamationData.add(dataOfSKM); result = true; } else if (this.multiRules.isEmpty()) { result = true; } if (!result && !this.ruleScheme.parallelKernelMatch()) { clearMultiRuleMatches(); } // put kernel data into amalgam data to be able // to generate amalgamated rule based on kernel match only if (this.multiRules.isEmpty() || (!atLeastOneRule && !this.ruleScheme.atLeastOneMultiMatchRequired())) { dataOfSKM.put(this.kernelRule, kernelData); this.amalgamationData.add(dataOfSKM); if (!this.multiRules.contains(this.kernelRule)) this.multiRules.add(this.kernelRule); result = true; } if (!result || this.ruleScheme.parallelKernelMatch()) { clearMultiRuleMatches(); } return result; } /** * Returns an error message when amalgamation process failed. */ public String getErrorMessage() { return this.errorMsg; } /** * Makes own list of enabled multi rules from the given list. */ private List<Rule> getEnabledMultiRules(List<Rule> multis) { this.multiRules = new Vector<Rule>(multis.size()); // add enabled multi rules from list for (int i=0; i<multis.size(); i++) { final MultiRule multiRule = (MultiRule) multis.get(i); if (multiRule.isEnabled()) { this.multiRules.add(multiRule); } } return this.multiRules; } private void clear() { this.disjointObjects.clear(); this.amalgamationData.clear(); } /* * Clears matches of kernel and multi rules. */ // private void clearRuleSchemeMatches() { // clearKernelRuleMatche(); // clearMultiRuleMatches(); // } // private void clearKernelRuleMatche() { // if (this.kernelMatch != null) { // this.kernelMatch.clear(); // this.kernelMatch.dispose(); // this.kernelRule.setMatch(null); // this.kernelMatch = null; // } // } private void clearMultiRuleMatches() { for (int i=0; i<this.multiRules.size(); i++) { if (this.multiRules.get(i) instanceof MultiRule) { final MultiRule multiRule = (MultiRule) this.multiRules.get(i); if (multiRule.getMatch() != null) { // ((VarTuple)multiRule.getAttrContext().getVariables()).showVariables(); // multiRule.getMatch().clear(); multiRule.getMatch().dispose(); multiRule.setMatch(null); } } } } /** Create isomorphic copies of multi rules based on the kernel rule. */ private boolean createInstMultiMatchesDuetoKernelMatch( final Match multiMatch, final MultiRule multiRule, final AmalgamationDataOfSingleKernelMatch dataOfSKM) { this.errorMsg = ""; boolean valid = false; // try to make more while (multiMatch.nextCompletion()) { if (multiMatch.isValid()) { valid = true; // ((VarTuple)multiMatch.getAttrContext().getVariables()).showVariables(); makeInstMultiMatchDuetoKernelMatch(multiMatch, multiRule, dataOfSKM); } } if (!valid // because partial match set before can be total && multiMatch.isTotal() && multiMatch.isAttrConditionSatisfied() && multiMatch.areNACsSatisfied() && multiMatch.arePACsSatisfied() && multiRule.evalFormula() && multiMatch.isValid()) { makeInstMultiMatchDuetoKernelMatch(multiMatch, multiRule, dataOfSKM); valid = true; } multiMatch.clear(); return valid; } private boolean makeInstMultiMatchDuetoKernelMatch( final Match multiMatch, final MultiRule multiRule, final AmalgamationDataOfSingleKernelMatch dataOfSKM) { // ((VarTuple)multiMatch.getAttrContext().getVariables()).showVariables(); boolean nextComplMayExist = true; if (this.ruleScheme.disjointMultiMatches()) { if (!isDisjoint(multiMatch, multiRule)) { nextComplMayExist = false; } else { this.disjointObjects.add(this.localDisjointObjs); } } else if (!isDeleteUseConflictFree(multiMatch, multiRule, dataOfSKM)) { nextComplMayExist = false; } if (nextComplMayExist) { AmalgamationRuleData data = new AmalgamationRuleData(multiRule); data.isoCopyLeft = multiRule.getLeft().isomorphicCopy(); data.isoCopyRight = multiRule.getRight().isomorphicCopy(); nextComplMayExist = false; if (data.isoCopyLeft != null && data.isoCopyRight != null) { // create instance match of a multi match data.instMatch = makeInstanceMatchOfRuleMatch(data.isoCopyLeft, multiMatch); if (data.instMatch == null) { data.isoCopyLeft.dispose(); data.isoCopyRight.dispose(); data = null; } else { dataOfSKM.put(multiRule, data); // ((VarTuple)data.instMatch.getAttrContext().getVariables()).showVariables(); } } else { data = null; } } return nextComplMayExist; } /** * Checks whether the match of the given multi rule is disjoint due to * already existing matches of other multi rules over the * matches of the kernel rule. * * @param multiMatch * @param rule * @return true by success */ private boolean isDisjoint(final Rule rule, final List<GraphObject> owns) { if (!owns.isEmpty()) { for (int k=0; k<owns.size(); k++) { final GraphObject obj = owns.get(k); for (int i=0; i<this.disjointObjects.size(); i++) { final List<GraphObject> list = this.disjointObjects.get(i); if (list.contains(obj)) { // System.out.println("Rule: "+rule.getName()+" - (multi) disjoint match failed."); this.errorMsg = "Rule: "+rule.getName()+" - (multi) disjoint match failed."; return false; } } } } return true; } /** * Checks whether the given match of the given multi rule is disjoint due to * already existing matches of other multi rules over the single match of the * kernel rule. * * @param multiMatch * @param rule * @return true by success */ private boolean isDisjoint(final Match multiMatch, final MultiRule rule) { final List<GraphObject> owns = new Vector<GraphObject>(); final Enumeration<GraphObject> objs = multiMatch.getDomain(); while (objs.hasMoreElements()) { final GraphObject obj = objs.nextElement(); if (!rule.isTargetOfEmbeddingLeft(obj)) { owns.add(multiMatch.getImage(obj)); } } if (!owns.isEmpty()) { boolean localdisjointOK = true; for (int k=0; k<owns.size(); k++) { final GraphObject obj = owns.get(k); if (this.localDisjointObjs.contains(obj)) { // System.out.println("Rule: "+rule.getName()+" - local (multi) disjoint match failed."); this.errorMsg = "Rule: "+rule.getName()+" - (multi) disjoint match failed."; localdisjointOK = false; break; } } if (localdisjointOK && isDisjoint(rule, owns)) { this.localDisjointObjs.addAll(owns); } else { return false; } } return true; } /** * Checks whether the given multi rule and match is in delete-use conflict * with other already existing matches of the multi rules. * * @param multiMatch current match * @param rule current multi rule * @param askMultiMatchData already existing multi match data * @return true when no conflict found */ private boolean isDeleteUseConflictFree( final Match multiMatch, final MultiRule rule, final AmalgamationDataOfSingleKernelMatch askMultiMatchData) { final List<GraphObject> owns = new Vector<GraphObject>(); final Enumeration<GraphObject> objs = multiMatch.getDomain(); while (objs.hasMoreElements()) { final GraphObject obj = objs.nextElement(); if (!rule.isTargetOfEmbeddingLeft(obj)) { owns.add(multiMatch.getImage(obj)); } } if (!owns.isEmpty()) { final Enumeration<Rule> keys = askMultiMatchData.getData().keys(); while (keys.hasMoreElements()) { final Rule r = keys.nextElement(); final List<AmalgamationRuleData> datas = askMultiMatchData.getData().get(r); for (int i=0; i<datas.size(); i++) { final OrdinaryMorphism m = datas.get(i).instMatch; final OrdinaryMorphism iso = datas.get(i).isoCopyLeft; if (iso != null && iso.getSource() == r.getLeft()) { for (int k=0; k<owns.size(); k++) { // object of host graph final GraphObject obj = owns.get(k); if (m.getInverseImage(obj).hasMoreElements()) { // object in domain of an already existing match GraphObject obj1 = m.getInverseImage(obj).nextElement(); if (iso.getInverseImage(obj1).hasMoreElements()) { // object of the LHS of its multi rule GraphObject obj2 = iso.getInverseImage(obj1).nextElement(); // other multi rule deletes this object if (r.getImage(obj2) == null) { if (this.ruleScheme.checkDeleteUseConflictRequired() ){ this.errorMsg = "Rule: "+rule.getName() +" has use-delete conflict with rule: "+r.getName(); return false; } } // current multi rule deletes this object else if (rule.getImage(multiMatch .getInverseImage(obj).nextElement()) == null) { if (this.ruleScheme.checkDeleteUseConflictRequired()) { this.errorMsg = "Rule: "+rule.getName() +" causes delete-use conflict."; return false; } else if (obj2.isNode()) { // check new edges from obj2 of rule r GraphObject img2 = r.getImage(obj2); Iterator<Arc> arcs = ((Node)img2).getOutgoingArcs(); while (arcs.hasNext()) { if (!r.getInverseImage(arcs.next()).hasMoreElements()) { this.errorMsg = "Rule: "+rule.getName() +" causes delete-use conflict."; return false; } } arcs = ((Node)img2).getIncomingArcs(); while (arcs.hasNext()) { if (!r.getInverseImage(arcs.next()).hasMoreElements()) { this.errorMsg = "Rule: "+rule.getName() +" causes delete-use conflict."; return false; } } } } } } } } } } } return true; } @SuppressWarnings("unused") private boolean deleteUseConflictFound() { boolean result = false; this.ruleScheme.propagateApplCondsOfKernelToMultiRules(); final List<Rule> list = this.ruleScheme.getMultiRules(); for (int i=list.size()-1; i>=0 && !result; i--) { Rule r1 = list.get(i); if (r1.isEnabled()) { for (int j=0; j<list.size() && !result; j++) { Rule r2 = list.get(j); if (r2.isEnabled()) { if (r1 != r2) { if (this.delUseConflictFound((MultiRule) r1, (MultiRule) r2)) { result = true; } } } } } } this.ruleScheme.removeShiftedApplConditionsFromMultiRules(); return result; } private boolean delUseConflictFound(final MultiRule r1, final MultiRule r2) { final SimpleExcludePair cp = new SimpleExcludePair(); cp.setGraGra(this.gragra); cp.setMorphismCompletionStrategy(this.strategy); cp.enableStrongAttrCheck(true); cp.enableEqualVariableNameOfAttrMapping(true); boolean result = false; try { final Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>> conflicts = cp.isCritical(CriticalPair.EXCLUDE, r1, r2); if (conflicts != null && !conflicts.isEmpty()) { for (int i=0; i<conflicts.size() && !result; i++) { OrdinaryMorphism om1 = conflicts.get(i).first.first; OrdinaryMorphism om2 = conflicts.get(i).first.second; if (this.isMultiObjConflict(r1, om1) || this.isMultiObjConflict(r2, om2)) { this.errorMsg = "Some multi rules are not conflict free ( " .concat(r1.getName().concat(" , ") .concat(r2.getName()).concat(" )")); result = true; } } } } catch (Exception ex) {} return result; } private boolean isMultiObjConflict(final MultiRule r, final OrdinaryMorphism om) { Enumeration<GraphObject> dom = om.getDomain(); while (dom.hasMoreElements()) { GraphObject obj = dom.nextElement(); if (om.getImage(obj).isCritical()) { if (!r.getEmbeddingLeft().getInverseImage(obj).hasMoreElements()) { return true; } } } return false; } private AmalgamationRuleData createInstMatchDuetoKernelMatch( final Match match, final Rule rule) { AmalgamationRuleData data = new AmalgamationRuleData(rule); data.isoCopyLeft = rule.getLeft().isomorphicCopy(); data.isoCopyRight = rule.getRight().isomorphicCopy(); if (data.isoCopyLeft != null && data.isoCopyRight != null) { // ((VarTuple) LmultiLinst.getAttrContext().getVariables()).showVariables(); // ((VarTuple) RmultiRinst.getAttrContext().getVariables()).showVariables(); // create instance match of a plain match data.instMatch = makeInstanceMatchOfRuleMatch(data.isoCopyLeft, match); if (data.instMatch == null) { data.isoCopyLeft.dispose(); data.isoCopyRight.dispose(); data = null; } } else { data = null; } return data; } /** * For each multi rule of the amalgamation data creates morphisms * of the lhs of the kernel rule into lhs of the instance of the multi rule * inside the host graph. * Creates similar morphisms for the rhs of the kernel rule * and instance of the multi rule. * * @param amalgamData */ private void createLkernLinst_RkernRinstMorphs( final List<AmalgamationDataOfSingleKernelMatch> amalgamData ) { // System.out.println("### createLkernLinst_RkernRinstMorphs"); for (int j=0; j<this.amalgamationData.size(); j++) { final AmalgamationDataOfSingleKernelMatch dataOfSKM = this.amalgamationData.get(j); final AmalgamationRuleData kerneldata = dataOfSKM.getKernelData(); for (int i=0; i<this.multiRules.size(); i++) { final Rule rule = this.multiRules.get(i); if (dataOfSKM.isEmpty(rule)) continue; Hashtable<Rule, List<AmalgamationRuleData>> amalgamationRuleData = dataOfSKM.getData(); final List<AmalgamationRuleData> datas = amalgamationRuleData.get(rule); if (datas.isEmpty()) continue; boolean failed = false; for (int k=0; k<datas.size() && !failed; k++) { final AmalgamationRuleData data = datas.get(k); if (data.isoCopyLeft == null || data.isoCopyRight == null) continue; OrdinaryMorphism embLeft = null; OrdinaryMorphism embRight = null; if (rule instanceof MultiRule) { embLeft = ((MultiRule) rule).getEmbeddingLeft(); embRight = ((MultiRule) rule).getEmbeddingRight(); } else { embLeft = data.isoCopyLeft; embRight = data.isoCopyRight; } //add mappings to LkernLinst morphism if (rule instanceof MultiRule) data.LkernelLinst = this.bf.createMorphism( // this.kernelRule.getLeft(), kerneldata.isoCopyLeft.getImage(), data.isoCopyLeft.getImage()); else { data.LkernelLinst = data.isoCopyLeft; } final Enumeration<GraphObject> embLeftDomain = embLeft.getDomain(); while (embLeftDomain.hasMoreElements()) { GraphObject domElem = embLeftDomain.nextElement(); GraphObject obj = null; GraphObject img = null; if (rule instanceof MultiRule) { obj = kerneldata.isoCopyLeft.getImage(domElem); img = data.isoCopyLeft.getImage(embLeft.getImage(domElem)); try { data.LkernelLinst.addMapping(obj, img); adoptEntriesWhereEmpty(data.LkernelLinst, obj, img, null); } catch (BadMappingException ex) { failed = true; break; } } } if (!failed) { //add mappings to RkernRinst morphism if (rule instanceof MultiRule) data.RkernelRinst = this.bf.createMorphism( // this.kernelRule.getRight(), kerneldata.isoCopyRight.getImage(), data.isoCopyRight.getImage()); else { data.RkernelRinst = data.isoCopyRight; } final Enumeration<GraphObject> embRightDomain = embRight.getDomain(); while(embRightDomain.hasMoreElements()) { GraphObject domElem = embRightDomain.nextElement(); GraphObject obj = null; GraphObject img = null; if (rule instanceof MultiRule) { obj = kerneldata.isoCopyRight.getImage(domElem); img = data.isoCopyRight.getImage(embRight.getImage(domElem)); try { data.RkernelRinst.addMapping(obj, img); adoptEntriesWhereEmpty(data.RkernelRinst, obj, img, null); } catch (BadMappingException ex) { failed = true; break; } } } } } } } } /** * For the multi rules and all its matches over a single kernel match * create an instance morphism to be basis of an instance rule. * Apply attribute context of the kernel rule to each instance morphism. */ private void createInstanceRules( final List<AmalgamationDataOfSingleKernelMatch> amalgamData) { // System.out.println("createInstanceRules..."); for (int i=0; i<this.multiRules.size(); i++) { final Rule rule = this.multiRules.get(i); final List<AmalgamationRuleData> datas = new Vector<AmalgamationRuleData>(); for (int j=0; j<amalgamData.size(); j++) { if (amalgamData.get(j).getRuleData(rule) != null) datas.addAll(amalgamData.get(j).getRuleData(rule)); } for (int k=0; k<datas.size(); k++) { final AmalgamationRuleData data = datas.get(k); final OrdinaryMorphism instRuleMorph = this.makeInstanceMorphism( data.isoCopyLeft.getTarget(), data.isoCopyRight.getTarget()); instRuleMorph.addToAttrContextFromList(rule.getInputParametersLeft(), true); instRuleMorph.addToAttrContextFromList(rule.getInputParametersRight(), true); instRuleMorph.adaptAttrContextValues(rule.getAttrContext()); // ((VarTuple) instRuleMorph.getAttrContext().getVariables()).showVariables(); // isomorphism data.isoCopyLeft: Lmulti -> Linst // isomorphism data.isoCopyRight: Rmulti -> Rinst // set morphism mappings boolean mapOK = true; final Enumeration<GraphObject> dom = rule.getDomain(); while (dom.hasMoreElements()) { GraphObject obj = dom.nextElement(); GraphObject img = rule.getImage(obj); GraphObject objLeft = data.isoCopyLeft.getImage(obj); GraphObject objRight = data.isoCopyRight.getImage(img); if (instRuleMorph.getImage(objLeft) == null) { try { instRuleMorph.addMapping(objLeft, objRight); adoptEntriesWhereEmpty(instRuleMorph, objLeft, objRight, img); } catch (BadMappingException ex) { mapOK = false; break; } } } if (mapOK) { data.instRule = this.bf.constructRuleFromMorph(instRuleMorph); data.instRule.setName(rule.getName()+k); data.instRule.addToAttrContext((VarTuple)data.instMatch.getAttrContext().getVariables()); data.instRule.adaptAttrContextValues(data.instMatch.getAttrContext()); // ((VarTuple)data.instMatch.getAttrContext().getVariables()).showVariables(); if (k>0) { renameVariables(this.kernelRule, data.instRule, k); } // ((VarTuple)data.instRule.getAttrContext().getVariables()).showVariables(); this.tryToSetAttrValuesOfMorph(data.instRule); } } } } /**Computes left colim diagram. */ private boolean computeColimLeft() { final AttrContext aRuleContext = agg.attribute.impl.AttrTupleManager.getDefaultManager().newContext(AttrMapping.PLAIN_MAP ); final AttrContext aLeftContext = agg.attribute.impl.AttrTupleManager.getDefaultManager().newLeftContext(aRuleContext); this.leftColimGraph = BaseFactory.theFactory().createGraph(this.kernelRule.getTypeSet()); this.leftColimGraph.setAttrContext(aLeftContext); final ColimDiagram colimL = new ColimDiagram(this.leftColimGraph); colimL.addNode(this.leftColimGraph); // colimL.addNode(this.kernelRule.getLeft()); for (int j=0; j<this.amalgamationData.size(); j++) { final AmalgamationDataOfSingleKernelMatch askMatchdata = this.amalgamationData.get(j); final AmalgamationRuleData kernelData = askMatchdata.getKernelData(); colimL.addNode(kernelData.isoCopyLeft.getImage()); Enumeration<Rule> keys = askMatchdata.getData().keys(); while (keys.hasMoreElements()) { final Rule rule = keys.nextElement(); final List<AmalgamationRuleData> datas = askMatchdata.getData().get(rule); for (int i=0; i<datas.size(); i++) { final AmalgamationRuleData data = datas.get(i); if (data.LkernelLinst == null) continue; OrdinaryMorphism colimedge = data.LkernelLinst; if (rule instanceof KernelRule) { colimL.addNode(this.kernelRule.getLeft()); colimL.addEdge(kernelData.isoCopyLeft); } else { colimL.addNode(colimedge.getImage()); } colimL.addEdge(colimedge); data.leftRequestEdge = new OrdinaryMorphism( colimedge.getImage(), this.leftColimGraph, AttrTupleManager.getDefaultManager().newContext(AttrMapping.PLAIN_MAP)); colimL.requestEdge(data.leftRequestEdge); } } } try { colimL.computeColimit(true); } catch(TypeException ex) { this.errorMsg = "Construction of the LHS of the amalgamated rule failed."; return false; } return true; } /**Computes right colim diagram. */ private boolean computeColimRight() { final AttrContext aRuleContext = agg.attribute.impl.AttrTupleManager.getDefaultManager().newContext(AttrMapping.PLAIN_MAP); final AttrContext aRightContext = agg.attribute.impl.AttrTupleManager.getDefaultManager().newRightContext(aRuleContext); this.rightColimGraph = BaseFactory.theFactory().createGraph(this.kernelRule.getTypeSet()); this.rightColimGraph.setAttrContext(aRightContext); final ColimDiagram colimR = new ColimDiagram(this.rightColimGraph); colimR.addNode(this.rightColimGraph); // colimR.addNode(this.kernelRule.getRight()); for (int j=0; j<this.amalgamationData.size(); j++) { final AmalgamationDataOfSingleKernelMatch askMatchdata = this.amalgamationData.get(j); final AmalgamationRuleData kernelData = askMatchdata.getKernelData(); colimR.addNode(kernelData.isoCopyRight.getImage()); final Enumeration<Rule> keys = askMatchdata.getData().keys(); while (keys.hasMoreElements()) { final Rule rule = keys.nextElement(); final List<AmalgamationRuleData> datas = askMatchdata.getData().get(rule); for (int i=0; i<datas.size(); i++) { final AmalgamationRuleData data = datas.get(i); if (data.RkernelRinst == null) continue; OrdinaryMorphism colimedge = data.RkernelRinst; if (rule instanceof KernelRule) { colimR.addNode(this.kernelRule.getRight()); colimR.addEdge( kernelData.isoCopyRight); } else colimR.addNode(colimedge.getImage()); colimR.addEdge(colimedge); data.rightRequestEdge = new OrdinaryMorphism( colimedge.getImage(), this.rightColimGraph, AttrTupleManager.getDefaultManager().newContext(AttrMapping.PLAIN_MAP)); colimR.requestEdge(data.rightRequestEdge); } } } try{ colimR.computeColimit(true); } catch(TypeException ex) { this.errorMsg = "Construction of the RHS of the amalgamated rule failed."; return false; } return true; } /** Constructs an amalgamated rule. */ private boolean constructAmalgamatedRule() { final OrdinaryMorphism amalgamMorph = this.makeInstanceMorphism(this.leftColimGraph, this.rightColimGraph); for (int j=0; j<this.amalgamationData.size(); j++) { boolean stored = false; final AmalgamationDataOfSingleKernelMatch askMatchdata = this.amalgamationData.get(j); final Enumeration<Rule> keys = askMatchdata.getData().keys(); while (keys.hasMoreElements()) { final Rule rule = keys.nextElement(); final List<AmalgamationRuleData> datas = askMatchdata.getData().get(rule); for (int i=0; i<datas.size(); i++) { final AmalgamationRuleData data = datas.get(i); if (data.leftRequestEdge == null) continue; // System.out.println("data.instRule... "+data.instRule.getName()); // ((VarTuple) data.instRule.getAttrContext().getVariables()).showVariables(); // set morphism mappings final Enumeration<GraphObject> dom = data.instRule.getDomain(); while (dom.hasMoreElements()) { GraphObject obj = dom.nextElement(); GraphObject img = data.instRule.getImage(obj); GraphObject objLeft = data.leftRequestEdge.getImage(obj); GraphObject objRight = data.rightRequestEdge.getImage(img); if(objLeft != null && objRight != null) { if (amalgamMorph.getImage(objLeft) == null) { try { amalgamMorph.addMapping(objLeft, objRight); GraphObject origRight = data.isoCopyRight.getInverseImage(img).nextElement(); adoptEntriesWhereEmpty(amalgamMorph, objLeft, objRight, origRight); } catch (BadMappingException ex) { this.errorMsg = "Amalgamated rule failed.\n"+ex.getMessage(); // System.out.println("Mapping of amalgamated rule failed! "+ex.getLocalizedMessage()); return false; } } } } if (!stored) { storeMappingAmalgamObjToKernelObj(data); stored = true; } setAttrContext(data.instRule, amalgamMorph); // ((VarTuple)amalgamMorph.getAttrContext().getVariables()).showVariables(); } } } setAttrContext(this.kernelRule, amalgamMorph); // ((VarTuple) amalgamMorph.getAttrContext().getVariables()).showVariables(); this.amalgamatedRule = new AmalgamatedRule(amalgamMorph); this.amalgamatedRule.setName(this.ruleScheme.getName()+"-Amalgamation"); // System.out.println("AmalgamatedRule: "+this.amalgamatedRule.getName()); // ((VarTuple)this.amalgamatedRule.getAttrContext().getVariables()).showVariables(); // takeNACsFromKernelRule(); // takeNACsFromMultiRules(); return true; } /** * Only RHS node and edges are taken in account. */ private void storeMappingAmalgamObjToKernelObj(AmalgamationRuleData data) { // store LHS Iterator<?> elems = data.instRule.getLeft().getNodesSet().iterator(); while (elems.hasNext()) { GraphObject obj = (GraphObject) elems.next(); if (data.LkernelLinst.getInverseImage(obj).hasMoreElements()) { GraphObject kernelObj = data.LkernelLinst.getInverseImage(obj).nextElement(); GraphObject objAmalgam = data.leftRequestEdge.getImage(obj); if(kernelObj != null && objAmalgam != null) { if (this.lastKernelData.isoCopyLeft.getInverseImage(kernelObj).hasMoreElements()) { GraphObject kernel = this.lastKernelData.isoCopyLeft.getInverseImage(kernelObj).nextElement(); this.amalgamLHS2kernelLHS.put(objAmalgam, kernel); } } } } elems = data.instRule.getLeft().getArcsSet().iterator(); while (elems.hasNext()) { GraphObject obj = (GraphObject) elems.next(); if (data.LkernelLinst.getInverseImage(obj).hasMoreElements()) { GraphObject kernelObj = data.LkernelLinst.getInverseImage(obj).nextElement(); GraphObject objAmalgam = data.leftRequestEdge.getImage(obj); if(kernelObj != null && objAmalgam != null) { if (this.lastKernelData.isoCopyLeft.getInverseImage(kernelObj).hasMoreElements()) { GraphObject kernel = this.lastKernelData.isoCopyLeft.getInverseImage(kernelObj).nextElement(); this.amalgamLHS2kernelLHS.put(objAmalgam, kernel); } } } } // store RHS elems = data.instRule.getRight().getNodesSet().iterator(); while (elems.hasNext()) { GraphObject obj = (GraphObject) elems.next(); if (data.RkernelRinst.getInverseImage(obj).hasMoreElements()) { GraphObject kernelObj = data.RkernelRinst.getInverseImage(obj).nextElement(); GraphObject objAmalgam = data.rightRequestEdge.getImage(obj); if(kernelObj != null && objAmalgam != null) { if (this.lastKernelData.isoCopyRight.getInverseImage(kernelObj).hasMoreElements()) { GraphObject kernel = this.lastKernelData.isoCopyRight.getInverseImage(kernelObj).nextElement(); this.amalgamRHS2kernelRHS.put(objAmalgam, kernel); } } } } elems = data.instRule.getRight().getArcsSet().iterator(); while (elems.hasNext()) { GraphObject obj = (GraphObject) elems.next(); if (data.RkernelRinst.getInverseImage(obj).hasMoreElements()) { GraphObject kernelObj = data.RkernelRinst.getInverseImage(obj).nextElement(); GraphObject objAmalgam = data.rightRequestEdge.getImage(obj); if(kernelObj != null && objAmalgam != null) { if (this.lastKernelData.isoCopyRight.getInverseImage(kernelObj).hasMoreElements()) { GraphObject kernel = this.lastKernelData.isoCopyRight.getInverseImage(kernelObj).nextElement(); this.amalgamRHS2kernelRHS.put(objAmalgam, kernel); } } } } } /** * @deprecated replaced by getRHSMappingAmalgamToKernelRule() */ public Hashtable<GraphObject, GraphObject> getMappingAmalgamToKernelRule() { return this.amalgamRHS2kernelRHS; } public Hashtable<GraphObject, GraphObject> getLHSMappingAmalgamToKernelRule() { return this.amalgamLHS2kernelLHS; } public Hashtable<GraphObject, GraphObject> getRHSMappingAmalgamToKernelRule() { return this.amalgamRHS2kernelRHS; } /** Constructs an amalgamated match of the given amalgamated rule. */ private Match constructAmalgamatedMatch(final Rule amalgamRule) { Match m = this.bf.createMatch(amalgamRule, this.hostGraph); amalgamRule.setMatch(m); boolean mapOK = true; for (int j=0; mapOK && j<this.amalgamationData.size(); j++) { final AmalgamationDataOfSingleKernelMatch askMatchdata = this.amalgamationData.get(j); final Enumeration<Rule> keys = askMatchdata.getData().keys(); while (mapOK && keys.hasMoreElements()) { final Rule rule = keys.nextElement(); final List<AmalgamationRuleData> datas = askMatchdata.getData().get(rule); for (int i=0; i<datas.size() && mapOK; i++) { final AmalgamationRuleData data = datas.get(i); if (data.leftRequestEdge == null) continue; Iterator<?> LkernObjs = data.LkernelLinst.getOriginal().getNodesSet().iterator(); while (LkernObjs.hasNext()) { GraphObject obj = (GraphObject) LkernObjs.next(); GraphObject imgLi = data.LkernelLinst.getImage(obj); GraphObject imgG = data.instMatch.getImage(imgLi); GraphObject imgL = data.leftRequestEdge.getImage(imgLi); try { if (imgL != null && imgG != null) { m.addMapping(imgL, imgG); } } catch (BadMappingException ex) { mapOK = false; // System.out.println(ex.getLocalizedMessage()); break; } } LkernObjs = data.LkernelLinst.getOriginal().getArcsSet().iterator(); while (LkernObjs.hasNext()) { GraphObject obj = (GraphObject) LkernObjs.next(); GraphObject imgLi = data.LkernelLinst.getImage(obj); GraphObject imgG = data.instMatch.getImage(imgLi); GraphObject imgL = data.leftRequestEdge.getImage(imgLi); try { if (imgL != null && imgG != null) { m.addMapping(imgL, imgG); } } catch (BadMappingException ex) { mapOK = false; // System.out.println(ex.getLocalizedMessage()); break; } } if (!m.makeDiagram(data.leftRequestEdge, data.instMatch)) { System.out.println("makeDiagram FAILED!"); break; } } } } if (!mapOK || !m.isTotal()) { this.errorMsg = "Amalgamated match failed.\n"+m.getErrorMsg(); } else if (this.ruleScheme.parallelKernelMatch()) { if (this.glueObjectsOfAmalgamatedRule(amalgamRule, m)) { return m; } this.errorMsg = "Amalgamated rule failed.\n" + this.errorMsg; } else { m.setCompletionStrategy(this.strategy); m.getCompletionStrategy().getProperties() .set(CompletionPropertyBits.INJECTIVE, this.ruleScheme.disjointMultiMatches()); if (this.ruleScheme.disjointMultiMatches()) { if (m.getCompletionStrategy().getProperties().get(CompletionPropertyBits.DANGLING)) { if (m.isDanglingSatisfied()) return m; this.errorMsg = "Amalgamated match failed.\n" + m.getErrorMsg(); } else return m; } else { if (this.glueObjectsOfAmalgamatedRule(amalgamRule, m)) { if (m.getCompletionStrategy().getProperties().get(CompletionPropertyBits.DANGLING)) { if (m.isDanglingSatisfied()) return m; this.errorMsg = "Amalgamated match failed.\n" + m.getErrorMsg(); } else return m; } else { this.errorMsg = "Amalgamated rule failed.\n" + this.errorMsg; } } } // match failed, return null amalgamRule.setMatch(null); m.dispose(); m = null; return null; } private boolean glueObjectsOfAmalgamatedRule(final Rule amalgamRule, final Match m) { int tgCheckLevel = m.getTarget().getTypeSet().getLevelOfTypeGraphCheck(); m.getTarget().getTypeSet().setLevelOfTypeGraph(TypeSet.ENABLED); final Hashtable<GraphObject, GraphObject> l2r = new Hashtable<GraphObject, GraphObject>(); final Hashtable<GraphObject, List<GraphObject>> keep2glue = new Hashtable<GraphObject,List<GraphObject>>(); final List<GraphObject> toDelete = new Vector<GraphObject>(); Enumeration<GraphObject> matchCodom = m.getCodomain(); while (matchCodom.hasMoreElements()) { final GraphObject codomObj = matchCodom.nextElement(); // store arcs to glue if (codomObj instanceof Arc) { List<GraphObject> listL = m.getInverseImageList(codomObj); // LHS arcs if (listL.size() > 1) { List<GraphObject> listR = new Vector<GraphObject>(); // RHS arcs for (int i=0; i<listL.size(); i++) { GraphObject img = amalgamRule.getImage(listL.get(i)); if (img != null) listR.add(img); } boolean shouldDelete = listL.size() > listR.size(); GraphObject objL = listL.get(0); GraphObject objR = (listR.size() > 0)? listR.get(0): null; keep2glue.put(objL, listL); if (objR != null) { keep2glue.put(objR, listR); l2r.put(objL, objR); if (shouldDelete) toDelete.add(objR); } } } } boolean result = true; // glue nodes matchCodom = m.getCodomain(); while (matchCodom.hasMoreElements()) { GraphObject codomObj = matchCodom.nextElement(); if (codomObj instanceof Node) { List<GraphObject> listL = m.getInverseImageList(codomObj); // LHS nodes if (listL.size() > 1) { List<GraphObject> listR = new Vector<GraphObject>(); for (int i=0; i<listL.size(); i++) { GraphObject obj = listL.get(i); GraphObject img = amalgamRule.getImage(obj); if (img != null) listR.add(img); } boolean shouldDelete = listL.size() > listR.size(); GraphObject objL = listL.get(0); GraphObject objR = (listR.size() > 0)? listR.get(0): null; try { if (this.glueObjects(objL, listL)) { if (objR != null) { try { if (this.glueObjects(objR, listR)) { l2r.put(objL, objR); if (shouldDelete) toDelete.add(objR); } else { this.errorMsg = "Gluing nodes failed."; result = false; } } catch (TypeException ex) { this.errorMsg = "Gluing nodes failed. \n"+ex.getLocalizedMessage(); result = false; } } } else { this.errorMsg = "Gluing nodes failed."; result = false; } } catch (TypeException ex) { this.errorMsg = "Gluing nodes failed. \n"+ex.getLocalizedMessage(); result = false; } } } } // glue arcs final Enumeration<GraphObject> keep = keep2glue.keys(); while (keep.hasMoreElements() && result) { GraphObject keepObj = keep.nextElement(); List<GraphObject> glue = keep2glue.get(keepObj); try { if (!this.glueObjects(keepObj, glue)) { this.errorMsg = "Gluing edges failed."; result = false; } } catch (TypeException ex) { this.errorMsg = "Gluing edges failed. \n"+ex.getLocalizedMessage(); result = false; } } // restore mapping if (result) { final Enumeration<GraphObject> lhs = l2r.keys(); while (lhs.hasMoreElements()) { GraphObject l = lhs.nextElement(); if (l.isNode()) { GraphObject r = l2r.get(l); if (amalgamRule.getImage(l) == null) { try { amalgamRule.addMapping(l, r); } catch (BadMappingException ex) { this.errorMsg = "Node mapping after gluing nodes failed."; result = false; break; } } } } while (lhs.hasMoreElements()) { GraphObject l = lhs.nextElement(); if (l.isArc()) { GraphObject r = l2r.get(l); if (amalgamRule.getImage(l) == null) { try { amalgamRule.addMapping(l, r); } catch (BadMappingException ex) { this.errorMsg = "Edge mapping after gluing edges failed."; result = false; break; } } } } } // remove rhs node/edge because at least one of glued lhs nodes/edges does not have an rhs image if (result) { for (int i=0; i<toDelete.size(); i++) { GraphObject go = toDelete.get(i); try { if (go.getContext() != null) { if (go instanceof Node) amalgamRule.getRight().destroyNode((Node) go, true, false); else amalgamRule.getRight().destroyArc((Arc) go, true, false); } } catch (TypeException ex) {} } } m.getTarget().getTypeSet().setLevelOfTypeGraph(tgCheckLevel); if (result) { if (amalgamRule.getTypeSet().checkType(amalgamRule.getLeft(), tgCheckLevel).isEmpty() && amalgamRule.getTypeSet().checkType(amalgamRule.getRight(), tgCheckLevel).isEmpty()) { result = true; } else { this.errorMsg = "Gluing of graph objects failed (type check). "; result = false; } } return result; } private boolean glueObjects( final GraphObject keep, final List<GraphObject> list) throws TypeException { for (int i=0; i<list.size(); i++) { GraphObject glue = list.get(i); if (keep != glue) { try { if (!keep.getContext().glue(keep, glue)) { return false; } list.remove(glue); i--; } catch (TypeException ex) { throw ex; } } } return true; } private void setAttrContext( final OrdinaryMorphism from, final OrdinaryMorphism to) { final VarTuple varsTo = (VarTuple) to.getAttrContext().getVariables(); final VarTuple varsFrom = (VarTuple) from.getAttrContext().getVariables(); for (int j=0; j<varsFrom.getSize(); j++) { final VarMember vmFrom = varsFrom.getVarMemberAt(j); final DeclMember dm = (DeclMember) vmFrom.getDeclaration(); if (!varsTo.isDeclared(dm.getTypeName(), dm.getName())) { varsTo.declare(dm.getHandler(), dm.getTypeName(), dm.getName()); } final VarMember vmTo = varsTo.getVarMemberAt(dm.getName()); vmTo.setInputParameter(vmFrom.isInputParameter()); if (vmFrom.isSet()) { vmTo.setExprAsText(vmFrom.getExprAsText()); } } // final CondTuple conds = (CondTuple) to.getAttrContext().getConditions(); // final CondTuple condsFrom = (CondTuple) from.getAttrContext().getConditions(); // for(int j=0; j<condsFrom.getSize(); j++){ // final CondMember cm = condsFrom.getCondMemberAt(j); // if(!cm.getExprAsText().equals("") // &&!conds.contains(cm.getExprAsText())) { // conds.addCondition(cm.getExprAsText()); // } // } } /* Converts NACs form kernel rule */ /* private void takeNACsFromKernelRule() { final List<OrdinaryMorphism> NACs = this.kernelRule.getNACsList(); if (NACs.isEmpty()) { return; } final OrdinaryMorphism LkernL = createLkernLcolimMorph(); if (LkernL == null) { // System.out.println("Covering.takeNACsFromKernelRule: FAILED"); return; } for (int i=0; i<NACs.size(); i++) { final OrdinaryMorphism nac = NACs.get(i); final OrdinaryMorphism NkernNamalgam = nac.getImage().isomorphicCopy(); final OrdinaryMorphism amalgamNAC = this.bf.createMorphism(amalgamatedRule.getLeft(), NkernNamalgam.getTarget()); boolean nacOK = true; final Enumeration dom = nac.getDomain(); while (dom.hasMoreElements()) { GraphObject obj = (GraphObject) dom.nextElement(); GraphObject img = nac.getImage(obj); GraphObject objRight = NkernNamalgam.getImage(img); GraphObject objLeft = LkernL.getImage(obj); if (objLeft != null && objRight != null) { try { amalgamNAC.addMapping(objLeft, objRight); } catch (BadMappingException ex) { // System.out.println("Covering.takeNACsFromKernelRule: kernel "+nac.getName()+" failed. "+ex.getLocalizedMessage()); nacOK = false; break; } } else { // System.out.println("Covering.takeNACsFromKernelRule: kernel "+nac.getName()+" failed. "); nacOK = false; break; } } if (nacOK) { amalgamNAC.setName(nac.getName()); amalgamatedRule.addNAC(amalgamNAC); } } } */ /* Converts NACs from multi rules. */ /* private boolean takeNACsFromMultiRules() { int nn = this.multiRules.size(); if (this.multiRules.contains(this.kernelRule)) nn--; for (int i=0; i<nn; i++) { final MultiRule multi = (MultiRule) multiRules.get(i); final Enumeration<OrdinaryMorphism> multiNACs = multi.getNACs(); while(multiNACs.hasMoreElements()) { final OrdinaryMorphism nac = multiNACs.nextElement(); final List<OrdinaryMorphism> isoNACs = createIsoNACs(multi, nac); if (!makeNACfromInstanceNAC(multi, nac, isoNACs)) { return false; } } } return true; } */ /* Create NAC morphism for the instance rules. */ /*private List<OrdinaryMorphism> createIsoNACs( final Rule rule, final OrdinaryMorphism nac) { final List<OrdinaryMorphism> isoNACs = new Vector<OrdinaryMorphism>(); for (int j=0; j<this.amalgamationData.size(); j++) { final AmalgamationDataOfSingleKernelMatch askMatchdata = this.amalgamationData.get(j); if (askMatchdata.getRuleData(rule) == null) continue; final List<AmalgamationRuleData> datas = askMatchdata.getRuleData(rule); for (int i=0; i<datas.size(); i++) { final AmalgamationRuleData data = datas.get(i); final OrdinaryMorphism currentLeLi = data.isoCopyLeft; final OrdinaryMorphism NeNi = nac.getImage().isomorphicCopy(); final OrdinaryMorphism NiLi = this.bf.createMorphism( data.isoCopyLeft.getTarget(), NeNi.getTarget()); final Enumeration<GraphObject> dom = nac.getDomain(); while (dom.hasMoreElements()) { final GraphObject obj = dom.nextElement(); final GraphObject img = nac.getImage(obj); final GraphObject objR = NeNi.getImage(img); final GraphObject objL = data.isoCopyLeft.getImage(obj); if (objL != null && objR != null) { try { NiLi.addMapping(objL, objR); } catch (BadMappingException ex) { return null; } if (objL.getAttribute() != null && objR.getAttribute() != null) { final ValueTuple value = (ValueTuple) objL.getAttribute(); final ValueTuple value1 = (ValueTuple) objR.getAttribute(); for (int ii=0; ii<value.getSize(); ii++) { final ValueMember vm = value.getValueMemberAt(ii); if (vm.isSet() && vm.getExpr().isVariable()) { final ValueMember vm1 = value1.getValueMemberAt(ii); if (vm1.isSet() && !vm1.getExprAsText().equals(vm.getExprAsText())) { vm1.setExprAsText(vm.getExprAsText()); } } } } } } isoNACs.add(NiLi); if (nac.getSize() == 0) break; } } return isoNACs; } private boolean makeNACfromInstanceNAC( final Rule rule, final OrdinaryMorphism nac, final List<OrdinaryMorphism> isoNacs) { final List<OrdinaryMorphism> isoNACs = new Vector<OrdinaryMorphism>(); for (int j=0; j<this.amalgamationData.size(); j++) { final AmalgamationDataOfSingleKernelMatch askMatchdata = this.amalgamationData.get(j); if (askMatchdata.getRuleData(rule) == null) continue; final List<AmalgamationRuleData> datas = askMatchdata.getRuleData(rule); for (int i=0; i<datas.size(); i++) { final AmalgamationRuleData data = datas.get(i); if (data.leftRequestEdge == null) continue; for (int k=0; k<isoNacs.size(); k++) { OrdinaryMorphism NiNa = isoNacs.get(k); OrdinaryMorphism LaNa = this.bf. createMorphism(amalgamatedRule.getLeft(), NiNa.getTarget()); LaNa.setName(nac.getName()); boolean nacOK = true; if (nac.getSize() > 0) { LaNa.setName(nac.getName()+k); Enumeration<GraphObject> dom = NiNa.getDomain(); while (dom.hasMoreElements()) { GraphObject obj = dom.nextElement(); GraphObject objLeft = NiNa.getImage(obj); GraphObject objRight = data.leftRequestEdge.getImage(obj); if (objLeft != null && objRight != null) { try { LaNa.addMapping(objRight, objLeft); } catch (BadMappingException ex) { // System.out.println("Covering.takeNACsFromMultiRule: multi nac "+LaNa.getName()+" failed. "+ex.getLocalizedMessage()); nacOK = false; break; } } else { nacOK = false; break; } } } if (nacOK) { amalgamatedRule.addNAC(LaNa); } if (nac.getSize() == 0) break; } if (nac.getSize() == 0) break; } } return true; } */ /* Creates morphism of left hand side of the kernel rule into left colim diagram. */ /* private OrdinaryMorphism createLkernLcolimMorph() { OrdinaryMorphism leftRequest = null; OrdinaryMorphism LkernLinst = null; OrdinaryMorphism isoLeft = null; for (int j=0; j<this.amalgamationData.size(); j++) { final AmalgamationDataOfSingleKernelMatch askMatchdata = this.amalgamationData.get(j); if (askMatchdata.getData().isEmpty()) continue; final AmalgamationRuleData kernelData = askMatchdata.getKernelData(); leftRequest = kernelData.leftRequestEdge; isoLeft = kernelData.isoCopyLeft; final Enumeration<Rule> keys = askMatchdata.getData().keys(); while (keys.hasMoreElements() && (leftRequest == null)) { final Rule rule = keys.nextElement(); final List<AmalgamationRuleData> datas = askMatchdata.getData().get(rule); for (int i=0; i<datas.size(); i++) { final AmalgamationRuleData data = datas.get(i); if (data.leftRequestEdge != null) { leftRequest = data.leftRequestEdge; break; } } } if (askMatchdata.getData().get(this.kernelRule) != null) { AmalgamationRuleData data = askMatchdata.getData().get(this.kernelRule).get(0); LkernLinst = data.LkernelLinst; isoLeft = data.isoCopyLeft; } else { Enumeration<List<AmalgamationRuleData>> all = askMatchdata.getData().elements(); while (all.hasMoreElements() && (LkernLinst == null)) { List<AmalgamationRuleData> datas = all.nextElement(); for (int i=0; i<datas.size(); i++) { final AmalgamationRuleData data = datas.get(i); if (data.LkernelLinst != null) { LkernLinst = data.LkernelLinst; break; } } } } if (LkernLinst != null && leftRequest != null) { final OrdinaryMorphism LkernL = this.bf.createMorphism( this.kernelRule.getLeft(), amalgamatedRule.getLeft()); //add mappings to LkerL morphism final Enumeration<GraphObject> el = isoLeft.getDomain(); while (el.hasMoreElements()) { final GraphObject obj = el.nextElement(); GraphObject img = leftRequest.getImage(LkernLinst.getImage(isoLeft.getImage(obj))); if (img == null && isoLeft == LkernLinst) { img = leftRequest.getImage(LkernLinst.getImage(obj)); } if (obj != null && img != null) { try { LkernL.addMapping(obj, img); } catch (BadMappingException ex) { // System.out.println("Covering.createLkernLcolimMorph mapping FAILED "+ex.getLocalizedMessage()); return null; } } else { // System.out.println("Covering.createLkernLcolimMorph FAILED "); return null; } } return LkernL; } } return null; } */ /** Returns match of the kernel rule. */ private void getKernelMatch() { this.kernelMatch = this.kernelRule.getMatch(); if (this.kernelMatch == null) { this.kernelMatch = this.bf.createMatch(this.kernelRule, this.hostGraph); this.kernelRule.setMatch(this.kernelMatch); // if (this.strategy.getProperties().get(CompletionPropertyBits.INJECTIVE)) // this.kernelMatch.setCompletionStrategy(new Completion_NAC(new Completion_InjCSP())); // else // this.kernelMatch.setCompletionStrategy(new Completion_NAC(new Completion_CSP())); } // else { // this.kernelMatch.getCompletionStrategy().getProperties() // .set(CompletionPropertyBits.INJECTIVE, // this.strategy.getProperties().get(CompletionPropertyBits.INJECTIVE)); // } if (this.strategy.getProperties().get(CompletionPropertyBits.INJECTIVE)) this.kernelMatch.setCompletionStrategy(new Completion_NAC(new Completion_InjCSP())); else this.kernelMatch.setCompletionStrategy(new Completion_NAC(new Completion_CSP())); this.kernelMatch.getCompletionStrategy().getProperties() .set(CompletionPropertyBits.IDENTIFICATION, this.strategy.getProperties().get(CompletionPropertyBits.IDENTIFICATION)); this.kernelMatch.getCompletionStrategy().getProperties() .set(CompletionPropertyBits.NAC, this.strategy.getProperties().get(CompletionPropertyBits.NAC)); this.kernelMatch.getCompletionStrategy().getProperties() .set(CompletionPropertyBits.PAC, this.strategy.getProperties().get(CompletionPropertyBits.PAC)); this.kernelMatch.getCompletionStrategy().getProperties() .set(CompletionPropertyBits.GAC, this.strategy.getProperties().get(CompletionPropertyBits.GAC)); this.kernelMatch.getCompletionStrategy().getProperties() .set(CompletionPropertyBits.DANGLING, this.strategy.getProperties().get(CompletionPropertyBits.DANGLING)); // unset dangling bit for match of kernel rule this.kernelMatch.getCompletionStrategy().getProperties() .set(CompletionPropertyBits.DANGLING, false); this.kernelMatch.getCompletionStrategy().setRandomisedDomain(this.strategy.isRandomisedDomain()); // this.kernelMatch.getCompletionStrategy().showProperties(); this.kernelMatch.getCompletionStrategy().initialize(this.kernelMatch); } /** Returns partial match of the specified multi rule. */ private Match getPartialMultiMatch(final MultiRule multiRule) { Match multiMatch = multiRule.getMatch(); // System.out.println("getPartialMultiMatch:::: "+multiRule.getName()+" match: "+multiMatch); if (multiMatch == null) { multiMatch = multiRule.getMatch(this.kernelRule); } if (multiMatch != null) { if (this.strategy.getProperties().get(CompletionPropertyBits.INJECTIVE)) { multiMatch.setCompletionStrategy(new Completion_NAC(new Completion_InjCSP())); } else { multiMatch.setCompletionStrategy(new Completion_NAC(new Completion_CSP())); } multiMatch.getCompletionStrategy().getProperties() .set(CompletionPropertyBits.IDENTIFICATION, this.strategy.getProperties().get(CompletionPropertyBits.IDENTIFICATION)); multiMatch.getCompletionStrategy().getProperties() .set(CompletionPropertyBits.NAC, this.strategy.getProperties().get(CompletionPropertyBits.NAC)); multiMatch.getCompletionStrategy().getProperties() .set(CompletionPropertyBits.PAC, this.strategy.getProperties().get(CompletionPropertyBits.PAC)); multiMatch.getCompletionStrategy().getProperties() .set(CompletionPropertyBits.GAC, this.strategy.getProperties().get(CompletionPropertyBits.GAC)); // unset dangling bit for match of multi rule multiMatch.getCompletionStrategy().getProperties() .set(CompletionPropertyBits.DANGLING, false); multiMatch.getCompletionStrategy().setRandomisedDomain(this.strategy.isRandomisedDomain()); // multiMatch.getCompletionStrategy().showProperties(); multiMatch.getCompletionStrategy().initialize(multiMatch); } return multiMatch; } private OrdinaryMorphism makeInstanceMorphism(final Graph src, final Graph tar) { AttrContext context = agg.attribute.impl.AttrTupleManager .getDefaultManager().newContext(AttrMapping.PLAIN_MAP); OrdinaryMorphism morph = new OrdinaryMorphism(src, tar, context); return morph; } private OrdinaryMorphism makeInstanceMatchOfRuleMatch( final OrdinaryMorphism LruleLinst, final Match ruleMatch) { // ((VarTuple)ruleMatch.getAttrContext().getVariables()).showVariables(); OrdinaryMorphism instMatch = this.makeInstanceMorphism(LruleLinst.getTarget(), ruleMatch.getTarget()); instMatch.setName(ruleMatch.getName()); final Enumeration<GraphObject> e = ruleMatch.getDomain(); while (e.hasMoreElements()) { final GraphObject o = e.nextElement(); final GraphObject oImg = LruleLinst.getImage(o); final GraphObject img = ruleMatch.getImage(o); try { instMatch.addMapping(oImg, img); // set attr value from graph to LHS object // adoptEntries(instMatch, img, oImg); } catch (BadMappingException ex) { return null; } } instMatch.addToAttrContext((VarTuple) ruleMatch.getRule().getAttrContext().getVariables()); // instMatch.addToAttrContextFromList(ruleMatch.getRule().getInputParametersLeft(), true); // instMatch.addToAttrContextFromList(ruleMatch.getRule().getInputParametersRight(), true); // instMatch.addToAttrContextFromList(ruleMatch.getRule().getNonInputParametersOfNewGraphObjects(), false); instMatch.adaptAttrContextValues(ruleMatch.getAttrContext()); // ((VarTuple)instMatch.getAttrContext().getVariables()).showVariables(); return instMatch; } private void tryToSetAttrValuesOfMorph(final OrdinaryMorphism morph) { for (Iterator<Node> e1 = morph.getSource().getNodesSet().iterator(); e1.hasNext();) { tryToSetValueFromVar(morph, e1.next()); } for (Iterator<Arc> e1 = morph.getSource().getArcsSet().iterator(); e1.hasNext();) { tryToSetValueFromVar(morph, e1.next()); } for (Iterator<Node> e1 = morph.getTarget().getNodesSet().iterator(); e1.hasNext();) { tryToSetValueFromVarAndExpr(morph, e1.next()); } for (Iterator<Arc> e1 = morph.getTarget().getArcsSet().iterator(); e1.hasNext();) { tryToSetValueFromVarAndExpr(morph, e1.next()); } } private void tryToSetValueFromVar(final OrdinaryMorphism morph, final GraphObject go) { if (go.getAttribute() != null) { ValueTuple value = (ValueTuple) go.getAttribute(); for (int j=0; j<value.getNumberOfEntries(); j++) { ValueMember mem = value.getValueMemberAt(j); if (mem.isSet() && mem.getExpr().isVariable()) { VarMember var = ((VarTuple)morph.getAttrContext().getVariables()) .getVarMemberAt(mem.getExprAsText()); if (var != null && var.isSet()) { mem.setExpr(var.getExpr()); } } } } } private void tryToSetValueFromVarAndExpr(final OrdinaryMorphism morph, final GraphObject go) { if (go.getAttribute() != null) { ValueTuple value = (ValueTuple) go.getAttribute(); for (int j=0; j<value.getNumberOfEntries(); j++) { ValueMember mem = value.getValueMemberAt(j); if (mem.isSet()) { if (mem.getExpr().isVariable()) { VarMember var = ((VarTuple)morph.getAttrContext().getVariables()) .getVarMemberAt(mem.getExprAsText()); if (var != null && var.isSet()) { mem.setExpr(var.getExpr()); } } else if (mem.getExpr().isComplex()) { try { mem.getExpr().evaluate(morph.getAttrContext()); } catch (AttrHandlerException ex) { System.out.println("Covering.tryToComputeAttrExpresionOfMorph:: "+ex); } } } } } } @SuppressWarnings("unused") private void adoptEntries( final OrdinaryMorphism morph, final GraphObject from, final GraphObject to) { if (from.getAttribute() != null && to.getAttribute() != null) { ValueTuple valFrom = (ValueTuple) from.getAttribute(); ValueTuple valTo = (ValueTuple) to.getAttribute(); for (int i=0; i<valFrom.getNumberOfEntries(); i++) { ValueMember vmFrom = valFrom.getEntryAt(i); if (vmFrom.isSet()) { ValueMember vmTo = valTo.getEntryAt(vmFrom.getName()); if (vmTo != null) vmTo.setExprAsText(vmFrom.getExprAsText()); } } } } private void adoptEntriesWhereEmpty( final OrdinaryMorphism morph, final GraphObject from, final GraphObject to, final GraphObject origTo) { if (morph.getImage(from) != null && from.getAttribute() != null && to.getAttribute() != null) { final ValueTuple valuefrom = (ValueTuple) from.getAttribute(); final ValueTuple value = (ValueTuple) to.getAttribute(); for (int i = 0; i < value.getSize(); i++) { ValueMember vm = value.getValueMemberAt(i); ValueMember vmfrom = valuefrom.getValueMemberAt(vm.getName()); if (origTo == null) { if (!vm.isSet() && vmfrom != null && vmfrom.isSet()) { vm.setExprAsText(vmfrom.getExprAsText()); } } else { ValueMember vm_origTo = ((ValueTuple)origTo.getAttribute()).getValueMemberAt(vm.getName()); if (vm_origTo.isSet()) { if (!vm.isSet() && vmfrom != null && vmfrom.isSet()) { vm.setExprAsText(vmfrom.getExprAsText()); } } } } } } /* private void setAttrCond(final Rule r, final OrdinaryMorphism LiRi) { // System.out.println("Covering.setAttrCond ..."); final VarTuple varsLiRi = (VarTuple) LiRi.getAttrContext().getVariables(); final VarTuple varsR = (VarTuple) r.getAttrContext().getVariables(); for(int jj=0; jj<varsR.getSize(); jj++) { final VarMember vm = varsR.getVarMemberAt(jj); final DeclMember dm = (DeclMember) vm.getDeclaration(); if(!varsLiRi.isDeclared(dm.getTypeName(), dm.getName())){ varsLiRi.declare(dm.getHandler(), dm.getTypeName(), dm.getName()); final VarMember var = varsLiRi .getVarMemberAt(vm.getName()); var.setInputParameter(vm.isInputParameter()); if(var.isInputParameter() && ((ValueMember)vm).isSet()) { ((ValueMember)var).setExprAsText(((ValueMember)vm).getExprAsText()); } } } final CondTuple condsR = (CondTuple) r.getAttrContext().getConditions(); final CondTuple condsLiRi = (CondTuple) LiRi.getAttrContext().getConditions(); for (int jj=0; jj<condsR.getSize(); jj++) { final CondMember cm = condsR.getCondMemberAt(jj); if(!cm.getExprAsText().equals("") && !condsLiRi.contains(cm.getExprAsText())) { condsLiRi.addCondition(cm.getExprAsText()); } } } */ private void setAttributeVariable( final String from, final String to, final AttrContext ac, final Iterator<?> e) { final VarTuple vars = (VarTuple) ac.getVariables(); while (e.hasNext()) { final GraphObject obj = (GraphObject)e.next(); if (obj.getAttribute() == null) { continue; } final ValueTuple fromObj = (ValueTuple) obj.getAttribute(); for (int i=0; i<fromObj.getSize(); i++) { final ValueMember fromVM = fromObj.getValueMemberAt(i); if (fromVM.isSet()) { if (fromVM.getExpr().isVariable() && fromVM.getExprAsText().equals(from)) { fromVM.setExprAsText(to); // test variable final VarMember var = vars.getVarMemberAt(to); if(var != null) { // System.out.println("Variable "+to+" exists"); } else { // declare variable vars.declare(fromVM.getDeclaration().getHandler(), fromVM.getDeclaration().getTypeName(), to); } } else if (fromVM.getExpr().isComplex()) { // final VarMember toVM = vars.getVarMemberAt(to); final JexExpr oldExpr = (JexExpr) fromVM.getExpr(); final Vector<String> variables = new Vector<String>(); oldExpr.getAllVariables(variables); this.findPrimaryAndReplace( (SimpleNode) oldExpr.getAST(), from, to, ac, vars); } } } } } private void renameVariables(final Rule basicr, final OrdinaryMorphism LiRi, int index) { // System.out.println("Covering.renameVariables ... for "+index); final String mark = String.valueOf(index); final VarTuple varsBasic = (VarTuple) basicr.getAttrContext().getVariables(); final VarTuple varsLiRi = (VarTuple)LiRi.getAttrContext().getVariables(); for (int i=0; i<varsLiRi.getSize(); i++) { final VarMember vm = varsLiRi.getVarMemberAt(i); final VarMember vmKernel = varsBasic.getVarMemberAt(vm.getName()); // do not rename variables of the kernel rule if(vmKernel == null) { final String from = vm.getName(); final String to = vm.getName()+mark; vm.getDeclaration().setName(to); // rename variables in left/right graphs of instance morphs setAttributeVariable(from, to, LiRi.getAttrContext(), LiRi.getSource().getNodesSet().iterator()); setAttributeVariable(from, to, LiRi.getAttrContext(), LiRi.getSource().getArcsSet().iterator()); setAttributeVariable(from, to, LiRi.getAttrContext(), LiRi.getTarget().getNodesSet().iterator()); setAttributeVariable(from, to, LiRi.getAttrContext(), LiRi.getTarget().getArcsSet().iterator()); // rename variables in conditions final CondTuple conds = (CondTuple) LiRi.getAttrContext().getConditions(); for (int j=0; j<conds.getSize(); j++) { final CondMember cm = conds.getCondMemberAt(j); // final String condStr = cm.getExprAsText(); final Vector<String> v1 = cm.getAllVariables(); if (v1.contains(from)) { final JexExpr oldExpr = (JexExpr) cm.getExpr(); final Vector<String> variables = new Vector<String>(); oldExpr.getAllVariables(variables); this.findPrimaryAndReplace((SimpleNode) oldExpr.getAST(), from, to, LiRi.getAttrContext(), null); } } } } } private void findPrimaryAndReplace( final SimpleNode node, final String from, final String to, final AttrContext ac, final VarTuple vars) { // System.out.println("Covering.findPrimaryAndChange: in "+node); final SymbolTable symbs = ac; // System.out.println(ac); for (int j=0; j<node.jjtGetNumChildren(); j++) { final SimpleNode n = (SimpleNode) node.jjtGetChild(j); // System.out.println(j+" Child of ast: "+n+" is "+n.getString()+" "+n.getIdentifier()); if (n instanceof ASTPrimaryExpression || n instanceof ASTId) { // String ident = ""; // if (n instanceof ASTPrimaryExpression) // ident = ((ASTPrimaryExpression) n).getIdentifier(); // else if (n instanceof ASTId) // ident = ((ASTId) n).getIdentifier(); // System.out.println("Identifier: "+ ident+" "+ n.getString()); if (n.getString().equals(from)) { // System.out.println("SymbolTable: "+from+" type= "+symbs.getType(from)+" expr= "+ symbs.getExpr(from)); // System.out.println("SymbolTable: "+to+" type= "+symbs.getType(to)+" expr= "+ symbs.getExpr(to)); boolean to_found = false; final ContextView context = (ContextView) symbs; final VarTuple vt = (VarTuple) context.getVariables(); for (int i=0; i<vt.getSize(); i++ ){ final VarMember vm = vt.getVarMemberAt(i); // System.out.println(vm.getName()+" "+vm); if (vm.getName().equals(to)) { to_found = true; // System.out.println(to+" exists:: "+vm.getName()+" "+vm); final HandlerType t = vm.getDeclaration().getType(); try { final HandlerExpr expression = vm.getHandler().newHandlerExpr(t, to); // System.out.println(expression.getAST()); final SimpleNode test = (SimpleNode) expression.getAST().jjtGetChild(0); // System.out.println(test); node.replaceChild(n, test); // System.out.println("child replaced: getString()= "+node.jjtGetChild(0).getString()+" "+node.jjtGetChild(0).toString()); } catch (AttrHandlerException ex) {} } } if (!to_found) { // System.out.println("Something wrong: "+to+" NOT FOUND in SymbolTable! Try to replace if variable exists i VarTuple."); for (int i=0; i<vars.getSize(); i++) { final VarMember vm = vars.getVarMemberAt(i); // System.out.println(vm.getName()+" "+vm); if (vm.getName().equals(to)) { to_found = true; // System.out.println(to+" exists in vars "+vm.getName()+" "+vm); final HandlerType t = vm.getDeclaration().getType(); try { final HandlerExpr expression = vm.getHandler().newHandlerExpr(t, to); // System.out.println(expression.getAST()); final SimpleNode test = (SimpleNode) expression.getAST().jjtGetChild(0); // System.out.println(test); node.replaceChild(n, test); // System.out.println("child replaced: getString()= "+node.jjtGetChild(0).getString()+" "+node.jjtGetChild(0).toString()); } catch (AttrHandlerException ex) {} } } } } else if (n.getString().contains(from)) { // System.out.println("Take Child of ast: "+n); findPrimaryAndReplace(n, from, to, ac, vars); } } else { // System.out.println("Take Child of ast: "+n); findPrimaryAndReplace(n, from, to, ac, vars); } } } }