/////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Inserts code to get an implicit node from an edge /// receives insertion point, returns new insertion point /// </summary> private InterpretationPlan insertImplicitNodeFromEdge( InterpretationPlan insertionPoint, SearchPlanEdgeNode edge, SearchPlanNodeNode currentNode, ImplicitNodeType nodeType) { int targetType = currentNode.PatternElement.TypeID; if (nodeType == ImplicitNodeType.Source) { currentNode.nodeMatcher = new InterpretationPlanImplicitSource(targetType, edge.edgeMatcher, currentNode); } else if (nodeType == ImplicitNodeType.Target) { currentNode.nodeMatcher = new InterpretationPlanImplicitTarget(targetType, edge.edgeMatcher, currentNode); } else { Debug.Assert(nodeType != ImplicitNodeType.TheOther); if (currentNodeIsSecondIncidentNodeOfEdge(currentNode, edge)) { currentNode.nodeMatcher = new InterpretationPlanImplicitTheOther(targetType, edge.edgeMatcher, edge.PatternEdgeSource == currentNode ? edge.PatternEdgeTarget.nodeMatcher : edge.PatternEdgeSource.nodeMatcher, currentNode); } else // edge connects to first incident node { if (edge.PatternEdgeSource == edge.PatternEdgeTarget) { // reflexive edge without direction iteration as we don't want 2 matches currentNode.nodeMatcher = new InterpretationPlanImplicitSource(targetType, edge.edgeMatcher, currentNode); } else { edge.directionVariable = new InterpretationPlanBothDirections(); insertionPoint.next = edge.directionVariable; insertionPoint = insertionPoint.next; currentNode.nodeMatcher = new InterpretationPlanImplicitSourceOrTarget(targetType, edge.edgeMatcher, edge.directionVariable, currentNode); } } } currentNode.nodeMatcher.prev = insertionPoint; insertionPoint.next = currentNode.nodeMatcher; insertionPoint = insertionPoint.next; return(insertionPoint); }
/// <summary> /// Decides which check connectedness operations are needed for the given node just drawn from edge /// and inserts them into the interpretation plan /// receives insertion point, returns new insertion point /// </summary> private InterpretationPlan decideOnAndInsertCheckConnectednessOfImplicitNodeFromEdge( InterpretationPlan insertionPoint, SearchPlanNodeNode node, SearchPlanEdgeNode originatingEdge, SearchPlanNodeNode otherNodeOfOriginatingEdge) { // check for edges required by the pattern to be incident to the given node // only if the node was not taken from the given originating edge // with the exception of reflexive edges, as these won't get checked thereafter foreach (SearchPlanEdgeNode edge in node.OutgoingPatternEdges) { if (((PatternEdge)edge.PatternElement).fixedDirection || edge.PatternEdgeSource == edge.PatternEdgeTarget) { if (edge != originatingEdge || node == otherNodeOfOriginatingEdge) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeFixedDirection(insertionPoint, node, edge, CheckCandidateForConnectednessType.Source); } } else { if (edge != originatingEdge || node == otherNodeOfOriginatingEdge) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeBothDirections(insertionPoint, node, edge); } } } foreach (SearchPlanEdgeNode edge in node.IncomingPatternEdges) { if (((PatternEdge)edge.PatternElement).fixedDirection || edge.PatternEdgeSource == edge.PatternEdgeTarget) { if (edge != originatingEdge || node == otherNodeOfOriginatingEdge) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeFixedDirection(insertionPoint, node, edge, CheckCandidateForConnectednessType.Target); } } else { if (edge != originatingEdge || node == otherNodeOfOriginatingEdge) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeBothDirections(insertionPoint, node, edge); } } } return(insertionPoint); }
/// <summary> /// Interpretation plan operations implementing the /// Extend Incoming|Outgoing|IncomingOrOutgoing search plan operation /// are created and inserted into the interpretation plan at the insertion point /// </summary> private void buildIncident( InterpretationPlan insertionPoint, int index, SearchPlanNodeNode source, SearchPlanEdgeNode target, IncidentEdgeType edgeType) { // get candidate = iterate available incident edges insertionPoint = insertIncidentEdgeFromNode(insertionPoint, source, target, edgeType); // check connectedness of candidate insertionPoint = decideOnAndInsertCheckConnectednessOfIncidentEdgeFromNode(insertionPoint, target, source, edgeType == IncidentEdgeType.Incoming); // continue with next operation target.Visited = true; BuildInterpretationPlan(insertionPoint, index + 1); target.Visited = false; }
/// <summary> /// Interpretation plan operations implementing the /// Lookup edge search plan operation /// are created and inserted into the interpretation plan at the insertion point /// </summary> private void buildLookup( InterpretationPlan insertionPoint, int index, SearchPlanEdgeNode target) { // get candidate = iterate available edges target.edgeMatcher = new InterpretationPlanLookupEdge(target.PatternElement.TypeID, target); target.edgeMatcher.prev = insertionPoint; insertionPoint.next = target.edgeMatcher; insertionPoint = insertionPoint.next; // check connectedness of candidate insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeFromLookup(insertionPoint, target); // continue with next operation target.Visited = true; BuildInterpretationPlan(insertionPoint, index + 1); target.Visited = false; }
/// <summary> /// Inserts code to get an incident edge from some node /// receives insertion point, returns new insertion point /// </summary> private InterpretationPlan insertIncidentEdgeFromNode( InterpretationPlan insertionPoint, SearchPlanNodeNode node, SearchPlanEdgeNode currentEdge, IncidentEdgeType incidentType) { int targetType = currentEdge.PatternElement.TypeID; if (incidentType == IncidentEdgeType.Incoming) { currentEdge.edgeMatcher = new InterpretationPlanIncoming(targetType, node.nodeMatcher, currentEdge); } else if (incidentType == IncidentEdgeType.Outgoing) { currentEdge.edgeMatcher = new InterpretationPlanOutgoing(targetType, node.nodeMatcher, currentEdge); } else // IncidentEdgeType.IncomingOrOutgoing { if (currentEdge.PatternEdgeSource == currentEdge.PatternEdgeTarget) { // reflexive edge without direction iteration as we don't want 2 matches currentEdge.edgeMatcher = new InterpretationPlanIncoming(targetType, node.nodeMatcher, currentEdge); } else { currentEdge.directionVariable = new InterpretationPlanBothDirections(); insertionPoint.next = currentEdge.directionVariable; insertionPoint = insertionPoint.next; currentEdge.edgeMatcher = new InterpretationPlanIncomingOrOutgoing(targetType, node.nodeMatcher, currentEdge.directionVariable, currentEdge); } } currentEdge.edgeMatcher.prev = insertionPoint; insertionPoint.next = currentEdge.edgeMatcher; insertionPoint = insertionPoint.next; return(insertionPoint); }
/// <summary> /// Decides which check connectedness operations are needed for the given edge in both directions /// and inserts them into the interpretation plan /// receives insertion point, returns new insertion point /// </summary> private InterpretationPlan decideOnAndInsertCheckConnectednessOfEdgeBothDirections( InterpretationPlan insertionPoint, SearchPlanEdgeNode edge, bool edgeDeterminationContainsFirstNodeLoop) { // check whether source/target-nodes of the candidate edge // are the same as the already found nodes to which the edge must be incident if (!edgeDeterminationContainsFirstNodeLoop && currentEdgeConnectsToFirstIncidentNode(edge)) { SearchPlanNodeNode nodeRequiringFirstNodeLoop = edge.PatternEdgeSource != null ? edge.PatternEdgeSource : edge.PatternEdgeTarget; // due to currentEdgeConnectsToFirstIncidentNode: at least on incident node available if (edge.PatternEdgeSource == edge.PatternEdgeTarget) { // reflexive edge without direction iteration as we don't want 2 matches insertionPoint.next = new InterpretationPlanCheckConnectednessSource( nodeRequiringFirstNodeLoop.nodeMatcher, edge.edgeMatcher); // might be Target as well insertionPoint = insertionPoint.next; } else { edge.directionVariable = new InterpretationPlanBothDirections(); insertionPoint.next = edge.directionVariable; insertionPoint = insertionPoint.next; insertionPoint.next = new InterpretationPlanCheckConnectednessSourceOrTarget( nodeRequiringFirstNodeLoop.nodeMatcher, edge.edgeMatcher, edge.directionVariable); insertionPoint = insertionPoint.next; } } if (currentEdgeConnectsToSecondIncidentNode(edge)) { // due to currentEdgeConnectsToSecondIncidentNode: both incident node available insertionPoint.next = new InterpretationPlanCheckConnectednessTheOther( edge.PatternEdgeTarget.nodeMatcher, edge.edgeMatcher, edge.PatternEdgeSource.nodeMatcher); insertionPoint = insertionPoint.next; } return(insertionPoint); }
/// <summary> /// Decides which check connectedness operations are needed for the given edge determined from incident node /// and inserts them into the interpretation plan /// receives insertion point, returns new insertions point /// </summary> private InterpretationPlan decideOnAndInsertCheckConnectednessOfIncidentEdgeFromNode( InterpretationPlan insertionPoint, SearchPlanEdgeNode edge, SearchPlanNodeNode originatingNode, bool edgeIncomingAtOriginatingNode) { if (((PatternEdge)edge.PatternElement).fixedDirection) { // don't need to check if the edge is not required by the pattern to be incident to some given node // or if the edge was taken from the given originating node if (edge.PatternEdgeSource != null) { if (!(!edgeIncomingAtOriginatingNode && edge.PatternEdgeSource == originatingNode)) { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeFixedDirection(insertionPoint, edge, CheckCandidateForConnectednessType.Source); } } if (edge.PatternEdgeTarget != null) { if (!(edgeIncomingAtOriginatingNode && edge.PatternEdgeTarget == originatingNode)) { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeFixedDirection(insertionPoint, edge, CheckCandidateForConnectednessType.Target); } } } else { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeBothDirections(insertionPoint, edge, true); } return(insertionPoint); }
/// <summary> /// Decides which check connectedness operations are needed for the given node just determined by lookup /// and inserts them into the interpretation plan /// receives insertion point, returns new insertion point /// </summary> private InterpretationPlan decideOnAndInsertCheckConnectednessOfNodeFromLookup( InterpretationPlan insertionPoint, SearchPlanNodeNode node) { // check for edges required by the pattern to be incident to the given node foreach (SearchPlanEdgeNode edge in node.OutgoingPatternEdges) { if (((PatternEdge)edge.PatternElement).fixedDirection || edge.PatternEdgeSource == edge.PatternEdgeTarget) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeFixedDirection(insertionPoint, node, edge, CheckCandidateForConnectednessType.Source); } else { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeBothDirections(insertionPoint, node, edge); } } foreach (SearchPlanEdgeNode edge in node.IncomingPatternEdges) { if (((PatternEdge)edge.PatternElement).fixedDirection || edge.PatternEdgeSource == edge.PatternEdgeTarget) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeFixedDirection(insertionPoint, node, edge, CheckCandidateForConnectednessType.Target); } else { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeBothDirections(insertionPoint, node, edge); } } return(insertionPoint); }
/// <summary> /// Recursively assembles interpretation plan from scheduled search plan, beginning at index 0. /// Decides which specialized build procedure is to be called. /// The specialized build procedure then calls this procedure again, /// in order to process the next search plan operation at the following index. /// The insertionPoint is the lastly built operation; /// the next operation built is inserted into the next link of it, /// then it becomes the current insertionPoint. /// </summary> private void BuildInterpretationPlan(InterpretationPlan insertionPoint, int index) { if (index >= ssp.Operations.Length) { // end of scheduled search plan reached, stop recursive iteration buildMatchComplete(insertionPoint); return; } SearchOperation op = ssp.Operations[index]; // for current scheduled search plan operation // insert corresponding interpretation plan operations into interpretation plan switch (op.Type) { case SearchOperationType.Lookup: if (((SearchPlanNode)op.Element).NodeType == PlanNodeType.Node) { buildLookup(insertionPoint, index, (SearchPlanNodeNode)op.Element); } else { buildLookup(insertionPoint, index, (SearchPlanEdgeNode)op.Element); } break; case SearchOperationType.ImplicitSource: buildImplicit(insertionPoint, index, (SearchPlanEdgeNode)op.SourceSPNode, (SearchPlanNodeNode)op.Element, ImplicitNodeType.Source); break; case SearchOperationType.ImplicitTarget: buildImplicit(insertionPoint, index, (SearchPlanEdgeNode)op.SourceSPNode, (SearchPlanNodeNode)op.Element, ImplicitNodeType.Target); break; case SearchOperationType.Implicit: buildImplicit(insertionPoint, index, (SearchPlanEdgeNode)op.SourceSPNode, (SearchPlanNodeNode)op.Element, ImplicitNodeType.SourceOrTarget); break; case SearchOperationType.Incoming: buildIncident(insertionPoint, index, (SearchPlanNodeNode)op.SourceSPNode, (SearchPlanEdgeNode)op.Element, IncidentEdgeType.Incoming); break; case SearchOperationType.Outgoing: buildIncident(insertionPoint, index, (SearchPlanNodeNode)op.SourceSPNode, (SearchPlanEdgeNode)op.Element, IncidentEdgeType.Outgoing); break; case SearchOperationType.Incident: buildIncident(insertionPoint, index, (SearchPlanNodeNode)op.SourceSPNode, (SearchPlanEdgeNode)op.Element, IncidentEdgeType.IncomingOrOutgoing); break; case SearchOperationType.Condition: buildCondition(insertionPoint, index, (PatternCondition)op.Element); break; default: throw new Exception("Unknown or unsupported search operation"); } }