1   /*
2    * OntologyImpl.java
3    * Copyright:    Copyright (c) 2002, OntoText Lab.
4    * Company:      OntoText Lab.
5    * borislav popov 03/2002 */
6   
7   package com.ontotext.gate.ontology;
8   
9   import gate.creole.ontology.*;
10  import java.util.List;
11  import java.net.URL;
12  import gate.creole.ResourceInstantiationException;
13  import java.util.Set;
14  import java.util.Iterator;
15  import java.util.Comparator;
16  import gate.DataStore;
17  import gate.persist.PersistenceException;
18  import gate.security.SecurityException;
19  import gate.LanguageResource;
20  import gate.FeatureMap;
21  import gate.creole.ontology.Ontology;
22  import java.util.*;
23  import com.hp.hpl.jena.daml.*;
24  import com.hp.hpl.jena.daml.common.*;
25  import com.hp.hpl.mesa.rdf.jena.model.*;
26  import com.hp.hpl.mesa.rdf.jena.common.*;
27  import com.hp.hpl.jena.vocabulary.*;
28  import com.hp.hpl.mesa.rdf.jena.common.prettywriter.*;
29  import com.hp.hpl.mesa.rdf.jena.vocabulary.*;
30  import com.hp.hpl.jena.rdf.arp.*;
31  
32  import java.util.*;
33  import java.io.*;
34  import java.net.*;
35  
36  import gate.util.Files;
37  import gate.util.Out;
38  
39  public class DAMLKnowledgeBaseImpl extends OntologyImpl  {
40  
41    /** DEBUG FLAG */
42    private static final boolean DEBUG = false;
43    private DAMLModel model = null;
44  
45    public void load() throws gate.creole.ResourceInstantiationException {
46      model = loadAndGetModel();
47      if (model == null || !model.getLoadSuccessful())
48        return;
49  
50      //now load the DAML instances into the KB
51      //currently I do not check for sameIndividualAs, this may have to change
52      //if future applications require it
53      DAMLInstance instance;
54      Iterator ri = model.listDAMLInstances();
55      while (ri.hasNext()) {
56        Object inst = ri.next();
57        if (! (inst instanceof DAMLInstance))
58          continue;
59        instance = (DAMLInstance) inst;
60  
61        Iterator classTypes = instance.getRDFTypes(false);
62        TClass theClass = null;
63        //take only the first class as a type for this instance
64        //because we only support instances that belong to one
65        //class. If an instance needs to belong to more than 1 class,
66        //then make a class, which is a sub-class of those classes,
67        //then add the instance to it
68        while (classTypes.hasNext() && theClass == null) {
69          String localName =
70              ((com.hp.hpl.mesa.rdf.jena.model.Resource)classTypes.next()
71               ).getLocalName();
72          if (localName != null && this.containsClassByName(localName))
73            theClass = this.getClassByName(localName);
74        }//while
75        if (theClass != null && instance.getLocalName() != null) {
76          addInstance(instance.getLocalName(), (OClass) theClass);
77          if (DEBUG)
78            System.out.println("Loaded instance: " + instance.getLocalName() +
79                               "in class: " + theClass.getName());
80        }
81      } //while
82  
83    }//load
84  
85    /** Introduced a protected method that retuns the model, so it can be
86     * used in a subclass to get more data before discarding it
87     */
88    protected DAMLModel loadAndGetModel() throws ResourceInstantiationException{
89  
90      try {
91        model = new DAMLModelImpl();
92  
93  
94        /*get the actual url instead of gate:path*/
95        URL curl = getURL();
96        if ( null == curl )
97          throw new ResourceInstantiationException(
98          "Unable to load ontology because url is not set. (null)");
99  
100       if (-1 != curl.getProtocol().indexOf("gate")) {
101         curl = gate.util.protocols.gate.Handler.class.getResource(
102                       Files.getResourcePath() + getURL().getPath()
103                     );
104       } // if gate:path url
105 
106       model.read(curl.toString());
107       DAMLVocabulary voc = DAML_OIL.getInstance();
108 
109       if (! model.getLoadSuccessful()) {
110         /** if the url does not exist : store the model first*/
111         File f = new File(curl.getFile());
112         if (!f.exists()) {
113           this.store();
114         } // if file doesn't exist
115 
116         //try again
117         model.read(curl.toString());
118 
119         if ( !model.getLoadSuccessful()) {
120           throw new ResourceInstantiationException(
121           "loading of ontology failed. url="+curl.toString());
122         }
123       }// if not sucessful load;
124 
125       if (model.getLoadSuccessful()) {
126         /* load classes */
127         /* on the first iteration the classes are created */
128         DAMLClass clas;
129         ResIterator ri = model.listSubjects();
130         Resource res;
131         while (ri.hasNext()) {
132           res = ri.next();
133           if ( (res instanceof DAMLClass) && ! (res instanceof DAMLRestriction) ) {
134             clas = (DAMLClass)res;
135             String comment = null;
136             if (null != clas.prop_comment().getValue()) {
137               comment = clas.prop_comment().getValue().getString();
138             }
139 
140             /* avoid anonyomouses and restrictions */
141             if ( null!=clas.getLocalName()) {
142               TClass oClass = this.createClass(
143                     clas.getLocalName(),
144                     comment);
145               /*currently only classes from the same ontology are expected*/
146               /*the problem was caused by the gate:/.... urls. when reading a
147               damlclass the urls are unpacked to e.g. file:///d:/.... which is a
148               change of the uri : this is the reason as uri of the class to be set:
149               ontology base uri + # + classURIafter#*/
150               String localURI = clas.getURI();
151 //              if ( -1 == localURI.indexOf('#') ) {
152               oClass.setURI(localURI);
153 //              }  else {
154 //                oClass.setURI(localURI.substring(
155 //                  localURI.indexOf('#')+1
156 //                ));
157 //              } // else
158             } // if not null name - anonymous
159           } else {
160             if (res instanceof DAMLOntologyImpl) {
161               /* only one ontology expected to be loaded */
162               DAMLOntologyImpl onto = (DAMLOntologyImpl) res;
163 
164 
165               try {
166                 Statement s = onto.getProperty(RDFS.label);
167                 this.setLabel(s.getObject().toString());
168               } catch (RDFException rdfex) {
169                 // this means that there is no label property :
170                 // so just set it to an empty string
171                 this.setLabel("");
172               }
173 
174               if ( null != onto.prop_comment().getValue()) {
175                 this.setComment(onto.prop_comment().getValue().toString());
176               }
177 
178               if (null != onto.prop_versionInfo()) {
179                 LiteralAccessor la = onto.prop_versionInfo();
180                 NodeIterator niValues = la.getValues();
181                 if (niValues.hasNext()) {
182                   this.setVersion(niValues.next().toString());
183                 }
184               } // if version
185 
186 
187               {/*set the pre # part as uri and the post # part as id*/
188                 String luri = onto.getURI();
189                 if (null == luri) {
190                   this.setSourceURI("");
191                 } else {
192                   int ix = luri.indexOf('#');
193                   if (-1 != ix) {
194                     this.setSourceURI(luri.substring(0,ix));
195                     this.setId(luri.substring(ix+1));
196                   } else {
197                     this.setSourceURI(onto.getURI());
198                   } // else
199                 } // else
200               } // block
201             }  // if ontology
202           } // else
203 
204         }// while nodes
205 
206 
207         /*append the base uri where needed to the class uris*/
208         Iterator cli = this.getClasses().iterator();
209         while(cli.hasNext()) {
210           OClass ocl = (OClass)cli.next();
211           if ( -1 == ocl.getURI().indexOf('#')) {
212             ocl.setURI(this.getSourceURI()+'#'+ocl.getURI());
213           }
214         } // while
215 
216         /* infer subclassof superclassof relations */
217         ri = model.listSubjects();
218         while (ri.hasNext()) {
219           res = ri.next();
220           if ( (res instanceof DAMLClass) && ! (res instanceof DAMLRestriction) ) {
221 
222             clas = (DAMLClass) res;
223             if ( null == clas.getLocalName()) {
224               continue;
225             }
226             TClass oc = this.getClassByName(clas.getLocalName());
227             if ( null == oc ) {
228               throw new InvalidFormatException(
229               curl,"class not found by name = "+clas.getLocalName());
230             }
231 
232             com.hp.hpl.mesa.rdf.jena.model.Property propSCO = RDFS.subClassOf;
233             StmtIterator subi = clas.listProperties(propSCO);
234             while(subi.hasNext()) {
235               Statement damlSub = (Statement)subi.next();
236               String obj = damlSub.getObject().toString();
237               /*euristic to remove < > from the obj string */
238               if (obj.charAt(0) == '<' && obj.charAt(obj.length()-1) == '>') {
239                 obj=obj.substring(1,obj.length()-1);
240               }
241               obj = obj.substring(obj.lastIndexOf("#")+1);
242               TClass sub = this.getClassByName(obj);
243 
244               if ( null != sub )
245                 oc.addSuperClass(sub);
246 
247             } //while sub classes
248           } //
249         } // while nodes
250 
251 //        if (DEBUG)
252 //          Out.setPrintWriter(new PrintWriter(new FileOutputStream("err.log"), true));
253 
254         //Now read the properties of each class
255         Iterator classIter = model.listDAMLClasses();
256         while (classIter.hasNext()) {
257           DAMLClass theClass = (DAMLClass) classIter.next();
258           if ( null == theClass.getLocalName()) {
259             continue;
260           }
261 
262           Iterator propIter =
263               theClass.getDefinedProperties(false);
264           TClass oc = this.getClassByName(theClass.getLocalName());
265           //if this class in the ontology is not a KBClass, we
266           //cannot read properties and restrictions
267           if (! (oc instanceof OClass) || oc == null)
268             continue;
269 
270           OClass kbClass = (OClass) oc;
271 
272           if (DEBUG) {
273             Out.println("==============================================");
274             Out.println("Class is: " + theClass.getLocalName());
275 
276             Out.println("Properties: ");
277             Out.println("----------------");
278           }
279 
280           HashMap propertiesMap = new HashMap();
281 
282           while (propIter.hasNext()) {
283             Object prop = propIter.next();
284             if (! (prop instanceof DAMLProperty))
285               continue;
286             DAMLProperty property = (DAMLProperty) prop;
287             if (property.getLocalName() == null)
288               continue;
289             String propName = property.getLocalName();
290 
291             if (DEBUG) {
292               Out.println("local name " + property.getLocalName());
293               Out.println("domains ");
294             }
295             //look through all domains for this property and
296             //only if we find one which is the same as our class
297             //then we're going to add it to the GATE ontology model
298             boolean toAdd = true;
299             Iterator domainIter = property.getDomainClasses();
300             while (domainIter.hasNext()) {
301               DAMLClass theDomain = (DAMLClass) domainIter.next();
302               if (DEBUG)
303                 Out.println(theDomain.getLocalName());
304               if (theDomain == null)
305                 continue;
306               if (kbClass.getName().equals(theDomain.getLocalName()))
307                 toAdd = true;
308               else
309                 toAdd = false;
310             }
311             if (!toAdd)
312               continue;
313 
314             if (DEBUG)
315               Out.println("range ");
316 
317             addPropertyDefinition(property, propName, kbClass, propertiesMap);
318 
319             if (DEBUG) Out.println("superproperties ");
320             Iterator superPropIter = property.getSuperProperties(true);
321             while (superPropIter.hasNext()) {
322               DAMLProperty superProp = (DAMLProperty) superPropIter.next();
323               if (superProp == null || superProp.getLocalName() == null)
324                 continue;
325               if (DEBUG) Out.println(superProp.getLocalName());
326               ((gate.creole.ontology.Property) propertiesMap.get(propName)).
327                                   setSubPropertyOf(superProp.getLocalName());
328             }
329 
330           }//while over the properties
331 
332           //add these properties as defined in the ontology
333           addPropertyDefinitions(propertiesMap);
334 
335           if (DEBUG) {
336             Out.println("Restrictions: ");
337             Out.println("----------------");
338           }
339 
340           Iterator superIter = theClass.getSuperClasses();
341           while (superIter.hasNext()) {
342             Object supClass = superIter.next();
343             if (! (supClass instanceof DAMLClass) )
344               continue;
345             DAMLClass superClass = (DAMLClass) supClass;
346             if (superClass.isRestriction()) {
347               DAMLRestriction restriction = (DAMLRestriction) superClass;
348               if (DEBUG) {
349                 Out.println("onProperty "
350                   + restriction.prop_onProperty().getDAMLValue().getLocalName());
351                 Out.println("toClass "
352                   + restriction.prop_toClass().getDAMLValue());
353                 Out.println("hasClass "
354                   + restriction.prop_hasClass().getDAMLValue());
355                 Out.println("hasClassQ "
356                   + restriction.prop_hasClassQ().getDAMLValue());
357                 Out.println("cardinality "
358                   + restriction.prop_cardinality().getDAMLValue());
359                 Out.println("cardinalityQ "
360                   + restriction.prop_cardinalityQ().getDAMLValue());
361               }
362               String propName =
363                 restriction.prop_onProperty().getDAMLValue().getLocalName();
364               if (propName == null)
365                 continue;
366               String rangeName = null;
367               if (restriction.prop_toClass().getDAMLValue() != null) {
368                 rangeName = restriction.prop_toClass().getDAMLValue().getLocalName();
369               } else if (restriction.prop_hasClass().getDAMLValue() != null) {
370                 rangeName = restriction.prop_hasClass().getDAMLValue().getLocalName();
371               } else if (restriction.prop_hasClassQ().getDAMLValue() != null) {
372                 rangeName = restriction.prop_hasClassQ().getDAMLValue().getLocalName();
373               }
374 
375 
376               gate.creole.ontology.Property theNewProperty = null;
377               gate.creole.ontology.Property thePropDefinition =
378                   (gate.creole.ontology.Property) propertiesMap.get(propName);
379               if (thePropDefinition == null) {
380                 //check if this property is defined for a superclass
381                 thePropDefinition =
382                   searchSuperClasses(propName, theClass, propertiesMap);
383               }
384               //we haven't seen this property defined for this class
385               if (thePropDefinition == null) {
386                 Out.println("Warning: Ignoring restriction on property " + propName +
387                   " because cannot find such property defined for this class");
388               } else {
389                 //process the properties differently depending on their type
390                 if (thePropDefinition instanceof ObjectProperty) {
391                   TClass rangeClass = this.getClassByName(rangeName);
392 
393                   if (rangeClass == null || !(rangeClass instanceof OClass))
394                     rangeClass = (OClass)((ObjectProperty) thePropDefinition).getRange();
395 
396                   theNewProperty = this.addObjectProperty(
397                                           thePropDefinition.getName(),
398                                           kbClass,
399                                           (OClass) rangeClass);
400                 } else {
401                   theNewProperty = this.addDatatypeProperty(
402                                           thePropDefinition.getName(),
403                                           kbClass,
404                                           rangeName);
405                 }
406               }//if
407 
408 
409             }//if restriction
410           } //loop through the restrictions
411 
412         } //while loop through the classes
413 
414       } // if model.getloadsucessful
415 
416       /**debug*/
417       if (DEBUG) {
418         Out.println("Property definitions for the ontology");
419         Set propertyDefs = this.getPropertyDefinitions();
420         if (propertyDefs != null ) {
421           Iterator iter = propertyDefs.iterator();
422           while (iter.hasNext())
423             Out.println( iter.next().toString());
424         }
425 
426         Out.println("Classes: ");
427         Iterator ic = this.getClasses().iterator();
428         while (ic.hasNext()) {
429           OClass cl = (OClass)ic.next();
430           Out.println(" ");
431           Out.println(" " +cl+ " [direct sub classes = "+
432           cl.getSubClasses(OClass.DIRECT_CLOSURE).size()+"] "+
433           "[transitive sub classes = "+
434           cl.getSubClasses(OClass.TRANSITIVE_CLOSURE).size()+"]" +
435            "[direct super classes = " +
436            cl.getSuperClasses(OClass.DIRECT_CLOSURE).size() + " ] " +
437            "[transitive super classes = " +
438            cl.getSuperClasses(OClass.TRANSITIVE_CLOSURE).size() + "]");
439 
440           if (cl instanceof OClass) {
441             OClass kbCl = (OClass) cl;
442             if (kbCl.getProperties() == null)
443               continue;
444             Iterator ip = kbCl.getProperties().iterator();
445             while (ip.hasNext()) {
446               Out.println( ip.next().toString());
447             }
448           }
449         }
450       } // debug end
451 
452 
453     } catch (Exception e) {
454       throw new ResourceInstantiationException(e);
455     }
456 
457     this.setModified(false);
458 
459     return model;
460   } // load()
461 
462   private gate.creole.ontology.Property addPropertyDefinition(
463         DAMLProperty property, String propName, OClass kbClass,
464         Map propertiesMap) throws RDFException{
465     gate.creole.ontology.Property newProperty = null;
466     PropertyAccessor propAcc = property.prop_range();
467     if (property instanceof DAMLDatatypeProperty) {
468       //do not read the ranges of the datatatype properties, because
469       //they are tricky
470       newProperty =
471         new DatatypePropertyImpl(propName, kbClass, (String) null, this);
472       propertiesMap.put(propName, newProperty);
473     } else if (propAcc instanceof LiteralAccessor) {
474       if (DEBUG) Out.println("Literal accessor");
475       //add a DatatypeProperty
476       if (((LiteralAccessor)propAcc).getValue() != null) {
477         newProperty = new DatatypePropertyImpl(propName, kbClass,
478             ((LiteralAccessor)propAcc).getValue().getString(), this);
479         propertiesMap.put(propName, newProperty);
480         if (DEBUG)
481           Out.println(((LiteralAccessor)propAcc).getValue());
482       }
483     } else if (property instanceof DAMLObjectProperty) {
484       if (DEBUG)
485         Out.println(propAcc.getDAMLValue());
486       if (propAcc.getDAMLValue() == null) {
487         if (DEBUG)
488           Out.println("Found a null value, adding as null");
489         newProperty = new ObjectPropertyImpl(propName, kbClass, null, this);
490         propertiesMap.put(propName, newProperty);
491       } else {
492         if (DEBUG)
493           Out.println(propAcc.getDAMLValue().getLocalName());
494         TClass rangeClass =
495           this.getClassByName(propAcc.getDAMLValue().getLocalName());
496         if (rangeClass == null || !(rangeClass instanceof OClass)) {
497           newProperty = new ObjectPropertyImpl(propName, kbClass, null, this);
498           propertiesMap.put(propName, newProperty);
499         } else {
500           newProperty =
501             new ObjectPropertyImpl(propName, kbClass, (OClass) rangeClass, this);
502           propertiesMap.put(propName, newProperty);
503         }
504       }
505     }
506     return newProperty;
507   }
508 
509   private gate.creole.ontology.Property searchSuperClasses(String propName, DAMLClass theClass,
510                                         Map propertiesMap)
511                     throws RDFException{
512     if (DEBUG)
513       Out.println("searchSuperClasses called: propName" +
514                   propName + "; className " + theClass.getLocalName());
515     if (theClass == null)
516       return null;
517     if (propName == null)
518       return null;
519 
520     gate.creole.ontology.Property theProperty =
521         this.getPropertyDefinitionByName(propName);
522     String propDomainName = null;
523     //we have not yet loaded this property, so find it among the inherited ones in
524     //the DAML model
525     if (theProperty == null) {
526       if (DEBUG) Out.println("Cannot find property definition" + propName);
527 
528       Iterator iter = theClass.getDefinedProperties(true);
529       boolean propFound = false;
530       while (iter.hasNext() && !propFound) {
531         DAMLProperty property = (DAMLProperty) iter.next();
532         if (property.getLocalName().equals(propName)
533             && property.getDomainClasses().hasNext()) {
534           propDomainName =
535             ((DAMLClass) property.getDomainClasses().next()).getLocalName();
536           propFound = true;
537           if (DEBUG)
538             Out.println("Domain is: " + propDomainName);
539           TClass kbClass = this.getClassByName(propDomainName);
540           if (kbClass != null && kbClass instanceof OClass) {
541             theProperty =
542               this.addPropertyDefinition(
543                     property, propName, (OClass) kbClass, propertiesMap);
544           }//if
545         }//if
546       }//while
547       if (!propFound) {
548         Out.println("Warning: Found restriction on property " + propName +
549                     " for class " +
550                     theClass.getLocalName() +
551                     "which has undefined domain or its domain does not" +
552                     "match the given class");
553         Iterator propIter = model.listDAMLProperties();
554         while (propIter.hasNext()) {
555           DAMLProperty property = (DAMLProperty) propIter.next();
556           if (property.getLocalName().equals(propName))
557             theProperty =
558               this.addPropertyDefinition(
559                     property, propName, null, propertiesMap);
560         }
561       }
562     } else {
563       propDomainName = theProperty.getDomain().getName();
564       boolean found = false;
565       //search the superclasses of the given DAML class to find if the domain
566       //of this property is a superclass of the given class
567       Iterator cIter = theClass.getSuperClasses(true);
568       while (cIter.hasNext() && !found) {
569         if (propDomainName.equals( ((DAMLClass) cIter.next()).getLocalName()))
570           found = true;
571       }
572       if (!found)
573         theProperty = null;
574     }
575     return theProperty;
576 
577   }
578 
579   private boolean isRelationDefinedOnSuperClass(OClass kbClass, String domainName) {
580     boolean result = false;
581     Set superClasses = null;
582     try {
583       superClasses = kbClass.getSuperClasses(OClass.TRANSITIVE_CLOSURE);
584     } catch (gate.creole.ontology.NoSuchClosureTypeException ex) {}
585     if (superClasses == null || superClasses.isEmpty())
586       return false;
587     Iterator iter = superClasses.iterator();
588     while (iter.hasNext()) {
589       if (((OClass) iter.next()).getName().equals(domainName))
590         return true;
591     }
592     return result;
593   }
594   private void addPropertyDefinitions(HashMap propertiesMap) {
595     Iterator iter = propertiesMap.keySet().iterator();
596     while (iter.hasNext()) {
597       String propertyName = (String) iter.next();
598       //we have already added this property definition to the ontology
599       if (this.getPropertyDefinitionByName(propertyName) != null)
600         continue;
601       this.addPropertyDefinition(
602           (gate.creole.ontology.Property) propertiesMap.get(propertyName));
603     }
604   }
605 
606   private void addRemainingProperties(HashMap propertiesMap) {
607     if (propertiesMap == null || propertiesMap.isEmpty())
608       return;
609 
610     Iterator iter = propertiesMap.keySet().iterator();
611     while (iter.hasNext()) {
612       String propertyName = (String) iter.next();
613       gate.creole.ontology.Property theProperty =
614           (gate.creole.ontology.Property) propertiesMap.get(propertyName);
615 
616       //process the properties differently depending on their type
617       if (theProperty instanceof ObjectProperty) {
618         this.addObjectProperty(theProperty.getName(),
619                                theProperty.getDomain(),
620                                (OClass)((ObjectProperty)theProperty).getRange());
621       } else {
622         this.addDatatypeProperty(theProperty.getName(),
623                                  theProperty.getDomain(),
624                                  (String)((DatatypeProperty)theProperty).getRange());
625       }
626     }
627 
628   }
629 
630   public void store() throws gate.creole.ResourceInstantiationException {
631     DAMLModel theModel = storeAndGetModel();
632     writeModel(theModel);
633     System.out.println("No storage of instances and properties implemented yet!");
634   }
635 
636   protected void writeModel(DAMLModel model) throws ResourceInstantiationException {
637     try {
638       /* store the model */
639       Writer writer = new FileWriter(this.getURL().getFile());
640       RDFWriter rdfWriter = model.getWriter("RDF/XML-ABBREV");
641       rdfWriter.write(model, writer, this.getSourceURI());
642     } catch (Exception e) {
643       throw new ResourceInstantiationException(e);
644     }
645   }
646 
647 
648   protected DAMLModel storeAndGetModel()throws ResourceInstantiationException  {
649       DAMLModel model = new DAMLModelImpl();
650 
651       try {
652       /*ensure that all classes will be newly inferred
653       later make this through more carefull
654       handling of ontology.modified flag*/
655       this.setModified(true);
656 
657       /* create ontology & get vocabulary */
658       DAMLVocabulary voc = DAML_OIL.getInstance();
659       com.hp.hpl.jena.daml.DAMLOntology onto =
660           new DAMLOntologyImpl(
661             this.getSourceURI(),
662             this.getLabel(),
663             model,
664             voc);
665 
666       /* create properties necessary for classes & the ontology */
667 
668       com.hp.hpl.mesa.rdf.jena.model.Property propVersion =
669           model.createProperty(voc.versionInfo().getURI());
670       onto.addProperty(propVersion,this.getVersion());
671 
672       com.hp.hpl.mesa.rdf.jena.model.Property propLabel =
673           model.createProperty(RDFS.label.getURI());
674       onto.addProperty(propLabel,this.getLabel());
675 
676       com.hp.hpl.mesa.rdf.jena.model.Property propComment =
677           model.createProperty(RDFS.comment.getURI());
678       onto.addProperty(propComment,this.getComment());
679 
680 
681       com.hp.hpl.mesa.rdf.jena.model.Property propSubClassOf =
682           model.createProperty(RDFS.subClassOf.getURI());
683 
684 
685       /* create classes */
686       Iterator classes = this.getClasses().iterator();
687       OClass clas;
688       DAMLClass dclas;
689       while (classes.hasNext())  {
690         clas = (OClass) classes.next();
691 
692         dclas = model.createDAMLClass(clas.getURI());
693         dclas.addProperty(propLabel,clas.getName());
694         if (null != clas.getComment()) {
695           dclas.addProperty(propComment,clas.getComment());
696         }
697 
698         /* set super classes */
699         Iterator sups = clas.getSuperClasses(clas.DIRECT_CLOSURE).iterator();
700         OClass supClass;
701         while (sups.hasNext()) {
702           supClass = (OClass) sups.next();
703           dclas.addProperty(propSubClassOf,supClass.getURI());
704         } // while subs
705 
706 
707       } //while classes
708 
709 
710 
711     } catch (Exception e) {
712       throw new ResourceInstantiationException(e);
713     }
714 
715     this.setModified(false);
716     return model;
717   } // store
718 
719 
720 }