KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > hp > hpl > jena > db > GraphRDB


1 /*
2   (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
3   [See end of file]
4 */

5
6 package com.hp.hpl.jena.db;
7
8 import com.hp.hpl.jena.db.impl.*;
9 import com.hp.hpl.jena.graph.*;
10 import com.hp.hpl.jena.graph.impl.*;
11 import com.hp.hpl.jena.graph.query.QueryHandler;
12 import com.hp.hpl.jena.shared.*;
13 import com.hp.hpl.jena.util.iterator.*;
14
15 import java.util.*;
16
17 /**
18  *
19  * A persistent Graph implementation using a relational database for storage.
20  *
21  * <p>This graph stores data persistently in a relational database.
22  * It supports the full Graph interface and should operate just like
23  * a GraphMem.</p>
24  *
25  * <p>
26  * Internally, each GraphRDB keeps a list of specialized graphs.
27  * For each operation, it works through the list of graphs
28  * attempting to perform the operation on each one.</p>
29  *
30  * <p>
31  * The intention is that each type of specialized graph is
32  * optimized for a different type of triple. For example, one
33  * type of specialied graph might be optimized for storing
34  * triples in a particular ontology. The last specialized
35  * graph in the list is always a generic one that can handle any
36  * valid RDF triple.</p>
37  *
38  * <p>
39  * The order of the specialized graphs is consistent and
40  * immutable after the graph is constructed. This aids
41  * optimization. For example, if a specialized graph
42  * is asked to perform an operatin on a triple, and it knows
43  * that it would have added it if asked, then it can advise the
44  * calling GraphRDB that the operaton is complete even though
45  * it doesn't know anything about other specialized graphs later
46  * in the list.</p>
47  *
48  * @since Jena 2.0
49  *
50  * @author csayers (based in part on GraphMem by bwm).
51  * @version $Revision: 1.41 $
52  */

