public SubruleDebuggingDecision Decide(SubruleDebuggingEvent sde, object data, IGraphProcessingEnvironment procEnv) { if (!enabled) { return(SubruleDebuggingDecision.Undefined); } if (debuggingEvent != sde) { return(SubruleDebuggingDecision.Undefined); } switch (sde) { case SubruleDebuggingEvent.Add: case SubruleDebuggingEvent.Rem: case SubruleDebuggingEvent.Emit: case SubruleDebuggingEvent.Halt: case SubruleDebuggingEvent.Highlight: { string message = (string)data; switch (messageMatchingMode) { case SubruleMesssageMatchingMode.Equals: if (message == messageToMatch) { return(decisionOnMatch); } break; case SubruleMesssageMatchingMode.StartsWith: if (message.StartsWith(messageToMatch)) { return(decisionOnMatch); } break; case SubruleMesssageMatchingMode.EndsWith: if (message.EndsWith(messageToMatch)) { return(decisionOnMatch); } break; case SubruleMesssageMatchingMode.Contains: if (message.Contains(messageToMatch)) { return(decisionOnMatch); } break; default: throw new Exception("INTERNAL FAILURE: unkonwn message matching mode"); } } return(SubruleDebuggingDecision.Undefined); case SubruleDebuggingEvent.Match: { IMatches matches = (IMatches)data; if (matches.Producer == actionToMatch) { if (ifClause != null) { object oldThis = procEnv.GetVariableValue("this"); bool result = false; foreach (IMatch match in matches) { procEnv.SetVariableValue("this", match); if ((bool)ifClause.Evaluate(procEnv)) { result = true; break; } } procEnv.SetVariableValue("this", oldThis); if (result) { return(decisionOnMatch); } } else { return(decisionOnMatch); } } return(SubruleDebuggingDecision.Undefined); } case SubruleDebuggingEvent.New: case SubruleDebuggingEvent.Delete: case SubruleDebuggingEvent.Retype: case SubruleDebuggingEvent.SetAttributes: { IGraphElement elem = (IGraphElement)data; if (nameToMatch != null) { if (procEnv.NamedGraph.GetElementName(elem) == nameToMatch) { if (If(elem, procEnv)) { return(decisionOnMatch); } } } if (typeToMatch != null) { if (elem.Type is NodeType && typeToMatch is NodeType && elem.Type.IsA(typeToMatch) || elem.Type is EdgeType && typeToMatch is EdgeType && elem.Type.IsA(typeToMatch)) { if (onlyThisType) { if (typeToMatch.IsA(elem.Type)) { if (If(elem, procEnv)) { return(decisionOnMatch); } } } else { if (If(elem, procEnv)) { return(decisionOnMatch); } } } } return(SubruleDebuggingDecision.Undefined); } default: return(SubruleDebuggingDecision.Undefined); } }
/// <summary> /// Determines which homomorphy check operations are necessary /// at the operation of the given position within the scheduled search plan /// and appends them. /// </summary> private static void DetermineAndAppendHomomorphyChecks(IGraphModel model, ScheduledSearchPlan ssp, int j) { // take care of global homomorphy FillInGlobalHomomorphyPatternElements(ssp, j); /////////////////////////////////////////////////////////////////////////// // first handle special case pure homomorphy SearchPlanNode spn_j = (SearchPlanNode)ssp.Operations[j].Element; if (spn_j.ElementID == -1) { // inlined from independent for better matching, independent from the rest return; } bool homToAll = true; if (spn_j.NodeType == PlanNodeType.Node) { for (int i = 0; i < ssp.PatternGraph.nodesPlusInlined.Length; ++i) { if (!ssp.PatternGraph.homomorphicNodes[spn_j.ElementID - 1, i]) { homToAll = false; break; } } } else //(spn_j.NodeType == PlanNodeType.Edge) { for (int i = 0; i < ssp.PatternGraph.edgesPlusInlined.Length; ++i) { if (!ssp.PatternGraph.homomorphicEdges[spn_j.ElementID - 1, i]) { homToAll = false; break; } } } if (homToAll) { // operation is allowed to be homomorph with everything // no checks for isomorphy or restricted homomorphy needed at all return; } /////////////////////////////////////////////////////////////////////////// // no pure homomorphy, so we have restricted homomorphy or isomorphy // and need to inspect the operations before, together with the homomorphy matrix // for determining the necessary homomorphy checks GrGenType[] types; bool[,] hom; if (spn_j.NodeType == PlanNodeType.Node) { types = model.NodeModel.Types; hom = ssp.PatternGraph.homomorphicNodes; } else // (spn_j.NodeType == PlanNodeType.Edge) { types = model.EdgeModel.Types; hom = ssp.PatternGraph.homomorphicEdges; } // order operation to check against all elements it's not allowed to be homomorph to // iterate through the operations before our position bool homomorphyPossibleAndAllowed = false; for (int i = 0; i < j; ++i) { // only check operations computing nodes or edges if (ssp.Operations[i].Type == SearchOperationType.Condition || ssp.Operations[i].Type == SearchOperationType.NegativePattern || ssp.Operations[i].Type == SearchOperationType.IndependentPattern || ssp.Operations[i].Type == SearchOperationType.Assign || ssp.Operations[i].Type == SearchOperationType.AssignVar || ssp.Operations[i].Type == SearchOperationType.DefToBeYieldedTo || ssp.Operations[i].Type == SearchOperationType.InlinedIndependentCheckForDuplicateMatch) { continue; } SearchPlanNode spn_i = (SearchPlanNode)ssp.Operations[i].Element; if (spn_i.NodeType != spn_j.NodeType) { // don't compare nodes with edges continue; } if (spn_i.ElementID == -1) { // inlined from independent for better matching, independent from the rest continue; } // find out whether element types are disjoint GrGenType type_i = types[spn_i.PatternElement.TypeID]; GrGenType type_j = types[spn_j.PatternElement.TypeID]; bool disjoint = true; foreach (GrGenType subtype_i in type_i.SubOrSameTypes) { if (type_j.IsA(subtype_i) || subtype_i.IsA(type_j)) // IsA==IsSuperTypeOrSameType { disjoint = false; break; } } if (disjoint) { // don't check elements if their types are disjoint continue; } // at this position we found out that spn_i and spn_j // might get matched to the same host graph element, i.e. homomorphy is possible // if that's ok we don't need to insert checks to prevent this from happening if (hom[spn_i.ElementID - 1, spn_j.ElementID - 1]) { homomorphyPossibleAndAllowed = true; continue; } // otherwise the generated matcher code has to check // that pattern element j doesn't get bound to the same graph element // the pattern element i is already bound to if (ssp.Operations[j].Isomorphy.PatternElementsToCheckAgainst == null) { ssp.Operations[j].Isomorphy.PatternElementsToCheckAgainst = new List <SearchPlanNode>(); } ssp.Operations[j].Isomorphy.PatternElementsToCheckAgainst.Add(spn_i); // if spn_j might get matched to the same host graph element as spn_i and this is not allowed // make spn_i set the is-matched-bit so that spn_j can detect this situation ssp.Operations[i].Isomorphy.SetIsMatchedBit = true; } // only if elements, the operation must be isomorph to, were matched before // (otherwise there were only elements, the operation is allowed to be homomorph to, // matched before, so no check needed here) if (ssp.Operations[j].Isomorphy.PatternElementsToCheckAgainst != null && ssp.Operations[j].Isomorphy.PatternElementsToCheckAgainst.Count > 0) { // order operation to check whether the is-matched-bit is set ssp.Operations[j].Isomorphy.CheckIsMatchedBit = true; } // if no check for isomorphy was skipped due to homomorphy being allowed // pure isomorphy is to be guaranteed - simply check the is-matched-bit and be done // the pattern elements to check against are only needed // if spn_j is allowed to be homomorph to some elements but must be isomorph to some others if (ssp.Operations[j].Isomorphy.CheckIsMatchedBit && !homomorphyPossibleAndAllowed) { ssp.Operations[j].Isomorphy.PatternElementsToCheckAgainst = null; } }