1   /*
2    * OntologyImpl.java
3    * Copyright:    Copyright (c) 2002, OntoText Lab.
4    * Company:      OntoText Lab.
5    * borislav popov 03/2002 */
6   package com.ontotext.gate.ontology;
7   
8   import gate.creole.*;
9   import gate.creole.ontology.*;
10  import gate.util.*;
11  
12  import java.util.*;
13  import java.io.*;
14  import java.net.*;
15  
16  import com.hp.hpl.jena.daml.*;
17  import com.hp.hpl.jena.daml.common.*;
18  import com.hp.hpl.mesa.rdf.jena.model.*;
19  import com.hp.hpl.mesa.rdf.jena.common.*;
20  import com.hp.hpl.jena.vocabulary.*;
21  import com.hp.hpl.mesa.rdf.jena.common.prettywriter.*;
22  import com.hp.hpl.mesa.rdf.jena.vocabulary.*;
23  import com.hp.hpl.jena.rdf.arp.*;
24  
25  /** Provides load and store of ontologies from/to DAML+OIL repository
26   *  @author borislav popov
27   */
28  public class DAMLOntology extends TaxonomyImpl {
29  
30    /** DEBUG FLAG */
31    private static final boolean DEBUG = false;
32  
33    /**loads from rdf/parse rdf. it helps if setURL is called apriori.*/
34    public void load() throws ResourceInstantiationException{
35      loadAndGetModel();
36    }
37  
38    /**
39     * Stores the ontology to <@link getURL()/> in daml
40     */
41    public void store()throws ResourceInstantiationException  {
42      DAMLModel model = storeAndGetModel();
43      writeModel(model);
44    }
45  
46    /** Introduced a protected method that retuns the model, so it can be
47     * used in a subclass to get more data before discarding it
48     */
49    protected DAMLModel loadAndGetModel() throws ResourceInstantiationException{
50  
51      DAMLModel model;
52  
53      try {
54        model = new DAMLModelImpl();
55  
56  
57        /*get the actual url instead of gate:path*/
58        URL curl = getURL();
59        if ( null == curl )
60          throw new ResourceInstantiationException(
61          "Unable to load ontology because url is not set. (null)");
62  
63        if (-1 != curl.getProtocol().indexOf("gate")) {
64          curl = gate.util.protocols.gate.Handler.class.getResource(
65                        Files.getResourcePath() + getURL().getPath()
66                      );
67        } // if gate:path url
68  
69        model.read(curl.toString());
70        DAMLVocabulary voc = DAML_OIL.getInstance();
71  
72        if (! model.getLoadSuccessful()) {
73          /** if the url does not exist : store the model first*/
74          File f = new File(curl.getFile());
75          if (!f.exists()) {
76            this.store();
77          } // if file doesn't exist
78  
79          //try again
80          model.read(curl.toString());
81  
82          if ( !model.getLoadSuccessful()) {
83            throw new ResourceInstantiationException(
84            "loading of ontology failed. url="+curl.toString());
85          }
86        }// if not sucessful load;
87  
88        if (model.getLoadSuccessful()) {
89          /* load classes */
90          /* on the first iteration the classes are created */
91          DAMLClass clas;
92          ResIterator ri = model.listSubjects();
93          Resource res;
94          while (ri.hasNext()) {
95            res = ri.next();
96            if ( (res instanceof DAMLClass) && ! (res instanceof DAMLRestriction) ) {
97              clas = (DAMLClass)res;
98              String comment = null;
99              if (null != clas.prop_comment().getValue()) {
100               comment = clas.prop_comment().getValue().getString();
101             }
102 
103             /* avoid anonyomouses and restrictions */
104             if ( null!=clas.getLocalName()) {
105               TClass oClass = this.createClass(
106                     clas.getLocalName(),
107                     comment);
108               /*currently only classes from the same ontology are expected*/
109               /*the problem was caused by the gate:/.... urls. when reading a
110               damlclass the urls are unpacked to e.g. file:///d:/.... which is a
111               change of the uri : this is the reason as uri of the class to be set:
112               ontology base uri + # + classURIafter#*/
113               String localURI = clas.getURI();
114 //              if ( -1 == localURI.indexOf('#') ) {
115               oClass.setURI(localURI);
116 //              }  else {
117 //                oClass.setURI(localURI.substring(
118 //                  localURI.indexOf('#')+1
119 //                ));
120 //              } // else
121             } // if not null name - anonymous
122           } else {
123             if (res instanceof DAMLOntologyImpl) {
124               /* only one ontology expected to be loaded */
125               DAMLOntologyImpl onto = (DAMLOntologyImpl) res;
126 
127 
128               try {
129                 Statement s = onto.getProperty(RDFS.label);
130                 this.setLabel(s.getObject().toString());
131               } catch (RDFException rdfex) {
132                 // this means that there is no label property :
133                 // so just set it to an empty string
134                 this.setLabel("");
135               }
136 
137               if ( null != onto.prop_comment().getValue()) {
138                 this.setComment(onto.prop_comment().getValue().toString());
139               }
140 
141               if (null != onto.prop_versionInfo()) {
142                 LiteralAccessor la = onto.prop_versionInfo();
143                 NodeIterator niValues = la.getValues();
144                 if (niValues.hasNext()) {
145                   this.setVersion(niValues.next().toString());
146                 }
147               } // if version
148 
149 
150               {/*set the pre # part as uri and the post # part as id*/
151                 String luri = onto.getURI();
152                 if (null == luri) {
153                   this.setSourceURI("");
154                 } else {
155                   int ix = luri.indexOf('#');
156                   if (-1 != ix) {
157                     this.setSourceURI(luri.substring(0,ix));
158                     this.setId(luri.substring(ix+1));
159                   } else {
160                     this.setSourceURI(onto.getURI());
161                   } // else
162                 } // else
163               } // block
164             }  // if ontology
165           } // else
166 
167         }// while nodes
168 
169 
170         /*append the base uri where needed to the class uris*/
171         Iterator cli = this.getClasses().iterator();
172         while(cli.hasNext()) {
173           TClass ocl = (TClass)cli.next();
174           if ( -1 == ocl.getURI().indexOf('#')) {
175             ocl.setURI(this.getSourceURI()+'#'+ocl.getURI());
176           }
177         } // while
178 
179         /* infer subclassof superclassof relations */
180         ri = model.listSubjects();
181         while (ri.hasNext()) {
182           res = ri.next();
183           if ( (res instanceof DAMLClass) && ! (res instanceof DAMLRestriction) ) {
184 
185             clas = (DAMLClass) res;
186             if ( null == clas.getLocalName()) {
187               continue;
188             }
189             TClass oc = this.getClassByName(clas.getLocalName());
190             if ( null == oc ) {
191               throw new InvalidFormatException(
192               curl,"class not found by name = "+clas.getLocalName());
193             }
194 
195             com.hp.hpl.mesa.rdf.jena.model.Property propSCO = RDFS.subClassOf;
196             StmtIterator subi = clas.listProperties(propSCO);
197             while(subi.hasNext()) {
198               Statement damlSub = (Statement)subi.next();
199               String obj = damlSub.getObject().toString();
200               /*euristic to remove < > from the obj string */
201               if (obj.charAt(0) == '<' && obj.charAt(obj.length()-1) == '>') {
202                 obj=obj.substring(1,obj.length()-1);
203               }
204               obj = obj.substring(obj.lastIndexOf("#")+1);
205               TClass sub = this.getClassByName(obj);
206 
207               if ( null != sub )
208                 oc.addSuperClass(sub);
209 
210             } //while sub classes
211           } //
212         } // while nodes
213 
214       } // if model.getloadsucessful
215 
216       /**debug*/
217       if (DEBUG) {
218         Iterator ic = this.getClasses().iterator();
219         while (ic.hasNext()) {
220           TClass cl = (TClass)ic.next();
221           System.out.println(""+cl+" [direct sub classes = "+
222           cl.getSubClasses(TClass.DIRECT_CLOSURE).size()+"] "+
223           "[transitive sub classes = "+
224           cl.getSubClasses(TClass.TRANSITIVE_CLOSURE).size()+"]");
225         }
226       } // debug end
227 
228 
229     } catch (Exception e) {
230       throw new ResourceInstantiationException(e);
231     }
232 
233     this.setModified(false);
234 
235     return model;
236   } // load()
237 
238 
239   protected void writeModel(DAMLModel model) throws ResourceInstantiationException {
240     try {
241       /* store the model */
242       Writer writer = new FileWriter(this.getURL().getFile());
243       RDFWriter rdfWriter = model.getWriter("RDF/XML-ABBREV");
244       rdfWriter.write(model, writer, this.getSourceURI());
245     } catch (Exception e) {
246       throw new ResourceInstantiationException(e);
247     }
248   }
249 
250   protected DAMLModel storeAndGetModel()throws ResourceInstantiationException  {
251       DAMLModel model = new DAMLModelImpl();
252 
253       try {
254       /*ensure that all classes will be newly inferred
255       later make this through more carefull
256       handling of ontology.modified flag*/
257       this.setModified(true);
258 
259       /* create ontology & get vocabulary */
260       DAMLVocabulary voc = DAML_OIL.getInstance();
261       com.hp.hpl.jena.daml.DAMLOntology onto =
262           new DAMLOntologyImpl(
263             this.getSourceURI(),
264             this.getLabel(),
265             model,
266             voc);
267 
268       /* create properties necessary for classes & the ontology */
269 
270       com.hp.hpl.mesa.rdf.jena.model.Property propVersion = model.createProperty(voc.versionInfo().getURI());
271       onto.addProperty(propVersion,this.getVersion());
272 
273       com.hp.hpl.mesa.rdf.jena.model.Property propLabel = model.createProperty(RDFS.label.getURI());
274       onto.addProperty(propLabel,this.getLabel());
275 
276       com.hp.hpl.mesa.rdf.jena.model.Property propComment = model.createProperty(RDFS.comment.getURI());
277       onto.addProperty(propComment,this.getComment());
278 
279 
280       com.hp.hpl.mesa.rdf.jena.model.Property propSubClassOf = model.createProperty(RDFS.subClassOf.getURI());
281 
282 
283       /* create classes */
284       Iterator classes = this.getClasses().iterator();
285       TClass clas;
286       DAMLClass dclas;
287       while (classes.hasNext())  {
288         clas = (TClass) classes.next();
289 
290         dclas = model.createDAMLClass(clas.getURI());
291         dclas.addProperty(propLabel,clas.getName());
292         if (null != clas.getComment()) {
293           dclas.addProperty(propComment,clas.getComment());
294         }
295 
296         /* set super classes */
297         Iterator sups = clas.getSuperClasses(clas.DIRECT_CLOSURE).iterator();
298         TClass supClass;
299         while (sups.hasNext()) {
300           supClass = (TClass) sups.next();
301           dclas.addProperty(propSubClassOf,supClass.getURI());
302         } // while subs
303 
304 
305       } //while classes
306 
307 
308 
309     } catch (Exception e) {
310       throw new ResourceInstantiationException(e);
311     }
312 
313     this.setModified(false);
314     return model;
315   } // store
316 
317 
318 } // class DAMLOntology