KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > hp > hpl > jena > ontology > OntDocumentManager


1 /*****************************************************************************
2  * Source code information
3  * -----------------------
4  * Original author Ian Dickinson, HP Labs Bristol
5  * Author email Ian.Dickinson@hp.com
6  * Package Jena 2
7  * Web http://sourceforge.net/projects/jena/
8  * Created 10 Feb 2003
9  * Filename $RCSfile: OntDocumentManager.java,v $
10  * Revision $Revision: 1.45 $
11  * Release status $State: Exp $
12  *
13  * Last modified on $Date: 2005/03/04 12:49:37 $
14  * by $Author: ian_dickinson $
15  *
16  * (c) Copyright 2002, 2003, 2004, 2005 Hewlett-Packard Development Company, LP
17  * (see footer for full conditions)
18  * ****************************************************************************/

19
20 // Package
21
///////////////
22
package com.hp.hpl.jena.ontology;
23
24
25 // Imports
26
///////////////
27
import java.io.*;
28 import java.util.*;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.xerces.util.XMLChar;
33
34 import com.hp.hpl.jena.rdf.model.*;
35 import com.hp.hpl.jena.util.FileUtils;
36 import com.hp.hpl.jena.vocabulary.RDF;
37 import com.hp.hpl.jena.shared.*;
38 import com.hp.hpl.jena.shared.impl.PrefixMappingImpl;
39
40
41 /**
42  * <p>
43  * Provides services for managing ontology documents, including loading imported
44  * documents, and locally caching documents from resolvable URL's to improve
45  * load performance.
46  * </p>
47  *
48  * @author Ian Dickinson, HP Labs
49  * (<a HREF="mailto:Ian.Dickinson@hp.com" >email</a>)
50  * @version CVS $Id: OntDocumentManager.java,v 1.45 2005/03/04 12:49:37 ian_dickinson Exp $
51  */