53 public class GraphRDB extends GraphBase implements Graph {
54
55     /** The name used for the default graph.
56      */

57     static public final String JavaDoc DEFAULT = "DEFAULT";
58
59     protected IRDBDriver m_driver = null;
60     protected DBPropGraph m_properties = null;
61     protected DBPrefixMappingImpl m_prefixMapping = null;
62     protected List m_specializedGraphs = null;
63     protected List m_specializedGraphReifiers = null;
64     protected Reifier m_reifier = null;
65
66     protected int m_reificationBehaviour = 0;
67     
68     /**
69      * Optimize all triples representing part or all of a reified statement;
70      * this is the recommended option.
71      *
72      * <p>
73      * This is the best choice in almost every case. It optimizes
74      * all reified triples regardless of how they are added to the graph,
75      * provides a simple interface, and is quite efficient.
76      * </p>
77      *
78      * <p>
79      * With this choice, if you do <code>add(A)</code> then
80      * <code>contains(A)</code> will return true for all A.
81      * </p>
82      *
83      */

84     public static final int OPTIMIZE_ALL_REIFICATIONS_AND_HIDE_NOTHING = 1;
85
86     /**
87      * Optimize and hide any triples representing part or all of a reified statement.
88      *
89      * <p>
90      * This optimizes all triples but hides them so they are visible only via the reifier interface.
91      * There is no significant performance advantage in using this option and it is not recommended.
92      * It is included only for compatability with in-memory graphs.
93      * </p>
94      *
95      * <p>
96      * Note that it will also cause unexpected behaviour, for example, if you do:
97      * <code>
98      * add(new Triple( s, RDF.predicate, o))
99      * </code>
100      * then that triple will be hidden and a subsequent call to <code>contains</code>,
101      * <code>find</code>, or <code>size</code> will not show it's presence. The only
102      * way to see that statement is to use <code>Reifier.getHiddenTriples</code>.
103      * </p>
104      *
105      */

106     public static final int OPTIMIZE_AND_HIDE_FULL_AND_PARTIAL_REIFICATIONS = 2;
107
108     /**
109      * Optimize and hide only fully reified statements added via the Reifier interface, use only for backward-compatability with Jena1.
110      *
111      * <p>
112      * This treats triples added through the Reifier interface as distinct from those
113      * added using the normal Graph.add function. Those added via the reifier interface
114      * will be optimized and hidden from view. Those added via Graph.add will not
115      * be optimized and will be visible.
116      * </p>
117      *
118      * <p>
119      * Since many of the techniques for adding triple to Graphs use Graph.add, and
120      * that is never optimized, this is not usually a good choice. It is included
121      * only for backward compability with Jena 1. There is no performance advantage
122      * in using this option.
123      * </p>
124      */

125     public static final int OPTIMIZE_AND_HIDE_ONLY_FULL_REIFICATIONS = 3;
126     
127     /**
128         Answer the integer representing the RDB reifier style given the Reifier style.
129     */

130     public static int styleRDB( ReificationStyle style )
131         {
132         if (style == ReificationStyle.Standard)
133             return GraphRDB.OPTIMIZE_ALL_REIFICATIONS_AND_HIDE_NOTHING;
134         if (style == ReificationStyle.Convenient)
135             return GraphRDB.OPTIMIZE_AND_HIDE_FULL_AND_PARTIAL_REIFICATIONS;
136         if (style == ReificationStyle.Minimal)
137             return GraphRDB.OPTIMIZE_AND_HIDE_ONLY_FULL_REIFICATIONS;
138         throw new JenaException( "unsupported reification style" );
139         }
140         
141     /**
142         Answer the reification style corresponding to the DB behaviour integer.
143     */

144     public static ReificationStyle styleRDB( int behaviour )
145         {
146         if (behaviour == OPTIMIZE_ALL_REIFICATIONS_AND_HIDE_NOTHING)
147             return ReificationStyle.Standard;
148         if (behaviour == OPTIMIZE_AND_HIDE_FULL_AND_PARTIAL_REIFICATIONS)
149             return ReificationStyle.Convenient;
150         if (behaviour == OPTIMIZE_AND_HIDE_ONLY_FULL_REIFICATIONS)
151             return ReificationStyle.Minimal;
152         throw new JenaException( "unsupported reification behaviour" );
153         }
154                 
155     /**
156      * Construct a new GraphRDB using an unusual reification style.
157      * @param con an open connection to the database
158      * @param graphID is the name of a graph or GraphRDB.DEFAULT
159      * @param requestedProperties a set of default properties.
160      * (May be null, if non-null should be a superset of the properties
161      * obtained by calling ModelRDB.getDefaultModelProperties ).
162      * @param isNew is true if the graph doesn't already exist and
163      * false otherwise. (If unsure, test for existance by using
164      * IDBConnection.containsGraph ).
165      * @deprecated Please use the alternate constructor and choose the desired
166      * reification behaviour.
167      */

168     public GraphRDB( IDBConnection con, String JavaDoc graphID, Graph requestedProperties, boolean isNew) {
169         this(con, graphID, requestedProperties, OPTIMIZE_AND_HIDE_FULL_AND_PARTIAL_REIFICATIONS, isNew);
170     }
171         
172     /**
173      * Construct a new GraphRDB
174      * @param con an open connection to the database
175      * @param graphID is the name of a graph or GraphRDB.DEFAULT
176      * @param requestedProperties a set of default properties.
177      * (May be null, if non-null should be a superset of the properties
178      * obtained by calling ModelRDB.getDefaultModelProperties ).
179      * @param reificationBehaviour specifies how this graph should handle reified triples.
180      * The options are OPTIMIZE_ALL_REIFICATIONS_AND_HIDE_NOTHING (strongly recommended), OPTIMIZE_AND_HIDE_FULL_AND_PARTIAL_REIFICATIONS (included only for full compatability with all the options for in-memory Graphs),
181      * OPTIMIZE_AND_HIDE_ONLY_FULL_REIFICATIONS (included only for compatability with older jena1-style usage).
182      *
183      * @param isNew is true if the graph doesn't already exist and
184      * false otherwise. (If unsure, test for existance by using
185      * IDBConnection.containsGraph ).
186      */

187     public GraphRDB( IDBConnection con, String JavaDoc graphID, Graph requestedProperties, int reificationBehaviour, boolean isNew) {
188        super( styleRDB( reificationBehaviour ) );
189         m_reificationBehaviour = reificationBehaviour;
190         
191         if(graphID == null)
192             graphID = DEFAULT;
193         else if ( graphID.equals(DEFAULT) )
194             throw new JenaException("The model name \"" + DEFAULT + "\" is reserved.");
195             
196         // Find the driver
197
m_driver = con.getDriver();
198         SpecializedGraph sysGraph = m_driver.getSystemSpecializedGraph(true);
199         
200         // Look for properties for this graphID
201
m_properties = DBPropGraph.findPropGraphByName( sysGraph, graphID );
202         
203         if( m_properties != null) {
204             if( isNew )
205                 throw new AlreadyExistsException( graphID );
206             if( requestedProperties != null )
207                 throw new RDFRDBException("Error: attempt to change a graph's properties after it has been used.");
208             m_specializedGraphs = m_driver.recreateSpecializedGraphs( m_properties );
209         }
210         else {
211             if( !isNew )
212                 throw new DoesNotExistException( graphID );
213             if( requestedProperties == null )
214                 throw new RDFRDBException("Error: requested properties is null");
215             
216             /*
217             m_properties = new DBPropGraph( m_driver.getSystemSpecializedGraph(true), graphID, requestedProperties);
218             DBPropDatabase dbprop = new DBPropDatabase( m_driver.getSystemSpecializedGraph(true));
219             dbprop.addGraph(m_properties);
220             */

221             m_specializedGraphs = m_driver.createSpecializedGraphs( graphID, requestedProperties );
222             m_properties = DBPropGraph.findPropGraphByName( sysGraph, graphID );
223             if ( m_properties == null )
224                 throw new RDFRDBException("Graph properties not found after creating graph.");
225         }
226         
227         // Keep a list of the specialized graphs that handle reification
228
// (we'll need this later to support getReifier)
229

230         m_specializedGraphReifiers = new ArrayList();
231         Iterator it = m_specializedGraphs.iterator();
232         while( it.hasNext() ) {
233             Object JavaDoc o = it.next();
234             if( o instanceof SpecializedGraphReifier )
235                 m_specializedGraphReifiers.add(o);
236         }
237     }
238     
239     /**
240      * Returns the Node for this model in the system properties graph.
241      *
242      * The properties of each GraphRDB (things like how it is stored in
243      * the database) are themelves stored in a system Graph. This function
244      * returns the Node which represents this GraphRDB in the system Graph.
245      *
246      * @since Jena 2.0
247      */

248     public Node getNode() {
249         if(m_properties == null)
250             throw new RDFRDBException("Error - attempt to call getNode() on a GraphRDB that has already been removed");
251         return m_properties.getNode();
252     }
253
254     /**
255      * Returns triples that describe this graph in the system properties graph.
256      *
257      * The properties of each GraphRDB (things like how it is stored in
258      * the database) are stored as triples in a system Graph. This function
259      * returns those triples.
260      *
261      * @since Jena 2.0
262      */

263     public ExtendedIterator getPropertyTriples() {
264         if(m_properties == null)
265             throw new RDFRDBException("Error - attempt to call getPropertyTriples on a GraphRDB that has been removed.");
266         return m_properties.listTriples();
267     }
268
269     protected boolean isOpen()
270         { return m_specializedGraphs != null; }
271
272     protected void checkOpen()
273         { if (isOpen() == false) throw new ClosedException( "GraphRDB", this ); }
274
275     /* (non-Javadoc)
276      * @see com.hp.hpl.jena.graph.Graph#add(com.hp.hpl.jena.graph.Triple)
277      */

278     public void performAdd(Triple t) {
279         checkOpen();
280         SpecializedGraph.CompletionFlag complete = new SpecializedGraph.CompletionFlag();
281         Iterator it = m_specializedGraphs.iterator();
282         while( it.hasNext() ) {
283             SpecializedGraph sg = (SpecializedGraph) it.next();
284             if( sg instanceof SpecializedGraphReifier && m_reificationBehaviour == OPTIMIZE_AND_HIDE_ONLY_FULL_REIFICATIONS)
285                 continue; // don't let the reifier graphs see partial reifications
286
sg.add( t, complete);
287             if( complete.isDone())
288                 return;
289         }
290         
291         throw new JenaException("Error - GraphRDB.add(Triple) failed to find a suitable store for the triple:"+t.toString());
292         
293     }
294
295     /** Add a list of triples.
296      *
297      * @param triples List to be added. This is unchanged by the call
298      */

299     public void add(List triples) {
300         checkOpen();
301         ArrayList localTriples = new ArrayList( triples );
302         SpecializedGraph.CompletionFlag complete = new SpecializedGraph.CompletionFlag();
303         Iterator it = m_specializedGraphs.iterator();
304         while( it.hasNext() ) {
305             SpecializedGraph sg = (SpecializedGraph) it.next();
306             if( sg instanceof SpecializedGraphReifier && m_reificationBehaviour == OPTIMIZE_AND_HIDE_ONLY_FULL_REIFICATIONS)
307                 continue; // don't let the reifier graphs see partial reifications
308
sg.add( localTriples, complete);
309             if( complete.isDone())
310                 return;
311         }
312         
313         throw new JenaException("Error - GraphRDB.add(List) failed to find a suitable store for at least one triple:"+triples.get(0).toString());
314         
315     }
316
317     /* (non-Javadoc)
318      * @see com.hp.hpl.jena.graph.Graph#delete(com.hp.hpl.jena.graph.Triple)
319      */

320     public void performDelete(Triple t) {
321         checkOpen();
322         SpecializedGraph.CompletionFlag complete = new SpecializedGraph.CompletionFlag();
323         Iterator it = m_specializedGraphs.iterator();
324         while( it.hasNext() ) {
325             SpecializedGraph sg = (SpecializedGraph) it.next();
326             if( sg instanceof SpecializedGraphReifier && m_reificationBehaviour == OPTIMIZE_AND_HIDE_ONLY_FULL_REIFICATIONS)
327                 continue; // don't let the reifier graphs see partial reifications
328
sg.delete( t, complete);
329             if( complete.isDone())
330                 return;
331         }
332         
333         throw new JenaException("Error - GraphRDB.delete(Triple) failed to find a suitable store for the triple:"+t.toString());
334
335     }
336
337     /** Delete a list of triples.
338      *
339      * @param triples List to be deleted. This is unchanged by the call.
340      */

341     public void delete( List triples ) {
342         checkOpen();
343         ArrayList localTriples = new ArrayList( triples );
344         SpecializedGraph.CompletionFlag complete = new SpecializedGraph.CompletionFlag();
345         Iterator it = m_specializedGraphs.iterator();
346         while( it.hasNext() ) {
347             SpecializedGraph sg = (SpecializedGraph) it.next();
348             if( sg instanceof SpecializedGraphReifier && m_reificationBehaviour == OPTIMIZE_AND_HIDE_ONLY_FULL_REIFICATIONS)
349                 continue; // don't let the reifier graphs see partial reifications
350
sg.delete( localTriples, complete);
351             if( complete.isDone())
352                 return;
353         }
354         
355         throw new JenaException("Error - GraphRDB.delete(Triple) failed to find a suitable store for at least one triple:"+triples.get(0).toString());
356
357     }
358
359     /* (non-Javadoc)
360      * @see com.hp.hpl.jena.graph.Graph#size()
361      */

362     public int graphBaseSize() {
363         checkOpen();
364         int result = 0;
365         Iterator it = m_specializedGraphs.iterator();
366         while( it.hasNext() ) {
367             SpecializedGraph sg = (SpecializedGraph) it.next();
368             if( sg instanceof SpecializedGraphReifier &&
369                 (m_reificationBehaviour == OPTIMIZE_AND_HIDE_ONLY_FULL_REIFICATIONS ||
370                 m_reificationBehaviour == OPTIMIZE_AND_HIDE_FULL_AND_PARTIAL_REIFICATIONS))
371                 continue; // don't let the reifier graphs see partial reifications
372
result += sg.tripleCount();
373         }
374         return result;
375     }
376
377     /* (non-Javadoc)
378      * @see com.hp.hpl.jena.graph.Graph#contains(com.hp.hpl.jena.graph.Triple)
379      */

380     public boolean graphBaseContains(Triple t) {
381         checkOpen();
382         SpecializedGraph.CompletionFlag complete = new SpecializedGraph.CompletionFlag();
383         Iterator it = m_specializedGraphs.iterator();
384         while( it.hasNext() ) {
385             SpecializedGraph sg = (SpecializedGraph) it.next();
386             if( sg instanceof SpecializedGraphReifier &&
387                 (m_reificationBehaviour == OPTIMIZE_AND_HIDE_ONLY_FULL_REIFICATIONS ||
388                 m_reificationBehaviour == OPTIMIZE_AND_HIDE_FULL_AND_PARTIAL_REIFICATIONS))
389                 continue; // don't let the reifier graphs see partial reifications
390
boolean result = sg.contains( t, complete);
391             if( result == true || complete.isDone() == true )
392                 return result;
393         }
394         return false;
395     }
396
397     /* (non-Javadoc)
398      * @see com.hp.hpl.jena.graph.Graph#find(com.hp.hpl.jena.graph.TripleMatch)
399      */

400     public ExtendedIterator graphBaseFind(TripleMatch m) {
401         checkOpen();
402         ExtendedIterator result = NullIterator.instance;
403         SpecializedGraph.CompletionFlag complete = new SpecializedGraph.CompletionFlag();
404         Iterator it = m_specializedGraphs.iterator();
405         while( it.hasNext() ) {
406             SpecializedGraph sg = (SpecializedGraph) it.next();
407             if( sg instanceof SpecializedGraphReifier &&
408                 (m_reificationBehaviour == OPTIMIZE_AND_HIDE_ONLY_FULL_REIFICATIONS ||
409                 m_reificationBehaviour == OPTIMIZE_AND_HIDE_FULL_AND_PARTIAL_REIFICATIONS))
410                 continue; // don't let the reifier graphs see partial reifications
411
ExtendedIterator partialResult = sg.find( m, complete);
412             result = result.andThen(partialResult);
413             if( complete.isDone())
414                 break;
415         }
416         return SimpleEventManager.notifyingRemove( this, result );
417     }
418
419     public ExtendedIterator reifierTriples( TripleMatch m )
420         { return NullIterator.instance; }
421     
422     public int reifierSize()
423         { return 0; }
424     
425     /* (non-Javadoc)
426      * @see com.hp.hpl.jena.graph.Graph#getBulkUpdateHandler()
427      */

428      public BulkUpdateHandler getBulkUpdateHandler()
429         { return new DBBulkUpdateHandler( this ); }
430
431     /*
432      * (non-Javadoc)
433      * @see com.hp.hpl.jena.graph.Graph#getReifier()
434      */

435     public Reifier getReifier() {
436         if (m_reifier == null)
437                 m_reifier = new DBReifier( this, style, m_specializedGraphReifiers, m_specializedGraphReifiers );
438         return m_reifier;
439     }
440      
441     /* (non-Javadoc)
442      * @see com.hp.hpl.jena.graph.Graph#getPrefixMapping()
443      */

444     public PrefixMapping getPrefixMapping() {
445         if( m_prefixMapping == null)
446             m_prefixMapping = new DBPrefixMappingImpl( m_properties );
447         return m_prefixMapping;
448     }
449
450
451     /* (non-Javadoc)
452      * @see com.hp.hpl.jena.graph.Graph#getTransactionHandler()
453      */

454     public TransactionHandler getTransactionHandler() {
455         return new DBTransactionHandler(m_driver, this);
456     }
457
458     /* (non-Javadoc)
459      * @see com.hp.hpl.jena.graph.Graph#close()
460      */

461     public synchronized void close() {
462         if( m_specializedGraphs != null) {
463             Iterator it = m_specializedGraphs.iterator();
464             while( it.hasNext() ) {
465                 SpecializedGraph sg = (SpecializedGraph) it.next();
466                 sg.close();
467             }
468             m_specializedGraphs = null;
469         }
470     }
471     
472     /**
473      * Remove this Graph entirely from the database.
474      *
475      * This operation is unique to GraphRDB - it removes all
476      * mention of this graph from the database - after removing
477      * a graph it is recommended to immediately call close()
478      * (there is no other useful operation that may be
479      * performed, and so no reason to keep the Graph around).
480      */

481     public synchronized void remove() {
482         checkOpen();
483         // First we ask the driver to remove the specialized graphs
484
m_driver.removeSpecializedGraphs( m_properties, m_specializedGraphs );
485         m_properties = null;
486         m_specializedGraphs = null;
487     }
488
489     /**
490      * Return the connection
491      *
492      * @return IDBConnection for the database on which this graph is stored.
493      * Returns null if the connection has not yet been estabilished.
494      */

495     public IDBConnection getConnection() {
496         if( m_driver == null )
497             return null;
498         return m_driver.getConnection();
499     }
500     
501     /**
502      * Return the reification behavior (GraphRDB) for this graph
503      *
504      * @return integer that defines the reification behavior for this graphRDB.
505      */

506     public int reificationBehavior( )
507         {
508         return m_reificationBehaviour;
509         }
510
511     
512
513     /**
514      * Return an iterator over the specialized graphs for this graph
515      *
516      * @return Iterator over the list of specialized graphs.
517      */

518     public Iterator getSpecializedGraphs() {
519         return m_specializedGraphs.iterator();
520     }
521
522     private QueryHandler q = null;
523    
524     /* (non-Javadoc)
525      * @see com.hp.hpl.jena.graph.Graph#queryHandler()
526      */

527     public QueryHandler queryHandler()
528         {
529         if (q == null) q = new DBQueryHandler( this);
530         return q;
531         }
532
533     /**
534     * Get the value of DoDuplicateCheck
535     * @return bool boolean
536     */

537     public boolean getDoDuplicateCheck() {
538         return m_driver.getDoDuplicateCheck();
539     }
540
541     /**
542     * Set the value of DoDuplicateCheck.
543     * @param bool boolean
544     */

545     public void setDoDuplicateCheck(boolean bool) {
546         m_driver.setDoDuplicateCheck(bool);
547         boolean nb = !bool;
548         if (isOpen()) {
549             Iterator it = m_specializedGraphs.iterator();
550             while (it.hasNext()) {
551                 SpecializedGraph sg = (SpecializedGraph) it.next();
552                 sg.getPSet().setSkipDuplicateCheck(nb);
553             }
554         }
555     }
556
557 }
558
559 /*
560  * (c) Copyright 2002, 2003, 2004, 2005 Hewlett-Packard Development Company, LP
561  * All rights reserved.
562  *
563  * Redistribution and use in source and binary forms, with or without
564  * modification, are permitted provided that the following conditions
565  * are met:
566  * 1. Redistributions of source code must retain the above copyright
567  * notice, this list of conditions and the following disclaimer.
568  * 2. Redistributions in binary form must reproduce the above copyright
569  * notice, this list of conditions and the following disclaimer in the
570  * documentation and/or other materials provided with the distribution.
571  * 3. The name of the author may not be used to endorse or promote products
572  * derived from this software without specific prior written permission.
573
574  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
575  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
576  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
577  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
578  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
579  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
580  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
581  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
582  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
583  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
584  */
Popular Tags