001: /*****************************************************************************
002: * Source code information
003: * -----------------------
004: * Original author Ian Dickinson, HP Labs Bristol
005: * Author email Ian.Dickinson@hp.com
006: * Package Jena 2
007: * Web http://sourceforge.net/projects/jena/
008: * Created 4 Mar 2003
009: * Filename $RCSfile: MultiUnion.java,v $
010: * Revision $Revision: 1.28 $
011: * Release status $State: Exp $
012: *
013: * Last modified on $Date: 2008/01/02 12:10:20 $
014: * by $Author: andy_seaborne $
015: *
016: * (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
017: * (see footer for full conditions)
018: *****************************************************************************/package com.hp.hpl.jena.graph.compose;
019:
020: // Imports
021: ///////////////
022: import com.hp.hpl.jena.JenaRuntime;
023: import com.hp.hpl.jena.graph.*;
024: import com.hp.hpl.jena.graph.impl.SimpleEventManager;
025: import com.hp.hpl.jena.graph.query.QueryHandler;
026: import com.hp.hpl.jena.shared.JenaException;
027: import com.hp.hpl.jena.util.CollectionFactory;
028: import com.hp.hpl.jena.util.iterator.*;
029:
030: import java.util.*;
031:
032: /**
033: * <p>
034: * A graph implementation that presents the union of zero or more subgraphs,
035: * one of which is distinguished as the updateable graph.
036: * </p>
037: *
038: * @author Ian Dickinson, HP Labs
039: * (<a href="mailto:Ian.Dickinson@hp.com" >email</a>)
040: * @version CVS $Id: MultiUnion.java,v 1.28 2008/01/02 12:10:20 andy_seaborne Exp $
041: */
042: public class MultiUnion extends Polyadic {
043: /**
044: * <p>
045: * Construct a union of exactly no sub graphs.
046: * </p>
047: */
048: public MultiUnion() {
049: super ();
050: }
051:
052: /**
053: * <p>
054: * Construct a union of all of the given graphs
055: * </p>
056: *
057: * @param graphs An array of the sub-graphs of this union
058: */
059: public MultiUnion(Graph[] graphs) {
060: super (graphs);
061: }
062:
063: /**
064: * <p>
065: * Construct a union of all of the given graphs.
066: * </p>
067: *
068: * @param graphs An iterator of the sub-graphs of this union. If graphs is
069: * a closable iterator, it will be automatically closed.
070: */
071: public MultiUnion(Iterator graphs) {
072: super (graphs);
073: }
074:
075: /**
076: Answer true iff we're optimising find and query over unions with a
077: single element.
078: */
079: private boolean optimiseOne() {
080: return optimising && m_subGraphs.size() == 1;
081: }
082:
083: private boolean optimising = JenaRuntime.getSystemProperty(
084: "jena.union.optimise", "yes").equals("yes");
085:
086: // External signature methods
087: //////////////////////////////////
088:
089: /**
090: Unions share the reifiers of their base graphs. THIS WILL CHANGE.
091: */
092: public Reifier getReifier() {
093: Graph base = getBaseGraph();
094: return base == null ? super .getReifier() : base.getReifier();
095: }
096:
097: protected GraphStatisticsHandler createStatisticsHandler() {
098: return new MultiUnionStatisticsHandler(this );
099: }
100:
101: /**
102: * <p>
103: * Add the given triple to the union model; the actual component model to
104: * be updated will be the designated (or default) {@linkplain #getBaseGraph updateable} graph.
105: * </p>
106: *
107: * @param t A triple to add to the union graph
108: * @exception JenaException if the union does not contain any sub-graphs yet
109: */
110: public void performAdd(Triple t) {
111: getRequiredBaseGraph().add(t);
112: }
113:
114: /**
115: * <p>
116: * Delete the given triple from the union model; the actual component model to
117: * be updated will be the designated (or default) {@linkplain #getBaseGraph updateable} graph.
118: * </p>
119: *
120: * @param t A triple to from the union graph
121: * @exception JenaException if the union does not contain any sub-graphs yet
122: */
123: public void performDelete(Triple t) {
124: getRequiredBaseGraph().delete(t);
125: }
126:
127: /**
128: * <p>
129: * Answer true if at least one of the graphs in this union contain the given triple.
130: * </p>
131: *
132: * @param t A triple
133: * @return True if any of the graphs in the union contain t
134: */
135: public boolean graphBaseContains(Triple t) {
136: for (Iterator i = m_subGraphs.iterator(); i.hasNext();)
137: if (((Graph) i.next()).contains(t))
138: return true;
139: return false;
140: }
141:
142: public QueryHandler queryHandler() {
143: return optimiseOne() ? singleGraphQueryHandler() : super
144: .queryHandler();
145: }
146:
147: private QueryHandler singleGraphQueryHandler() {
148: return ((Graph) m_subGraphs.get(0)).queryHandler();
149: }
150:
151: /**
152: * <p>
153: * Answer an iterator over the triples in the union of the graphs in this composition. <b>Note</b>
154: * that the requirement to remove duplicates from the union means that this will be an
155: * expensive operation for large (and especially for persistent) graphs.
156: * </p>
157: *
158: * @param t The matcher to match against
159: * @return An iterator of all triples matching t in the union of the graphs.
160: */
161: public ExtendedIterator graphBaseFind(final TripleMatch t) { // optimise the case where there's only one component graph.
162: ExtendedIterator found = optimiseOne() ? singleGraphFind(t)
163: : multiGraphFind(t);
164: return SimpleEventManager.notifyingRemove(MultiUnion.this ,
165: found);
166: }
167:
168: /**
169: Answer the result of <code>find( t )</code> on the single graph in
170: this union.
171: */
172: private ExtendedIterator singleGraphFind(final TripleMatch t) {
173: return ((Graph) m_subGraphs.get(0)).find(t);
174: }
175:
176: /**
177: Answer the concatenation of all the iterators from a-subGraph.find( t ).
178: */
179: private ExtendedIterator multiGraphFind(final TripleMatch t) {
180: Set seen = CollectionFactory.createHashedSet();
181: ExtendedIterator result = NullIterator.instance;
182: for (Iterator graphs = m_subGraphs.iterator(); graphs.hasNext();) {
183: ExtendedIterator newTriples = recording(rejecting(
184: ((Graph) graphs.next()).find(t), seen), seen);
185: result = result.andThen(newTriples);
186: }
187: return result;
188: }
189:
190: /**
191: * <p>
192: * Add the given graph to this union. If it is already a member of the union, don't
193: * add it a second time.
194: * </p>
195: *
196: * @param graph A sub-graph to add to this union
197: */
198: public void addGraph(Graph graph) {
199: if (!m_subGraphs.contains(graph)) {
200: m_subGraphs.add(graph);
201: }
202: }
203:
204: public static class MultiUnionStatisticsHandler implements
205: GraphStatisticsHandler {
206: protected final MultiUnion mu;
207:
208: public MultiUnionStatisticsHandler(MultiUnion mu) {
209: this .mu = mu;
210: }
211:
212: public long getStatistic(Node S, Node P, Node O) {
213: long result = 0;
214: for (int i = 0; i < mu.m_subGraphs.size(); i += 1) {
215: Graph g = (Graph) mu.m_subGraphs.get(i);
216: GraphStatisticsHandler s = g.getStatisticsHandler();
217: long n = s.getStatistic(S, P, O);
218: if (n < 0)
219: return n;
220: result += n;
221: }
222: return result;
223: }
224:
225: public MultiUnion getUnion() {
226: return mu;
227: }
228: }
229:
230: }
231:
232: /*
233: (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
234: All rights reserved.
235:
236: Redistribution and use in source and binary forms, with or without
237: modification, are permitted provided that the following conditions
238: are met:
239:
240: 1. Redistributions of source code must retain the above copyright
241: notice, this list of conditions and the following disclaimer.
242:
243: 2. Redistributions in binary form must reproduce the above copyright
244: notice, this list of conditions and the following disclaimer in the
245: documentation and/or other materials provided with the distribution.
246:
247: 3. The name of the author may not be used to endorse or promote products
248: derived from this software without specific prior written permission.
249:
250: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
251: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
252: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
253: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
254: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
255: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
256: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
257: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
258: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
259: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260: */
|