/** * Given a query q, a variable x and a starting node n projecting x, * retrieves all substitutions (from ConstructionNodes) generating a value for x in the subtree of q * rooted in n. * Note that unions may cause multiple such substitutions to be returned. * <p> * The intended usage of this method it to determine the type of a variable from the returned substitution. * Therefore this method is robust to simple variable renaming, * but only until a more complex substitution is found. * E.g. if [x/x2], [x2/x3] and [x3/URI("http://myURI{}", x4] are three substitutions found in that order in a same * branch, * then x/URI("http://myURI{}", x4) will be the only output substitution for that branch. * <p> * This method does not support composition otherwise. * E.g. if [x/+(x1,x2)] and [x2/x3] are found in that order in a branch, * then [x/+(x1,x2)] is returned. */ @Override public ImmutableSet<ImmutableTerm> extract(Variable variable, QueryNode node, IntermediateQuery query) { if (query.contains(node)) { if (query.getVariables(node).contains(variable)) { return getDefinitions(variable, variable, node, query) .collect(ImmutableCollectors.toSet()); } throw new IllegalArgumentException("The node should project the variable"); } throw new IllegalArgumentException("The node should be in the query"); }
/** * TODO: explain * * Propagates descending substitutions in some other branches * */ private static <T extends QueryNode> NodeTrackingResults<T> applyDescendingPropagations( ImmutableList<DescendingPropagationParams> propagations, IntermediateQuery query, QueryTreeComponent treeComponent, T originalFocusNode, Optional<NodeTracker> optionalNodeTracker) throws EmptyQueryException { NodeTracker tracker = optionalNodeTracker .orElseGet(() -> new NodeTrackerImpl()); for(DescendingPropagationParams params : propagations) { if (!query.contains(params.focusNode)) { break; } propagateSubstitutionDownToNodes(params.focusNode, params.otherChildren.stream(), params.substitution, query, treeComponent, Optional.of(tracker)); } NodeTracker.NodeUpdate<T> update = tracker.getUpdate(query, originalFocusNode); return update.getNewNode() .map(n -> new NodeTrackingResultsImpl<>(query, n, optionalNodeTracker)) .orElseGet(() -> update.getReplacingChild() .map(n -> new NodeTrackingResultsImpl<T>(query, Optional.of(n), optionalNodeTracker)) .orElseGet(() -> new NodeTrackingResultsImpl<T>(query, update.getOptionalNextSibling(query), update.getOptionalClosestAncestor(query), optionalNodeTracker))); }
@Override public void appendSubtree(QueryNode subQueryRoot, IntermediateQuery sourceQuery) { if(sourceQuery.contains(subQueryRoot)) { ImmutableList<QueryNode> children = sourceQuery.getChildren(subQueryRoot); addChildren(subQueryRoot, children); children.forEach(n -> appendSubtree(n, sourceQuery)); }else { throw new NodeNotInQueryException("Node " + subQueryRoot + " is not in the query"); } }
@Override public void appendSubtree(QueryNode subQueryRoot, IntermediateQuery sourceQuery) { if(sourceQuery.contains(subQueryRoot)) { ImmutableList<QueryNode> children = sourceQuery.getChildren(subQueryRoot); addChildren(subQueryRoot, children); children.forEach(n -> appendSubtree(n, sourceQuery)); }else { throw new NodeNotInQueryException("Node " + subQueryRoot + " is not in the query"); } }
if (intermediateQuery.contains(intensionalNode)) { intermediateQuery = rootCnEnforcer.enforceRootCn(intermediateQuery); QueryMergingProposal mergingProposal = new QueryMergingProposalImpl(intensionalNode,