/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.jena.graph; import java.util.Iterator; import java.util.Set; import org.apache.jena.util.CollectionFactory ; /** GraphExtract offers a very simple recursive extraction of a subgraph with a specified root in some supergraph. The recursion is terminated by triples that satisfy some supplied boundary condition. */ public class GraphExtract { protected final TripleBoundary b; public GraphExtract( TripleBoundary b ) { this.b = b; } /** Answer a new graph which is the reachable subgraph from <code>node</code> in <code>graph</code> with the terminating condition given by the TripleBoundary passed to the constructor. */ public Graph extract( Node node, Graph graph ) { return extractInto( Factory.createGraphMem(), node, graph ); } /** Answer the graph <code>toUpdate</code> augmented with the sub-graph of <code>extractFrom</code> reachable from <code>root</code> bounded by this instance's TripleBoundary. */ public Graph extractInto( Graph toUpdate, Node root, Graph extractFrom ) { new Extraction( b, toUpdate, extractFrom ).extractInto( root ); return toUpdate; } /** This is the class that does all the work, in the established context of the source and destination graphs, the TripleBoundary that determines the limits of the extraction, and a local set <code>active</code> of nodes already seen and hence not to be re-processed. */ protected static class Extraction { protected Graph toUpdate; protected Graph extractFrom; protected Set<Node> active; protected TripleBoundary b; Extraction( TripleBoundary b, Graph toUpdate, Graph extractFrom ) { this.toUpdate = toUpdate; this.extractFrom = extractFrom; this.active = CollectionFactory.createHashedSet(); this.b = b; } public void extractInto( Node root ) { active.add( root ); Iterator<Triple> it = extractFrom.find( root, Node.ANY, Node.ANY ); while (it.hasNext()) { Triple t = it.next(); Node subRoot = t.getObject(); toUpdate.add( t ); if (! (active.contains( subRoot ) || b.stopAt( t ))) extractInto( subRoot ); } } } }