52 public class OntDocumentManager
53 {
54     /** The default path for searching for the metadata on locally cached ontologies */
55     public static final String JavaDoc DEFAULT_METADATA_PATH = "file:ont-policy.rdf;file:etc/ont-policy.rdf";
56
57     /** Delimiter between path entries */
58     public static final String JavaDoc PATH_DELIMITER = ";";
59
60     /** Namespace for ontology metadata resources and properties */
61     public static final String JavaDoc NS = "http://jena.hpl.hp.com/schemas/2003/03/ont-manager#";
62
63     /** The anchor char is added to the end of namespace prefix expansions */
64     public static final String JavaDoc ANCHOR = "#";
65
66
67     // Static variables
68
//////////////////////////////////
69

70     /** Holds vocabulary terms */
71     private static final Model vocab = ModelFactory.createDefaultModel();
72
73     /** rdf:type for ontology specification nodes in meta-data file */
74     public static final Resource ONTOLOGY_SPEC = vocab.createResource( NS + "OntologySpec" );
75
76     /** Represents the public URI of an ontology; also used to derive the namespace */
77     public static final Property PUBLIC_URI = vocab.createProperty( NS + "publicURI" );
78
79     /** Represents the alternative local copy of the public ontology; assumed to be resolvable, hence URL not URI */
80     public static final Property ALT_URL = vocab.createProperty( NS + "altURL" );
81
82     /** Represents the standard prefix for this namespace */
83     public static final Property PREFIX = vocab.createProperty( NS + "prefix" );
84
85     /** Represents the ontology language used to encode the ontology */
86     public static final Property LANGUAGE = vocab.createProperty( NS + "language" );
87
88     /** rdf:type for document manager policy nodes */
89     public static final Resource DOC_MGR_POLICY = vocab.createResource( NS + "DocumentManagerPolicy" );
90
91     /** Defines boolean policy choice of caching loaded models */
92     public static final Property CACHE_MODELS = vocab.createProperty( NS, "cacheModels" );
93
94     /** Defines boolean policy choice of loading the imports closure */
95     public static final Property PROCESS_IMPORTS = vocab.createProperty( NS, "processImports" );
96
97     /** Specifies the URI of an ontology that we do not want to import, even if processImports is true. */
98     public static final Property IGNORE_IMPORT = vocab.createProperty( NS, "ignoreImport" );
99
100     /** The policy property for including the pre-declared namespace prefixes in a model. */
101     public static final Property USE_DECLARED_NS_PREFIXES = vocab.createProperty( NS, "useDeclaredNsPrefixes" );
102
103     /** Default document manager instance */
104     private static OntDocumentManager s_instance = null;
105
106
107     // Instance variables
108
//////////////////////////////////
109

110     /** The search path for metadata */
111     protected String JavaDoc m_searchPath = DEFAULT_METADATA_PATH;
112
113     /** Mapping from public URI to local cache (typically file) URL's for efficiently loading models */
114     protected Map m_altMap = new HashMap();
115
116     /** Mapping of public URI's to loaded models */
117     protected Map m_modelMap = new HashMap();
118
119     /** Mapping of public public URI's to language resources */
120     protected Map m_languageMap = new HashMap();
121
122     /** Log for this class */
123     private Log m_log = LogFactory.getLog( getClass() );
124
125     /** Flag: cache models as they are loaded */
126     protected boolean m_cacheModels = true;
127
128     /** Flag: process the imports closure */
129     protected boolean m_processImports = true;
130
131     /** List of URI's that will be ignored when doing imports processing */
132     protected Set m_ignoreImports = new HashSet();
133
134     /** Default prefix mapping to use to seed all models */
135     protected PrefixMapping m_prefixMap = new PrefixMappingImpl();
136
137     /** Flag to control whether we include the standard prefixes in generated models - default true. */
138     protected boolean m_useDeclaredPrefixes = true;
139
140     /** The URL of the policy file that was loaded, or null if no external policy file has yet been loaded */
141     protected String JavaDoc m_policyURL = null;
142
143
144     // Constructors
145
//////////////////////////////////
146

147     /**
148      * <p>
149      * Initialise a document manager by searching the default path for ontology
150      * metadata about known ontologies cached locally.
151      * </p>
152      */

153     public OntDocumentManager() {
154         this( DEFAULT_METADATA_PATH );
155     }
156
157
158     /**
159      * <p>
160      * Initialise a document manager by searching the given path for ontology
161      * metadata about known ontologies cached locally.
162      * </p>
163      *
164      * @param path The search path to search for initial metadata, which will
165      * also replace the current search path for this document manager. Use
166      * null to prevent loading of any initial ontology metadata. The path is a series
167      * of URL's, separated by the {@link #PATH_DELIMITER}, which defaults to
168      * semi-colon (;).
169      */

170     public OntDocumentManager( String JavaDoc path ) {
171         m_searchPath = (path == null) ? "" : path;
172         initialiseMetadata( m_searchPath, false );
173     }
174
175
176     /**
177      * <p>Initialise a document manager with the given configuration model. This model
178      * is used in place of any model that might be
179      * found by searching the meta-data search path.</p>
180      * @param config An RDF model containing configuration information for this document manager.
181      */

182     public OntDocumentManager( Model config ) {
183         // we don't need to reset first since this is a new doc mgr
184
configure( config, false );
185     }
186
187
188     // External signature methods
189
//////////////////////////////////
190

191     /**
192      * <p>
193      * OntDocumentManager is not a singleton, but a global default instance is available
194      * for applications where a single shared document manager is sufficient.
195      * </p>
196      *
197      * @return The default, global instance of a document manager
198      */

199     public static OntDocumentManager getInstance() {
200         if (s_instance == null) {
201             s_instance = new OntDocumentManager();
202         }
203         return s_instance;
204     }
205
206
207     /**
208      * <p>
209      * Answer the path used to search for the ontology metadata to load. The format is
210      * a ';' separated list of URI's. The first URI on the path that is readable is
211      * taken to be the location of the local ontology metadata.
212      * </p>
213      *
214      * @return The ontology metadata search path, as a string.
215      */

216     public String JavaDoc getMetadataSearchPath() {
217         return m_searchPath;
218     }
219
220
221     /**
222      * <p>
223      * Change the search path for loading ontology metadata to the given path. If
224      * <code>replace</code> is true, any existing mappings are removed before the
225      * new path is searched. Otherwise, existing data will only be replaced if
226      * it is clobbered by keys loaded from the metadata loaded from the new path.
227      * </p>
228      *
229      * @param path The new metadata search path (see {@link #getMetadataSearchPath} for format)
230      * @param replace If true, clear existing mappings first
231      */

232     public void setMetadataSearchPath( String JavaDoc path, boolean replace ) {
233         m_searchPath = path;
234         m_policyURL = null;
235         initialiseMetadata( path, replace );
236     }
237
238
239     /**
240      * <p>Configure this document manager using the given configuration information, after
241      * first resetting the model back to all default values.</p>
242      * @param config Document manager configuration as an RDF model
243      * @see #configure( Model, boolean )
244      */

245     public void configure( Model config ) {
246         configure( config, true );
247     }
248
249
250     /**
251      * <p>Configure this document manager according to the configuration options
252      * supplied by the given configuration model. If <code>reset</code> is true, the
253      * document manager is first reset back to all default values.</p>
254      * @param config Document manager configuration as an RDF model
255      * @param reset If true, reset the document manager to default values, before
256      * attempting to configure the document manager using the given model.
257      * @see #reset
258      */

259     public void configure( Model config, boolean reset ) {
260         if (reset) {
261             reset();
262         }
263
264         loadMetadata( config );
265     }
266
267
268     /**
269      * <p>Reset all state in this document manager back to the default
270      * values it would have had when the object was created. Optionally
271      * reload the profile metadata from the search path.</p>
272      * @param reload If true, reload the configuration file from the
273      * search path.
274      */

275     public void reset( boolean reload ) {
276         m_altMap.clear();
277         m_modelMap.clear();
278         m_languageMap.clear();
279         m_cacheModels = true;
280         m_processImports = true;
281         m_ignoreImports.clear();
282         m_prefixMap = new PrefixMappingImpl();
283         m_useDeclaredPrefixes = true;
284
285         if (reload) {
286             // reload the default values
287
setMetadataSearchPath( DEFAULT_METADATA_PATH, true );
288         }
289         else {
290             m_searchPath = DEFAULT_METADATA_PATH;
291         }
292     }
293
294     /**
295      * <p>Reset all state in this document manager back to the default
296      * values it would have had when the object was created. This does
297      * <strong>not</strong> reload the configuration information from
298      * the search path. Note also that the metadata search path is one
299      * of the values that is reset back to its default value.</p>
300      */

301     public void reset() {
302         reset( false );
303     }
304
305
306     /**
307      * <p>
308      * Answer an iterator over the ontology documents this document mananger is managing.
309      * </p>
310      *
311      * @return An Iterator ranging over the public URI strings for the known
312      * (i&#046;e&#046; cached) document models
313      */

314     public Iterator listDocuments() {
315         return m_altMap.keySet().iterator();
316     }
317
318
319     /**
320      * <p>
321      * Answer the URL of the alternative copy of the ontology document with the given URI, if known,
322      * or the URI unchanged if no alternative is known.
323      * </p>
324      *
325      * @param uri The ontology document to lookup
326      * @return The resolvable location of the alternative copy, if known, or <code>uri</code> otherwise
327      */

328     public String JavaDoc doAltURLMapping( String JavaDoc uri ) {
329         String JavaDoc alt = (String JavaDoc) m_altMap.get( uri );
330         return (alt == null) ? uri : alt;
331     }
332
333
334     /**
335      * <p>
336      * Answer the representation of the ontology document with the given URI, if known.
337      * </p>
338      *
339      * @param uri The ontology document to lookup
340      * @return The URI of the representation language, or null.
341      */

342     public String JavaDoc getLanguage( String JavaDoc uri ) {
343         return (String JavaDoc) m_languageMap.get( uri );
344     }
345
346
347     /**
348      * <p>
349      * Answer the prefix for the qnames in the given document, if known.
350      * </p>
351      *
352      * @param uri The ontology document to lookup
353      * @return The string to use as a prefix when serialising qnames in the
354      * given document's namespace, or null if not known
355      */

356     public String JavaDoc getPrefixForURI( String JavaDoc uri ) {
357         return m_prefixMap.getNsURIPrefix( uri );
358     }
359
360
361     /**
362      * <p>
363      * Answer the base URI for qnames with the given prefix, if known.
364      * </p>
365      *
366      * @param prefix A prefix string
367      * @return The basename that the prefix expands to, or null
368      */

369     public String JavaDoc getURIForPrefix( String JavaDoc prefix ) {
370         return m_prefixMap.getNsPrefixURI( prefix );
371     }
372
373
374     /**
375      * <p>
376      * Answer the cached model corresponding to the given document, if known.
377      * </p>
378      *
379      * @param uri The ontology document to lookup
380      * @return The model for the document, or null if the model is not known.
381      * @see #getOntology
382      */

383     public Model getModel( String JavaDoc uri ) {
384         return (Model) m_modelMap.get( uri );
385     }
386
387
388     /**
389      * <p>Answer true if, according to the policy expressed by this document manager, newly
390      * generated ontology models should include the pre-declared namespace prefixes.
391      * </p>
392      *
393      * @return True if pre-declared prefixes should be added to the models
394      */

395     public boolean useDeclaredPrefixes() {
396         return m_useDeclaredPrefixes;
397     }
398
399     /**
400      * <p>Set the flag that determines whether pre-declared namespace prefixes will be added to newly
401      * generated ontology models.</p>
402      *
403      * @param useDeclaredPrefixes If true, new models will include the pre-declared prefixes set held
404      * by this document manager.
405      */

406     public void setUseDeclaredPrefixes( boolean useDeclaredPrefixes ) {
407         m_useDeclaredPrefixes = useDeclaredPrefixes;
408     }
409
410     /**
411      * <p>Answer the namespace prefix map that contains the shared prefixes managed by this
412      * document manager.</p>
413      *
414      * @return The namespace prefix mapping
415      */

416     public PrefixMapping getDeclaredPrefixMapping() {
417         return m_prefixMap;
418     }
419
420
421     /**
422      * <p>
423      * Add a prefix mapping between the given public base URI and the
424      * given prefix.
425      * </p>
426      *
427      * @param uri The base URI that <code>prefix</code> expands to
428      * @param prefix A qname prefix
429      */

430     public void addPrefixMapping( String JavaDoc uri, String JavaDoc prefix ) {
431         m_prefixMap.setNsPrefix( prefix, uri );
432     }
433
434
435     /**
436      * <p>
437      * Add an entry for an alternative copy of the document with the given document
438      * URI.
439      * </p>
440      *
441      * @param docURI The public URI of the ontology document
442      * @param locationURL A locally resolvable URL where an alternative copy of the
443      * ontology document can be found
444      */

445     public void addAltEntry( String JavaDoc docURI, String JavaDoc locationURL ) {
446         m_altMap.put( docURI, locationURL );
447     }
448
449
450     /**
451      * <p>
452      * Add an entry that <code>model</code> is the appropriate model to use
453      * for the given ontology document. Will not replace any existing
454      * model that is cached for this URI (see
455      * {@link #addModel(String, Model, boolean)} for an alternative
456      * that can replace existing models).
457      * </p>
458      *
459      * @param docURI The public URI of the ontology document
460      * @param model A model containing the triples from the document
461      */

462     public void addModel( String JavaDoc docURI, Model model ) {
463         addModel( docURI, model, false );
464     }
465
466
467     /**
468      * <p>
469      * Add an entry that <code>model</code> is the appropriate model to use
470      * for the given ontology document
471      * </p>
472      *
473      * @param docURI The public URI of the ontology document
474      * @param model A model containing the triples from the document
475      * @param replace If true, replace any existing entry with this one.
476      */

477     public void addModel( String JavaDoc docURI, Model model, boolean replace ) {
478         if (m_cacheModels &&
479             (!m_modelMap.containsKey( docURI ) || replace))
480         {
481             m_modelMap.put( docURI, model );
482         }
483     }
484
485
486     /**
487      * <p>
488      * Add an entry that <code>language</code> is the URI defining the
489      * representation language for the given document
490      * </p>
491      *
492      * @param docURI The public URI of the ontology document
493      * @param language A string defining the URI of the language
494      */

495     public void addLanguageEntry( String JavaDoc docURI, String JavaDoc language ) {
496         m_languageMap.put( docURI, language );
497     }
498
499
500     /**
501      * <p>
502      * Remove all managed entries for the given document. Note does not side-effect
503      * the prefixes table: this will have to be done separately.
504      * </p>
505      *
506      * @param docURI The public URI for an ontology document
507      */

508     public void forget( String JavaDoc docURI ) {
509         m_altMap.remove( docURI );
510         m_modelMap.remove( docURI );
511         m_languageMap.remove( docURI );
512     }
513
514
515     /**
516      * <p>
517      * Answer the ontology model that results from loading the document with the
518      * given URI. This may be a cached model, if this document manager's policy
519      * is to cache loaded models. If not, or if no model is cached, the document
520      * will be read into a suitable model. The model will contain the imports closure
521      * of the ontology, if that is the current policy of this document manager.
522      * </p>
523      *
524      * @param uri Identifies the model to load.
525      * @param spec Specifies the structure of the ontology model to create
526      * @return An ontology model containing the statements from the ontology document.
527      * @see #getModel
528      */

529     public OntModel getOntology( String JavaDoc uri, OntModelSpec spec ) {
530         // ensure consistency of document managers (to allow access to cached documents)
531
OntModelSpec _spec = spec;
532         if (_spec.getDocumentManager() != this) {
533             _spec = new OntModelSpec( spec );
534             _spec.setDocumentManager( this );
535         }
536
537         // cached already?
538
if (m_modelMap.containsKey( uri )) {
539             Model cached = (Model) m_modelMap.get( uri );
540             if (cached instanceof OntModel) {
541                 return (OntModel) cached;
542             }
543             else {
544                 return ModelFactory.createOntologyModel( _spec, cached );
545             }
546         }
547
548         OntModel m = ModelFactory.createOntologyModel( _spec, null );
549         read( m, uri, true );
550
551         return m;
552     }
553
554
555     /**
556      * <p>
557      * Answer the policy flag indicating whether the imports statements of
558      * loaded ontologies will be processed to build a union of s.
559      * </p>
560      *
561      * @return True if imported models will be included in a loaded model
562      */

563     public boolean getProcessImports() {
564         return m_processImports;
565     }
566
567
568     /**
569      * <p>
570      * Answer true if the models loaded by this document manager from a given
571      * URI will be cached, so that they can be re-used in other compound
572      * ontology models.
573      * </p>
574      *
575      * @return If true, a cache is maintained of loaded models from their URI's.
576      */

577     public boolean getCacheModels() {
578         return m_cacheModels;
579     }
580
581
582     /**
583      * <p>
584      * Set the policy flag for processing imports of loaded ontologies.
585      * </p>
586      *
587      * @param processImports If true, load imported ontologies during load
588      * @see #getProcessImports
589      */

590     public void setProcessImports( boolean processImports ) {
591         m_processImports = processImports;
592     }
593
594
595     /**
596      * <p>
597      * Set the policy flag that indicates whether loaded models are cached by URI
598      * </p>
599      *
600      * @param cacheModels If true, models will be cached by URI
601      * @see #getCacheModels()
602      */

603     public void setCacheModels( boolean cacheModels ) {
604         m_cacheModels = cacheModels;
605     }
606
607     /**
608      * <p>Add the given URI to the set of URI's we ignore in imports statements</p>
609      * @param uri A URI to ignore when importing
610      */

611     public void addIgnoreImport( String JavaDoc uri ) {
612         m_ignoreImports.add( uri );
613     }
614
615     /**
616      * <p>Remove the given URI from the set of URI's we ignore in imports statements</p>
617      * @param uri A URI to ignore no longer when importing
618      */

619     public void removeIgnoreImport( String JavaDoc uri ) {
620         m_ignoreImports.remove( uri );
621     }
622
623     /**
624      * <p>Answer an iterator over the set of URI's we're ignoring</p>
625      * @return An iterator over ignored imports
626      */

627     public Iterator listIgnoredImports() {
628         return m_ignoreImports.iterator();
629     }
630
631     /**
632      * <p>Answer true if the given URI is one that will be ignored during imports </p>
633      * @param uri A URI to test
634      * @return True if uri will be ignored as an import
635      */

636     public boolean ignoringImport( String JavaDoc uri ) {
637         return m_ignoreImports.contains( uri );
638     }
639
640     /**
641      * <p>
642      * Remove all entries from the model cache
643      * </p>
644      */

645     public void clearCache() {
646         m_modelMap.clear();
647     }
648
649
650     /**
651      * <p>
652      * Inspect the statements in the graph expressed by the given model, and load
653      * into the model any imported documents. Imports statements are recognised according
654      * to the model's language profile. An occurs check allows cycles of importing
655      * safely. This method will do nothing if the {@linkplain #getProcessImports policy}
656      * for this manager is not to process imports. If the {@linkplain #getCacheModels cache policy}
657      * for this doc manager allows, models will be cached by URI and re-used where possible.
658      * </p>
659      *
660      * @param model An ontology model whose imports are to be loaded.
661      */

662     public void loadImports( OntModel model ) {
663         if (m_processImports) {
664             List readQueue = new ArrayList();
665
666             // add the imported statements from the given model to the processing queue
667
queueImports( model, readQueue, model.getProfile() );
668             loadImports( model, readQueue );
669         }
670     }
671
672
673     /**
674      * <p>Add the given model from the given URI as an import to the given model. Any models imported by the given
675      * URI will also be imported.</p>
676      *
677      * @param model A model to import into
678      * @param uri The URI of a document to import
679      */

680     public void loadImport( OntModel model, String JavaDoc uri ) {
681         if (m_processImports) {
682             List readQueue = new ArrayList();
683             readQueue.add( uri );
684             loadImports( model, readQueue );
685         }
686     }
687
688
689     /**
690      * <p>Remove from the given model the import denoted by the given URI.</p>
691      *
692      * @param model A model
693      * @param uri The URI of a document to no longer import
694      */

695     public void unloadImport( OntModel model, String JavaDoc uri ) {
696         if (m_processImports) {
697             List unloadQueue = new ArrayList();
698             unloadQueue.add( uri );
699             unloadImports( model, unloadQueue );
700         }
701     }
702
703
704     /**
705      * <p>Answer the URL of the most recently loaded policy URL, or null
706      * if no document manager policy has yet been loaded since the metadata
707      * search path was last set.</p>
708      * @return The most recently loaded policy URL or null.
709      */

710     public String JavaDoc getLoadedPolicyURL() {
711         return m_policyURL;
712     }
713
714
715     // Internal implementation methods
716
//////////////////////////////////
717

718     /**
719      * <p>Load all of the imports in the queue</p>
720      * @param model The model to load the imports into
721      * @param readQueue The queue of imports to load
722      */

723     protected void loadImports( OntModel model, List readQueue ) {
724         while (!readQueue.isEmpty()) {
725             // we process the import statements as a FIFO queue
726
String JavaDoc importURI = (String JavaDoc) readQueue.remove( 0 );
727
728             if (!model.hasLoadedImport( importURI ) && !ignoringImport( importURI )) {
729                 // this file has not been processed yet
730
loadImport( model, importURI, readQueue );
731             }
732         }
733     }
734
735
736     /**
737      * <p>Unload all of the imports in the queue</p>
738      * @param model The model to unload the imports from
739      * @param unloadQueue The queue of imports to unload
740      */

741     protected void unloadImports( OntModel model, List unloadQueue ) {
742         while (!unloadQueue.isEmpty()) {
743             // we process the import statements as a FIFO queue
744
String JavaDoc importURI = (String JavaDoc) unloadQueue.remove( 0 );
745
746             if (model.hasLoadedImport( importURI )) {
747                 // this import has not been unloaded yet
748

749                 // look up the cached model - if we can't find it, we can't unload the import
750
Model importModel = getModel( importURI );
751                 if (importModel != null) {
752                     List imports = new ArrayList();
753
754                     // collect a list of the imports from the model that is scheduled for removal
755
for (StmtIterator i = importModel.listStatements( null, model.getProfile().IMPORTS(), (RDFNode) null ); i.hasNext(); ) {
756                         imports.add( i.nextStatement().getResource().getURI() );
757                     }
758
759                     // now remove the sub-model
760
model.removeSubModel( importModel, false );
761                     model.removeLoadedImport( importURI );
762
763                     // check the list of imports of the model we have removed - if they are not
764
// imported by other imports that remain, we should remove them as well
765
for (StmtIterator i = model.listStatements( null, model.getProfile().IMPORTS(), (RDFNode) null ); i.hasNext(); ) {
766                         imports.remove( i.nextStatement().getResource().getURI() );
767                     }
768
769                     // any imports that remain are scheduled for removal
770
unloadQueue.addAll( imports );
771                 }
772             }
773         }
774
775         model.rebind();
776     }
777
778
779     /**
780      * <p>Add the ontologies imported by the given model to the end of the queue.</p>
781      */

782     protected void queueImports( Model model, List readQueue, Profile profile ) {
783         if (model instanceof OntModel) {
784             // add the imported ontologies to the queue
785
readQueue.addAll( ((OntModel) model).listImportedOntologyURIs() );
786         }
787         else {
788             // we have to do the query manually
789
StmtIterator i = model.listStatements( null, profile.IMPORTS(), (RDFNode) null );
790
791             while (i.hasNext()) {
792                 // read the next import statement
793
Resource imp = i.nextStatement().getResource();
794
795                 // add to the queue
796
readQueue.add( imp.getURI() );
797             }
798
799             i.close();
800         }
801     }
802
803
804     /**
805      * <p>
806      * Initialise the mappings for uri's and prefixes by loading metadata
807      * from an RDF model.
808      * </p>
809      *
810      * @param path The URI path to search for a loadable model
811      * @param replace If true, clear existing mappings first
812      */

813     protected void initialiseMetadata( String JavaDoc path, boolean replace ) {
814         // first clear out any old mappings if necessary
815
if (replace) {
816             m_altMap.clear();
817             m_modelMap.clear();
818             m_prefixMap = new PrefixMappingImpl();
819         }
820
821         // copy the standard prefixes
822
m_prefixMap.setNsPrefixes( PrefixMapping.Standard );
823
824         // search the path for metadata about locally cached models
825
Model metadata = findMetadata( path );
826
827         if (metadata != null) {
828             loadMetadata( metadata );
829         }
830     }
831
832
833     /**
834      * <p>
835      * Search the given path for a resolvable URI, from which we load a model
836      * (assuming RDF/XML).
837      * </p>
838      *
839      * @param path The path to search
840      * @return A model loaded by resolving an entry on the path, or null if
841      * no path entries succeed.
842      */

843     protected Model findMetadata( String JavaDoc path ) {
844         StringTokenizer pathElems = new StringTokenizer( path, PATH_DELIMITER );
845         Model m = ModelFactory.createDefaultModel();
846         boolean loaded = false;
847
848         // try to read each path entry in turn
849
while (!loaded && pathElems.hasMoreTokens()) {
850             String JavaDoc mdURI = pathElems.nextToken();
851             loaded = read( m, mdURI, false );
852             if (loaded) {
853                 m_policyURL = mdURI;
854             }
855         }
856
857         // only return m if we found some metadata
858
return loaded ? m : null;
859     }
860
861
862     /**
863      * <p>
864      * Load the ontology specification metadata from the model into the local
865      * mapping tables.
866      * </p>
867      *
868      * @param metadata A model containing metadata about ontologies.
869      */

870     protected void loadMetadata( Model metadata ) {
871         // first we process the general policy statements for this document manager
872
for (ResIterator i = metadata.listSubjectsWithProperty( RDF.type, DOC_MGR_POLICY ); i.hasNext(); ) {
873             Resource policy = i.nextResource();
874
875             // iterate over each policy statement
876
for (StmtIterator j = policy.listProperties(); j.hasNext(); ) {
877                 Statement s = j.nextStatement();
878                 Property pred = s.getPredicate();
879
880                 if (pred.equals( CACHE_MODELS )) {
881                     setCacheModels( s.getBoolean() );
882                 }
883                 else if (pred.equals( PROCESS_IMPORTS )) {
884                     setProcessImports( s.getBoolean() );
885                 }
886                 else if (pred.equals( IGNORE_IMPORT )) {
887                     addIgnoreImport( s.getResource().getURI() );
888                 }
889                 else if (pred.equals( USE_DECLARED_NS_PREFIXES )) {
890                     setUseDeclaredPrefixes( s.getBoolean() );
891                 }
892             }
893         }
894
895         // then we look up individual meta-data for particular ontologies
896
for (ResIterator i = metadata.listSubjectsWithProperty( RDF.type, ONTOLOGY_SPEC ); i.hasNext(); ) {
897             Resource root = i.nextResource();
898
899             Statement s = root.getProperty( PUBLIC_URI );
900             if (s != null) {
901                 // this will be the key in the mappings
902
String JavaDoc publicURI = s.getResource().getURI();
903
904                 // there may be a cached copy for this ontology
905
s = root.getProperty( ALT_URL );
906                 if (s != null) addAltEntry( publicURI, s.getResource().getURI() );
907
908                 // there may be a standard prefix for this ontology
909
s = root.getProperty( PREFIX );
910                 if (s != null) {
911                     // if the namespace doesn't end with a suitable split point character, add a #
912
boolean endWithNCNameCh = XMLChar.isNCName( publicURI.charAt( publicURI.length() - 1 ) );
913                     String JavaDoc prefixExpansion = endWithNCNameCh ? (publicURI + ANCHOR) : publicURI;
914
915                     addPrefixMapping( prefixExpansion, s.getString() );
916                 }
917
918                 // there may be a language specified for this ontology
919
s = root.getProperty( LANGUAGE );
920                 if (s != null) addLanguageEntry( publicURI, s.getResource().getURI() );
921             }
922             else {
923                 m_log.warn( "Ontology specification node lists no public URI - node ignored");
924             }
925         }
926     }
927
928
929     /**
930      * <p>
931      * Load the document referenced by the given URI into the model. The cache will be
932      * used if permitted by the policy, and the imports of loaded model will be added to
933      * the end of the queue.
934      * </p>
935      *
936      * @param model The composite model to load into
937      * @param importURI The URI of the document to load
938      * @param readQueue Cumulative read queue for this operation
939      */

940     protected void loadImport( OntModel model, String JavaDoc importURI, List readQueue ) {
941         if (m_processImports) {
942             LogFactory.getLog( getClass() ).debug( "OntDocumentManager loading " + importURI );
943
944             // add this model to occurs check list
945
model.addLoadedImport( importURI );
946
947             // if we have a cached version get that, otherwise load from the URI but don't do the imports closure
948
Model in = getModel( importURI );
949
950             // if not cached, we must load it from source
951
if (in == null) {
952                 // create a sub ontology model and load it from the source
953
// note that we do this to ensure we recursively load imports
954
ModelMaker maker = model.getSpecification().getImportModelMaker();
955                 boolean loaded = maker.hasModel( importURI );
956
957                 in = maker.openModel( importURI );
958
959                 // if the graph was already in existence, we don't need to read the contents (we assume)!
960
if (!loaded) {
961                     read( in, importURI, true );
962                 }
963             }
964
965             // we trap the case of importing ourself (which may happen via an indirect imports chain)
966
if (in != model) {
967                 // queue the imports from the input model on the end of the read queue
968
queueImports( in, readQueue, model.getProfile() );
969
970                 // add to the imports union graph, but don't do the rebind yet
971
model.addSubModel( in, false );
972
973                 // we also cache the model if we haven't seen it before (and caching is on)
974
addModel( importURI, in );
975             }
976         }
977     }
978
979
980     /**
981      * <p>
982      * Load into the given model from the given URI, or from a local cache URI if defined.
983      * </p>
984      *
985      * @param model A model to read statements into
986      * @param uri A URI string
987      * @param warn If true, warn on RDF exception
988      * @return True if the uri was read successfully
989      */

990     protected boolean read( Model model, String JavaDoc uri, boolean warn ) {
991         // map to the cache URI if defined
992
String JavaDoc resolvableURI = doAltURLMapping( uri );
993         String JavaDoc file = resolvableURI.startsWith( "file:" ) ? resolvableURI.substring( 5 ) : resolvableURI;
994
995         // try to load the URI
996
try {
997             // try to use the extension of the url to guess what syntax to use (.n3 => "N3", etc)
998
String JavaDoc lang = FileUtils.guessLang( resolvableURI );
999
1000            // see if we can find the file as a resource
1001
InputStream is = getClass().getClassLoader().getResourceAsStream( file );
1002
1003            if (is == null) {
1004                // we can't get this URI as a system resource, so just try to read
1005
// it in the normal way. Uses the original URI as the base (in case xml:base
1006
// is not set in the document itself)
1007
model.read( resolvableURI, uri, lang );
1008            }
1009            else {
1010                try {
1011                    // we have opened the file as a system resource - try to load it into the model
1012
model.read( is, uri, lang );
1013                }
1014                finally {
1015                    try {is.close();} catch (IOException ignore) {}
1016                }
1017            }
1018
1019            // success: cache the model against the uri
1020
addModel( uri, model );
1021            return true;
1022        }
1023        catch (JenaException e) {
1024            if (warn) {
1025                String JavaDoc u = "<" + resolvableURI + ">";
1026                if (!resolvableURI.equals( uri )) {
1027                    u = u + " (re-directed via the document mgr from <" + uri + ">)";
1028                }
1029
1030                LogFactory.getLog( OntDocumentManager.class )
1031                      .warn( "An error occurred while attempting to read from " + u +
1032                             ". Error was '" + e.getMessage() + "'.", e );
1033            }
1034            return false;
1035        }
1036    }
1037
1038
1039    //==============================================================================
1040
// Inner class definitions
1041
//==============================================================================
1042

1043
1044}
1045
1046
1047/*
1048    (c) Copyright 2002, 2003, 2004, 2005 Hewlett-Packard Development Company, LP
1049    All rights reserved.
1050
1051    Redistribution and use in source and binary forms, with or without
1052    modification, are permitted provided that the following conditions
1053    are met:
1054
1055    1. Redistributions of source code must retain the above copyright
1056       notice, this list of conditions and the following disclaimer.
1057
1058    2. Redistributions in binary form must reproduce the above copyright
1059       notice, this list of conditions and the following disclaimer in the
1060       documentation and/or other materials provided with the distribution.
1061
1062    3. The name of the author may not be used to endorse or promote products
1063       derived from this software without specific prior written permission.
1064
1065    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1066    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1067    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1068    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1069    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1070    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1071    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1072    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1073    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1074    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1075*/

1076
Popular Tags