001: /*
002: (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
003: [See end of file]
004: $Id: GraphBase.java,v 1.52 2008/02/11 09:32:33 chris-dollin Exp $
005: */
006:
007: package com.hp.hpl.jena.graph.impl;
008:
009: import com.hp.hpl.jena.graph.*;
010: import com.hp.hpl.jena.graph.query.*;
011: import com.hp.hpl.jena.util.iterator.*;
012:
013: import com.hp.hpl.jena.shared.*;
014: import com.hp.hpl.jena.shared.impl.PrefixMappingImpl;
015:
016: /**
017: GraphBase is an implementation of Graph that provides some convenient
018: base functionality for Graph implementations.
019: <p>
020: Subtypes of GraphBase must provide performAdd(Triple), performDelete(Triple),
021: graphBaseFind(TripleMatch,TripleAction), and graphBaseSize(). GraphBase
022: provides default implementations of the other methods, including the other finds
023: (on top of that one), a simple-minded prepare, and contains. GraphBase also
024: handles the event-listening and registration interfaces.
025: <p>
026: When a GraphBase is closed, future operations on it may throw an exception.
027:
028: @author kers
029: */
030:
031: public abstract class GraphBase implements GraphWithPerform {
032: /**
033: The reification style of this graph, used when the reifier is created (and
034: nowhere else, as it happens, which is good).
035: */
036: protected final ReificationStyle style;
037:
038: /**
039: Whether or not this graph has been closed - used to report ClosedExceptions
040: when an operation is attempted on a closed graph.
041: */
042: protected boolean closed = false;
043:
044: /**
045: Initialise this graph as one with reification style Minimal.
046: */
047: public GraphBase() {
048: this (ReificationStyle.Minimal);
049: }
050:
051: /**
052: Initialise this graph with the given reification style (which will be supplied to
053: the reifier when it is created).
054: */
055: public GraphBase(ReificationStyle style) {
056: this .style = style;
057: }
058:
059: /**
060: Utility method: throw a ClosedException if this graph has been closed.
061: */
062: protected void checkOpen() {
063: if (closed)
064: throw new ClosedException("already closed", this );
065: }
066:
067: /**
068: Close this graph. Subgraphs may extend to discard resources.
069: */
070: public void close() {
071: closed = true;
072: if (reifier != null)
073: reifier.close();
074: }
075:
076: public boolean isClosed() {
077: return closed;
078: }
079:
080: /**
081: Default implementation answers <code>true</code> iff this graph is the
082: same graph as the argument graph.
083: */
084: public boolean dependsOn(Graph other) {
085: return this == other;
086: }
087:
088: /**
089: Answer a QueryHandler bound to this graph. The default implementation
090: returns the same SimpleQueryHandler each time it is called; sub-classes
091: may override if they need specialised query handlers.
092: */
093: public QueryHandler queryHandler() {
094: if (queryHandler == null)
095: queryHandler = new SimpleQueryHandler(this );
096: return queryHandler;
097: }
098:
099: /**
100: The query handler for this graph, or null if queryHandler() has not been
101: called yet.
102: */
103: protected QueryHandler queryHandler;
104:
105: public GraphStatisticsHandler getStatisticsHandler() {
106: if (statisticsHandler == null)
107: statisticsHandler = createStatisticsHandler();
108: return statisticsHandler;
109: }
110:
111: protected GraphStatisticsHandler statisticsHandler;
112:
113: protected GraphStatisticsHandler createStatisticsHandler() {
114: return null;
115: }
116:
117: /**
118: Answer the event manager for this graph; allocate a new one if required.
119: Subclasses may override if they have a more specialised event handler.
120: The default is a SimpleEventManager.
121: */
122: public GraphEventManager getEventManager() {
123: if (gem == null)
124: gem = new SimpleEventManager(this );
125: return gem;
126: }
127:
128: /**
129: The event manager that this Graph uses to, well, manage events; allocated on
130: demand.
131: */
132: protected GraphEventManager gem;
133:
134: /**
135: Tell the event manager that the triple <code>t</code> has been added to the graph.
136: */
137: public void notifyAdd(Triple t) {
138: getEventManager().notifyAddTriple(this , t);
139: }
140:
141: /**
142: Tell the event manager that the triple <code>t</code> has been deleted from the
143: graph.
144: */
145: public void notifyDelete(Triple t) {
146: getEventManager().notifyDeleteTriple(this , t);
147: }
148:
149: /**
150: Answer a transaction handler bound to this graph. The default is
151: SimpleTransactionHandler, which handles <i>no</i> transactions.
152: */
153: public TransactionHandler getTransactionHandler() {
154: return new SimpleTransactionHandler();
155: }
156:
157: /**
158: Answer a BulkUpdateHandler bound to this graph. The default is a
159: SimpleBulkUpdateHandler, which does bulk update by repeated simple
160: (add/delete) updates; the same handler is returned on each call. Subclasses
161: may override if they have specialised implementations.
162: */
163: public BulkUpdateHandler getBulkUpdateHandler() {
164: if (bulkHandler == null)
165: bulkHandler = new SimpleBulkUpdateHandler(this );
166: return bulkHandler;
167: }
168:
169: /**
170: The allocated BulkUpdateHandler, or null if no handler has been allocated yet.
171: */
172: protected BulkUpdateHandler bulkHandler;
173:
174: /**
175: Answer the capabilities of this graph; the default is an AllCapabilities object
176: (the same one each time, not that it matters - Capabilities should be
177: immutable).
178: */
179: public Capabilities getCapabilities() {
180: if (capabilities == null)
181: capabilities = new AllCapabilities();
182: return capabilities;
183: }
184:
185: /**
186: The allocated Capabilities object, or null if unallocated.
187: */
188: protected Capabilities capabilities = null;
189:
190: /**
191: Answer the PrefixMapping object for this graph, the same one each time.
192: Subclasses are unlikely to want to modify this.
193: */
194: public PrefixMapping getPrefixMapping() {
195: return pm;
196: }
197:
198: protected PrefixMapping pm = new PrefixMappingImpl();
199:
200: /**
201: Add a triple, and notify the event manager. Subclasses should not need to
202: override this - we might make it final. The triple is added using performAdd,
203: and notification done by notifyAdd.
204: */
205: public void add(Triple t) {
206: checkOpen();
207: performAdd(t);
208: notifyAdd(t);
209: }
210:
211: /**
212: Add a triple to the triple store. The default implementation throws an
213: AddDeniedException; subclasses must override if they want to be able to
214: add triples.
215: */
216: public void performAdd(Triple t) {
217: throw new AddDeniedException("GraphBase::performAdd");
218: }
219:
220: /**
221: Delete a triple, and notify the event manager. Subclasses should not need to
222: override this - we might make it final. The triple is added using performDelete,
223: and notification done by notifyDelete.
224: */
225:
226: public final void delete(Triple t) {
227: checkOpen();
228: performDelete(t);
229: notifyDelete(t);
230: }
231:
232: /**
233: Remove a triple from the triple store. The default implementation throws
234: a DeleteDeniedException; subclasses must override if they want to be able
235: to remove triples.
236: */
237: public void performDelete(Triple t) {
238: throw new DeleteDeniedException("GraphBase::delete");
239: }
240:
241: /**
242: Answer an (extended) iterator over all the triples in this Graph matching
243: <code>m</code>. Subclasses cannot over-ride this, because it implements
244: the appending of reification quadlets; instead they must implement
245: graphBaseFind(TripleMatch).
246: */
247: public final ExtendedIterator find(TripleMatch m) {
248: checkOpen();
249: return reifierTriples(m).andThen(graphBaseFind(m));
250: }
251:
252: /**
253: Answer an iterator over all the triples held in this graph's non-reified triple store
254: that match <code>m</code>. Subclasses <i>must</i> override; it is the core
255: implementation for <code>find(TripleMatch)</code>.
256: */
257: protected abstract ExtendedIterator graphBaseFind(TripleMatch m);
258:
259: public ExtendedIterator forTestingOnly_graphBaseFind(TripleMatch tm) {
260: return graphBaseFind(tm);
261: }
262:
263: /**
264:
265: */
266: public final ExtendedIterator find(Node s, Node p, Node o) {
267: checkOpen();
268: return graphBaseFind(s, p, o);
269: }
270:
271: protected ExtendedIterator graphBaseFind(Node s, Node p, Node o) {
272: return find(Triple.createMatch(s, p, o));
273: }
274:
275: /**
276: Answer <code>true</code> iff <code>t</code> is in the graph as revealed by
277: <code>find(t)</code> being non-empty. <code>t</code> may contain ANY
278: wildcards. Sub-classes may over-ride reifierContains and graphBaseContains
279: for efficiency.
280: */
281: public final boolean contains(Triple t) {
282: checkOpen();
283: return reifierContains(t) || graphBaseContains(t);
284: }
285:
286: /**
287: Answer true if the reifier contains a quad matching <code>t</code>. The
288: default implementation uses the reifier's <code>findExposed</code> method.
289: Subclasses probably don't need to override (if they're interested, they
290: probably have specialised reifiers).
291: */
292: protected boolean reifierContains(Triple t) {
293: ClosableIterator it = getReifier().findExposed(t);
294: try {
295: return it.hasNext();
296: } finally {
297: it.close();
298: }
299: }
300:
301: /**
302: Answer true if the graph contains any triple matching <code>t</code>.
303: The default implementation uses <code>find</code> and checks to see
304: if the iterator is non-empty.
305: */
306: protected boolean graphBaseContains(Triple t) {
307: return containsByFind(t);
308: }
309:
310: /**
311: Answer <code>true</code> if this graph contains <code>(s, p, o)</code>;
312: this canonical implementation cannot be over-ridden.
313: */
314: public final boolean contains(Node s, Node p, Node o) {
315: checkOpen();
316: return contains(Triple.create(s, p, o));
317: }
318:
319: /**
320: Utility method: answer true iff we can find at least one instantiation of
321: the triple in this graph using find(TripleMatch).
322:
323: @param t Triple that is the pattern to match
324: @return true iff find(t) returns at least one result
325: */
326: final protected boolean containsByFind(Triple t) {
327: ClosableIterator it = find(t);
328: try {
329: return it.hasNext();
330: } finally {
331: it.close();
332: }
333: }
334:
335: /**
336: Answer an iterator over all the triples exposed in this graph's reifier that
337: match <code>m</code>. The default implementation delegates this to
338: the reifier; subclasses probably don't need to override this.
339: */
340: protected ExtendedIterator reifierTriples(TripleMatch m) {
341: return getReifier().findExposed(m);
342: }
343:
344: /**
345: Answer this graph's reifier. The reifier may be lazily constructed, and it
346: must be the same reifier on each call. The default implementation is a
347: SimpleReifier. Generally DO NOT override this method: override
348: <code>constructReifier</code> instead.
349: */
350: public Reifier getReifier() {
351: if (reifier == null)
352: reifier = constructReifier();
353: return reifier;
354: }
355:
356: /**
357: Answer a reifier appropriate to this graph. Subclasses override if
358: they need non-SimpleReifiers.
359: */
360: protected Reifier constructReifier() {
361: return new SimpleReifier(this , style);
362: }
363:
364: /**
365: The cache variable for the allocated Reifier.
366: */
367: protected Reifier reifier = null;
368:
369: /**
370: Answer the size of this graph (ie the number of exposed triples). Defined as
371: the size of the triple store plus the size of the reification store. Subclasses
372: must override graphBaseSize() to reimplement (and reifierSize if they have
373: some special reason for redefined that).
374: */
375: public final int size() {
376: checkOpen();
377: int baseSize = graphBaseSize();
378: int reifierSize = reifierSize();
379: // String className = leafName( this.getClass().getName() );
380: // System.err.println( ">> GB(" + className + ")::size = " + baseSize + "(base) + " + reifierSize + "(reifier)" );
381: return baseSize + reifierSize;
382: }
383:
384: // private String leafName( String name )
385: // {
386: // int dot = name.lastIndexOf( '.' );
387: // return name.substring( dot + 1 );
388: // }
389:
390: /**
391: Answer the number of visible reification quads. Subclasses will not normally
392: need to override this, since it just invokes the reifier's size() method, and
393: they can implement their own reifier.
394: */
395: protected int reifierSize() {
396: return getReifier().size();
397: }
398:
399: /**
400: Answer the number of triples in this graph. Default implementation counts its
401: way through the results of a findAll. Subclasses must override if they want
402: size() to be efficient.
403: */
404: protected int graphBaseSize() {
405: ExtendedIterator it = GraphUtil.findAll(this );
406: try {
407: int tripleCount = 0;
408: while (it.hasNext()) {
409: it.next();
410: tripleCount += 1;
411: }
412: return tripleCount;
413: } finally {
414: it.close();
415: }
416: }
417:
418: /**
419: Answer true iff this graph contains no triples (hidden reification quads do
420: not count). The default implementation is <code>size() == 0</code>, which is
421: fine if <code>size</code> is reasonable efficient. Subclasses may override
422: if necessary. This method may become final and defined in terms of other
423: methods.
424: */
425: public boolean isEmpty() {
426: return size() == 0;
427: }
428:
429: /**
430: Answer true iff this graph is isomorphic to <code>g</code> according to
431: the algorithm (indeed, method) in <code>GraphMatcher</code>.
432: */
433: public boolean isIsomorphicWith(Graph g) {
434: checkOpen();
435: return g != null && GraphMatcher.equals(this , g);
436: }
437:
438: /**
439: Answer a human-consumable representation of this graph. Not advised for
440: big graphs, as it generates a big string: intended for debugging purposes.
441: */
442:
443: public String toString() {
444: return toString((closed ? "closed " : ""), this );
445: }
446:
447: /**
448: Answer a human-consumable representation of <code>that</code>. The
449: string <code>prefix</code> will appear near the beginning of the string. Nodes
450: may be prefix-compressed using <code>that</code>'s prefix-mapping. This
451: default implementation will display all the triples exposed by the graph (ie
452: including reification triples if it is Standard).
453: */
454: public static String toString(String prefix, Graph that) {
455: PrefixMapping pm = that.getPrefixMapping();
456: StringBuffer b = new StringBuffer(prefix + " {");
457: String gap = "";
458: ClosableIterator it = GraphUtil.findAll(that);
459: while (it.hasNext()) {
460: b.append(gap);
461: gap = "; ";
462: b.append(((Triple) it.next()).toString(pm));
463: }
464: b.append("}");
465: return b.toString();
466: }
467:
468: }
469:
470: /*
471: (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
472: All rights reserved.
473:
474: Redistribution and use in source and binary forms, with or without
475: modification, are permitted provided that the following conditions
476: are met:
477:
478: 1. Redistributions of source code must retain the above copyright
479: notice, this list of conditions and the following disclaimer.
480:
481: 2. Redistributions in binary form must reproduce the above copyright
482: notice, this list of conditions and the following disclaimer in the
483: documentation and/or other materials provided with the distribution.
484:
485: 3. The name of the author may not be used to endorse or promote products
486: derived from this software without specific prior written permission.
487:
488: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
489: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
490: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
491: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
492: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
493: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
494: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
495: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
496: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
497: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
498: */
|