001    /**
002     * OntoBride library.
003     * GAIA - Group for Artifical Intelligence Applications
004     * Departamento de Ingeniería del Software e Inteligencia Artificial
005     * Universidad Complutense de Madrid
006     * 
007     * Licensed under the terms of the GNU Library or Lesser General Public License (LGPL)
008     *
009     * @author Juan A. Recio García
010     * @version 1.2
011     * 
012     * This software is a subproject of the jCOLIBRI framework
013     * http://sourceforge.net/projects/jcolibri-cbr/
014     * http://gaia.fdi.ucm.es/projects/jcolibri/
015     * 
016     * File: OntoBridge.java
017     * 22/11/2006
018     */
019    package es.ucm.fdi.gaia.ontobridge;
020    
021    
022    import java.io.FileWriter;
023    import java.util.ArrayList;
024    import java.util.Collection;
025    import java.util.HashMap;
026    import java.util.HashSet;
027    import java.util.Iterator;
028    import java.util.List;
029    import java.util.Set;
030    
031    import org.mindswap.pellet.jena.PelletReasonerFactory;
032    
033    import com.hp.hpl.jena.ontology.DatatypeProperty;
034    import com.hp.hpl.jena.ontology.OntClass;
035    import com.hp.hpl.jena.ontology.OntDocumentManager;
036    import com.hp.hpl.jena.ontology.OntModel;
037    import com.hp.hpl.jena.ontology.OntModelSpec;
038    import com.hp.hpl.jena.ontology.OntProperty;
039    import com.hp.hpl.jena.ontology.OntResource;
040    import com.hp.hpl.jena.rdf.model.Model;
041    import com.hp.hpl.jena.rdf.model.ModelFactory;
042    import com.hp.hpl.jena.rdf.model.Property;
043    import com.hp.hpl.jena.rdf.model.RDFNode;
044    import com.hp.hpl.jena.rdf.model.Resource;
045    import com.hp.hpl.jena.rdf.model.Statement;
046    import com.hp.hpl.jena.rdf.model.StmtIterator;
047    import com.hp.hpl.jena.reasoner.ReasonerRegistry;
048    import com.hp.hpl.jena.reasoner.ValidityReport;
049    import com.hp.hpl.jena.reasoner.dig.DIGReasoner;
050    import com.hp.hpl.jena.reasoner.dig.DIGReasonerFactory;
051    import com.hp.hpl.jena.util.iterator.Filter;
052    import com.hp.hpl.jena.vocabulary.RDF;
053    import com.hp.hpl.jena.vocabulary.RDFS;
054    import com.hp.hpl.jena.vocabulary.ReasonerVocabulary;
055    
056    import es.ucm.fdi.gaia.ontobridge.exceptions.NoLocalFileException;
057    import es.ucm.fdi.gaia.ontobridge.util.ToStringIterator;
058    
059    
060    
061    /**
062     * Main OntoBridge Class<br>
063     * This class provides a simple wrapper for JENA.<br> 
064     * It allows connecting to PELLET reasoner or any other that supports the DIG protocol.
065     * Instead of using JENA classes this class returns strings containing the URIs
066     * of the elements in the ontology.
067     * Input parameters of the methods use URIs (or the qualified short representation) for
068     * pointing to the ontology elements.<br>
069     * Conversion between URIs and JENA objects is managed automatically
070     * 
071     * 
072     * @author Juan A. Recio García
073     *
074     */
075    public class OntoBridge {
076    
077            /** JENA Ontology Model */
078            private OntModel ONT_MODEL;
079            /** Base URI/Namespace for the main ontology */
080            private String   BASE_NS;
081            
082            /** Backup variable used to store initial model when disabling inference */
083            private OntModel backupModel = null;
084            
085            
086            
087            /** Creates an OntoBridge object. Currentlly it does nothing.*/
088            public OntoBridge()
089            {   
090            }
091            
092            /**
093             * Inits the OntoBridge with the PELLET Reasoner
094             */
095            public void initWithPelletReasoner()
096            {
097                    ONT_MODEL = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC);   
098            }
099            
100            /**
101             * Inits the OntoBridge with a DIG reasoner.
102             * Dig is a protocol (working over http) that allows conecting with any reasoner.
103             * @param reasonerHost Host where the reasoner is running.
104             * @param reasonerPort Port that the reasoner listens to.
105             */
106            public void initWithDIGReasoner(String reasonerHost, int reasonerPort)
107            {
108                    //Create a default model
109                    Model cModel = ModelFactory.createDefaultModel();
110                    
111                    //Obtain the reasonerURL
112                    String reasonerURL = "http://" + reasonerHost + ":" + reasonerPort;
113                    
114                    //Create a reasoner configuration with the reasoner URL
115                    Resource conf = cModel.createResource();
116                    conf.addProperty(ReasonerVocabulary.EXT_REASONER_URL, cModel.createResource(reasonerURL));
117                    
118                    //Obtain the Dig reasoners Factory
119                    DIGReasonerFactory drf = (DIGReasonerFactory) ReasonerRegistry
120                                    .theRegistry().getFactory(DIGReasonerFactory.URI);
121    
122                    //Obtain a reasoner with our configuration
123                    DIGReasoner r = (DIGReasoner) drf.create(conf);
124    
125                    //Choose the Ontology Model Specification: OWL-DL in Memory
126                    OntModelSpec spec = new OntModelSpec(OntModelSpec.OWL_DL_MEM);
127                    spec.setReasoner(r);
128                    
129                    //Obtain the OntologyModel
130                    ONT_MODEL = ModelFactory.createOntologyModel(spec);
131            }
132            
133            /**
134             * Inits the OntoBridge without reasoner.
135             * That way, this class doesn't use any inferred knowledge of the ontology
136             */
137            public void initWithOutReasoner()
138            {
139                    ONT_MODEL = ModelFactory.createOntologyModel( OntModelSpec.OWL_MEM);
140            }
141            
142            
143            /**
144             * Enables or disables the inference. This method should be only used for performance reasons. 
145             * When disabling inference, current model is validated, backed-up and finally a new model is created without attached reasoner.
146             * If inference is enabled again the back-up model is restored.
147             * This method does not distinguish if the object was initializated without reasoner. If so, this method is unusefull.
148             * Any change performed in the ontology when inference is disabled will not be maintained when inference is enabled again, 
149             * because this method creates a copy of the current model.
150             * @param enabled Indicates if inference is enabled
151             */
152            public void setInference(boolean enabled)
153            {
154                    if(enabled)
155                    {
156                            if(backupModel != null)
157                            {
158                                    ONT_MODEL = backupModel;
159                                    backupModel = null;
160                            }
161                            else
162                                    org.apache.commons.logging.LogFactory.getLog(this.getClass()).warn("Inference already enabled.");
163                    }
164                    else
165                    {
166                            if(backupModel == null)
167                            {
168                                    //Validate the model (classify instances)
169                                    ONT_MODEL.validate();
170                                    //Backup model
171                                    backupModel = ONT_MODEL;
172                                    //Create a plain model with asserted and infered information (a-box + t-box)
173                                    Model plain = ModelFactory.createModelForGraph( ONT_MODEL.getGraph() );
174                                    //Create a new model without reasoner
175                                    ONT_MODEL = ModelFactory.createOntologyModel( OntModelSpec.OWL_MEM);
176                                    //Copy plain model into the model without reasoner
177                                    ONT_MODEL.add(plain);
178                                    //Copy ns prefixes
179                                    ONT_MODEL.setNsPrefixes(backupModel.getNsPrefixMap());
180                            }
181                            else
182                                    org.apache.commons.logging.LogFactory.getLog(this.getClass()).warn("Inference already disabled.");
183                    }
184            }
185            
186            /**
187             * Loads an ontology using the initialized reasoner
188             * @param mainOntology Main ontology document
189             * @param subOntologies Collection of ontology documents used by the main ontology
190             * @param loadSubOntologies Indicates if the reasoner must load the subOntologies. 
191             *        If loaded, their content is included in the reasoning graph of the main ontology graph.
192             */
193            public void loadOntology(OntologyDocument mainOntology, Collection<OntologyDocument> subOntologies, boolean loadSubOntologies)
194            {
195                    //Configure local copies of the ontologies
196                    OntDocumentManager dm = ONT_MODEL.getDocumentManager();
197                    
198                    try {
199                            if(mainOntology.hasAltLocalFile())
200                                    dm.addAltEntry(mainOntology.getURL(), mainOntology.getLocalfile());
201                    } catch (NoLocalFileException e) {
202                            org.apache.commons.logging.LogFactory.getLog(this.getClass()).error(e);
203                    }
204                    
205                    for(OntologyDocument od : subOntologies)
206                    {
207                            try {
208                            if(od.hasAltLocalFile())
209                                    dm.addAltEntry(od.getURL(), od.getLocalfile());
210                            } catch (NoLocalFileException e) {
211                                    org.apache.commons.logging.LogFactory.getLog(this.getClass()).error(e);
212                            }
213                    }
214                    
215                    org.apache.commons.logging.LogFactory.getLog(this.getClass()).info("Loading Main Ontology: "+mainOntology.getURL());
216                    ONT_MODEL.read(mainOntology.getURL());  
217                    BASE_NS = (String)ONT_MODEL.getNsPrefixMap().get("");
218                    
219                    if(loadSubOntologies)
220                            for(OntologyDocument od : subOntologies)
221                            {
222                                    org.apache.commons.logging.LogFactory.getLog(this.getClass()).info("Loading Sub-Ontology: "+od.getURL());
223                                    ONT_MODEL.read(od.getURL());
224                            }
225                    
226                    
227                    org.apache.commons.logging.LogFactory.getLog(this.getClass()).info("Loading Complete");
228                    //Print Namespaces
229                    org.apache.commons.logging.LogFactory.getLog(this.getClass()).info( "Base Namespace: "+ BASE_NS );
230                    org.apache.commons.logging.LogFactory.getLog(this.getClass()).info( "Namespaces loaded: " + ONT_MODEL.getNsPrefixMap() );
231                    
232                    preCalculateProfs();
233                    
234            }
235    
236            /**************************************************************/
237            /****************      Depth methods   ************************/
238            /**************************************************************/
239    
240            private HashMap<String, Integer> profs = new HashMap<String,Integer>();
241            private int maxDepth = 0;
242            
243            private void preCalculateProfs()
244            {
245                    profs.clear();
246                    
247                    String thing = getThingURI();
248                    profs.put(thing, new Integer(0));
249                    
250                    HashSet<String> subclasses = new HashSet<String>();
251                    
252                    Iterator<String> iter = this.listRootClasses();
253                    boolean cont = true;
254                    int i = 1;
255                    while(cont)
256                    {
257                            subclasses  = new HashSet<String>();
258                            while(iter.hasNext())
259                            {
260                                    String _class = iter.next();
261                                    profs.put(_class, new Integer(i));
262                                            
263                                    Iterator<String> aux = this.listSubClasses(_class,true);
264                                    while(aux.hasNext())
265                                            subclasses.add(aux.next());     
266                            }
267                            cont = !subclasses.isEmpty();
268                            iter = subclasses.iterator();
269                            i++;
270                    }
271                    maxDepth = i-2;
272            }
273            
274            public int profConcept(String _class)
275            {
276                    if(!_class.contains("#"))
277                            _class = getURI(_class);
278                    return profs.get(_class);
279            }
280            public int profInstance(String instance)
281            {
282                    int res = Integer.MAX_VALUE;
283                    for(Iterator<String> iter = listDeclaredBelongingClasses(instance); iter.hasNext();)
284                    {
285                            int prof = profConcept(iter.next());
286                            if(prof<res)
287                                    res = prof;
288                    }
289                    return res+1;
290            }
291            
292            public int getMaxProf()
293            {
294                    return maxDepth;
295            }
296            
297            
298            /**
299             * Returns the maximum profundity of the Least Common Subsumers of two instances.
300             */
301            public int maxProfLCS(String instance1, String instance2)
302            {
303                    Set<String> parents1 = new HashSet<String>();       
304                    for(Iterator<String> iter = listBelongingClasses(instance1);iter.hasNext(); )
305                            parents1.add(iter.next());
306                    
307    
308                    Set<String> parents2 = new HashSet<String>();       
309                    for(Iterator<String> iter = listBelongingClasses(instance2);iter.hasNext(); )
310                            parents2.add(iter.next());      
311    
312                    int maxProf = Integer.MIN_VALUE;
313                    
314                    parents1.retainAll(parents2);
315                    for(String c: parents1)
316                    {
317                            int pc = this.profConcept(c);
318                            if(pc>maxProf)
319                                    maxProf = pc;
320                    }
321                    return maxProf;
322            }
323            
324            /**
325             * Returns a set with the Least Common Subsumers of two instances. 
326             */
327            public Set<String> LCS(String instance1, String instance2)
328            {
329                    Set<String> parents1 = new HashSet<String>();       
330                    for(Iterator<String> iter = listBelongingClasses(instance1);iter.hasNext(); )
331                            parents1.add(iter.next());
332                    
333    
334                    Set<String> parents2 = new HashSet<String>();       
335                    for(Iterator<String> iter = listBelongingClasses(instance2);iter.hasNext(); )
336                            parents2.add(iter.next());      
337                    
338                    Set<String> res = new HashSet<String>();
339                    int maxProf = Integer.MIN_VALUE;
340                    
341                    parents1.retainAll(parents2);
342                    for(String c: parents1)
343                    {
344                            int pc = this.profConcept(c);
345                            if(pc>maxProf)
346                            {
347                                    res.clear();
348                                    res.add(c);
349                                    maxProf = pc;
350                            }
351                            else if(pc==maxProf)
352                            {
353                                    res.add(c);
354                                    maxProf = pc;
355                            }
356                            
357                    }
358                    return res;
359                    
360                    
361                    /*
362                    Set<String> res = new HashSet<String>();
363                    
364                    Set<String> sc1 = new HashSet<String>();    
365                    for(Iterator<String> iter = listDeclaredBelongingClasses(instance1);iter.hasNext(); )
366                            sc1.add(iter.next());
367                    
368                    Set<String> sc2 = new HashSet<String>();    
369                    for(Iterator<String> iter = listDeclaredBelongingClasses(instance2);iter.hasNext(); )
370                            sc2.add(iter.next());
371                    
372                    Set<String> inter = new HashSet<String>(sc1);
373                    inter.retainAll(sc2);
374                    
375                    res.addAll(inter);
376                    
377                    sc1.removeAll(inter);
378                    sc2.removeAll(inter);
379                    
380                    
381                    Set<String> sparentsc1 = new HashSet<String>();
382                    Set<String> sparentsc2 = new HashSet<String>();
383    
384                    while(!sc1.isEmpty() && !sc2.isEmpty())
385                    {
386                            
387                            for(String c1: sc1)
388                            {
389                                    Iterator<String> iter = listSuperClasses(c1, true);
390                                    if(iter != null)
391                                            while(iter.hasNext())
392                                                    sparentsc1.add(iter.next());
393                            }
394                            for(String c2: sc2)
395                            {
396                                    Iterator<String> iter = listSuperClasses(c2, true);
397                                    if(iter != null)
398                                            while(iter.hasNext())
399                                                    sparentsc2.add(iter.next());
400                            }
401                            
402                            inter.clear();
403                            inter.addAll(sparentsc1);
404                            inter.retainAll(sparentsc2);
405                            
406                            res.addAll(inter);
407                            sparentsc1.removeAll(inter);
408                            sparentsc2.removeAll(inter);
409                            
410                            sc1 = new HashSet<String>(sparentsc1);
411                            sc2 = new HashSet<String>(sparentsc2);
412                    }
413                    return inter;
414                    */
415            }
416            
417            /**************************************************************/
418            /*      Functions for listing Classes of the Ontology         */
419            /**************************************************************/
420            
421            /**
422             * Lists all the no anonymous classes of the ontology
423             */
424            public Iterator<String> listAllClasses()
425            {
426                    return new ToStringIterator<String>(ONT_MODEL.listClasses().filterDrop( new Filter() {
427                public boolean accept( Object o ) {
428                    return ((Resource) o).isAnon();
429                }} )
430            );
431            }
432    
433            /**
434             * Lists all the classes of the ontology including anonymous classes
435             */
436            public Iterator<String> listAllandAnonClasses()
437            {
438                    return new ToStringIterator<String>(ONT_MODEL.listClasses());
439            }
440            
441            /**
442             * Lists the enumerated classes of the ontology
443             */
444            public Iterator<String> listEnumeratedClasses()
445            {
446                    return new ToStringIterator<String>(ONT_MODEL.listEnumeratedClasses().filterDrop( new Filter() {
447                public boolean accept( Object o ) {
448                    return ((Resource) o).isAnon();
449                }} )
450            );
451            }
452            
453            /**
454             * Lists the union classes of the ontology
455             */
456            public Iterator<String> listUnionClasses()
457            {
458                    return new ToStringIterator<String>(ONT_MODEL.listUnionClasses().filterDrop( new Filter() {
459                public boolean accept( Object o ) {
460                    return ((Resource) o).isAnon();
461                }} )
462            );
463            }
464            
465            /**
466             * Lists the complement classes of the ontology
467             */
468            public Iterator<String> listComplementClasses()
469            {
470                    return new ToStringIterator<String>(ONT_MODEL.listComplementClasses().filterDrop( new Filter() {
471                public boolean accept( Object o ) {
472                    return ((Resource) o).isAnon();
473                }} )
474            );
475            }
476            
477            /**
478             * Lists the intersection classes of the ontology
479             */
480            public Iterator<String> listIntersectionClasses()
481            {
482                    return new ToStringIterator<String>(ONT_MODEL.listIntersectionClasses().filterDrop( new Filter() {
483                public boolean accept( Object o ) {
484                    return ((Resource) o).isAnon();
485                }} )
486            );
487            }
488            
489            /**
490             * Lists the restrictions of the ontology
491             */
492            public Iterator<String> listRestrictions()
493            {
494                    return new ToStringIterator<String>(ONT_MODEL.listRestrictions().filterDrop( new Filter() {
495                public boolean accept( Object o ) {
496                    return ((Resource) o).isAnon();
497                }} )
498            );
499            }
500            
501            /**
502             * Lists the hierarchy root classes of the ontology
503             */
504            public Iterator<String> listRootClasses()
505            {
506                    return new ToStringIterator<String>(ONT_MODEL.listHierarchyRootClasses().filterDrop( new Filter() {
507                public boolean accept( Object o ) {
508                    return ((Resource) o).isAnon();
509                }} )
510            );              
511            }
512            
513            /**************************************************************/
514            /*      Functions for checking sub-super classes and          */
515            /*      instances belonging                                   */
516            /**************************************************************/
517            
518            /**
519             * Lists the subclasses of a class. 
520             * @param ontClass class parent of the classes user is asking for
521             * @param direct return only direct subclasses
522             */
523            public Iterator<String> listSubClasses(String ontClass, boolean direct)
524            {
525                    try{
526                            OntClass ontC = obtainOntClass(ontClass);
527                            return new ToStringIterator<String>(ontC.listSubClasses(direct));
528                    }catch(Exception e)
529                    {
530                            return new ArrayList<String>().iterator();
531                    }
532            }
533            
534            /**
535             * Lists the superclasses (parents) of a class. 
536             * @param ontClass subclass of the classes user is asking for
537             * @param direct return only direct subclasses
538             */
539            public Iterator<String> listSuperClasses(String ontClass, boolean direct)
540            {
541                    try
542                    {
543                            OntClass ontC = obtainOntClass(ontClass);
544                            return new ToStringIterator<String>(ontC.listSuperClasses(direct));
545                    }catch(Exception e)
546                    {
547                            return new ArrayList<String>().iterator();
548                    }
549            }
550            
551            /**
552             * List the instances of a class
553             * @param ontClass class that instances belong to
554             */
555            public Iterator<String> listInstances(String ontClass)
556            {
557                    OntClass ontC = obtainOntClass(ontClass);
558                    return new ToStringIterator<String>(ontC.listInstances());
559            }
560    
561            /**
562             * List the declared (not inferred) instances of a class
563             * @param ontClass class that instances belong to
564             */
565            public Iterator<String> listDeclaredInstances(String ontClass)
566            {
567                    ArrayList<String> list = new ArrayList<String>();
568                    OntClass ontC = obtainOntClass(ontClass);
569                    StmtIterator si = ONT_MODEL.getRawModel().listStatements(null, RDF.type, ontC);
570                    while(si.hasNext())
571                    {
572                            Statement st = si.nextStatement();
573                            list.add(st.getSubject().toString());
574                    }
575                    return list.iterator();
576            }
577            
578            
579            /**
580             * Lists the classes that an instance belongs to
581             * @param instance instance asked for belonging classes
582             */
583            public Iterator<String> listBelongingClasses(String instance)
584            {
585                    ArrayList<String> list = new ArrayList<String>();
586                    OntResource ontI = obtainOntResource(instance);
587                    StmtIterator si = ONT_MODEL.listStatements(ontI, RDF.type, (RDFNode)null);
588                    while(si.hasNext())
589                    {
590                            Statement st = si.nextStatement();
591                            list.add(st.getObject().toString());
592                    }
593                    return list.iterator();
594                    
595            }
596            
597            /**
598             * Lists the declared (not inferred) classes that an instance belongs to
599             * @param instance instance asked for belonging classes
600             */
601            public Iterator<String> listDeclaredBelongingClasses(String instance)
602            {
603                    ArrayList<String> list = new ArrayList<String>();
604                    OntResource ontI = obtainOntResource(instance);
605                    StmtIterator si = ONT_MODEL.getRawModel().listStatements(ontI, RDF.type, (RDFNode)null);
606                    while(si.hasNext())
607                    {
608                            Statement st = si.nextStatement();
609                            list.add(st.getObject().toString());
610                    }
611                    return list.iterator();
612                    
613            }
614            
615            /**
616             * Checks if a class is subclass of other
617             * @param subclass subclasss
618             * @param superclass superclass
619             */
620            public boolean isSubClassOf(String subclass, String superclass)
621            {
622                    OntClass subC = obtainOntClass(subclass);
623                    OntClass superC = obtainOntClass(superclass);
624                    StmtIterator si = ONT_MODEL.listStatements(subC, RDFS.subClassOf,superC);
625                    return si.hasNext();
626            }
627    
628            /**
629             * Checks if an instance belongs to a class
630             * @param instance instance
631             * @param ontclass class
632             */
633            public boolean isInstanceOf(String instance, String ontclass)
634            {
635                    OntClass ontC = obtainOntClass(ontclass);
636                    OntResource ontI = obtainOntResource(instance);
637                    StmtIterator si = ONT_MODEL.listStatements(ontI, RDF.type, ontC);
638                    return si.hasNext();
639            }
640            
641            /**
642             * Checks if a proporty is an OntologyProperty instead of a DataTypeProperty
643             * @param property
644             * @return if it is an OntologyProperty
645             */
646            public boolean isOntoProperty(String property)
647            {
648                    return ! (obtainOntProperty(property) instanceof DatatypeProperty);
649            }
650            
651            
652            /**************************************************************/
653            /*      Functions for managing properties between             */
654            /*      classes and instances                                 */
655            /**************************************************************/
656            
657            /**
658             * Lists the properties applicable to a class
659             * @param ontClass class in the domain of the listed properties
660             */
661            public Iterator<String> listProperties(String ontClass)
662            {
663                    OntClass ontR = obtainOntClass(ontClass);
664                    return new ToStringIterator<String>(ontR.listDeclaredProperties());
665            }
666            
667            /**
668             * Lists the specific properties of class. This method only returns the 
669             * properties that has the specified class in the domain
670             * @param ontClass class in the domain of the listed properties
671             */
672            public Iterator<String> listSpecificProperties(String ontClass)
673            {
674                    ArrayList<String> list = new ArrayList<String>();
675                    OntClass ontR = obtainOntClass(ontClass);
676                    for(Iterator iter = ontR.listDeclaredProperties(); iter.hasNext();)
677                    {
678                            OntProperty prop = (OntProperty)iter.next();
679                            StmtIterator si = ONT_MODEL.listStatements(prop, RDFS.domain, ontR);
680                            if(si.hasNext())
681                                    list.add(prop.getURI());
682                    }
683                    return list.iterator();
684            }
685            
686            /**
687             * Lists the classes on the range of a property
688             * @param property property user is asking for its range
689             */
690            public Iterator<String> listPropertyRange(String property)
691            {
692                    OntProperty prop = obtainOntProperty(property);
693                    return new ToStringIterator<String>(prop.listRange());
694            }
695            
696            /**
697             * Lists the instances that are the values of a property of an instance.
698             * @param instance instance origin of the property
699             * @param property property 
700             */
701            public Iterator<String> listPropertyValue(String instance, String property)
702            {
703                    OntResource ontI = obtainOntResource(instance);
704                    Property prop = obtainOntProperty(property);
705                    return new ToStringIterator<String>(ontI.listPropertyValues(prop));
706            }
707            
708            /**
709             * Lists the properties of an instance
710             * @param instance source of the properties
711             */
712            public Iterator<String> listInstanceProperties(String instance)
713            {
714                    ArrayList<String> list = new ArrayList<String>();
715                    OntResource ontI = obtainOntResource(instance);
716                    for(StmtIterator props = ontI.listProperties(); props.hasNext();)
717                            list.add(props.nextStatement().getPredicate().toString());
718                    return list.iterator();
719            }
720            
721            /**
722             * Returns the properties with their corresponding values of an instance. The properties and values parameter are cleared.
723             * They are used to return the properties and values. property[i] has value values[i].
724             * @param instance source of the properties
725             * @param properties Array containing the name of the properties
726             * @param values Array containing the value of the property
727             */
728            public void listInstancePropertiesValues(String instance, List<String> properties, List<String> values)
729            {
730                    properties.clear();
731                    values.clear();
732                    
733                    
734                    OntResource ontI = obtainOntResource(instance);
735                    for(StmtIterator props = ontI.listProperties(); props.hasNext();)
736                    {
737                            Statement stmt = props.nextStatement();
738                            if(getShortName(stmt.getPredicate().toString()).equals("rdf:type"))
739                                    continue;
740                            properties.add(stmt.getPredicate().toString());
741                            values.add(stmt.getObject().toString());        
742                    }
743            }
744            
745            /**************************************************************/
746            /*             Names and URIs management                      */
747            /**************************************************************/
748            
749            /**
750             * Returns the short form of an URI.
751             */
752            public String getShortName(String URI)
753            {
754                    String sname = ONT_MODEL.shortForm(URI);
755                    if(sname.startsWith(":"))
756                            return sname.substring(1);
757                    else
758                            return sname;
759            }
760            
761            /**
762             * Returns the long URI form of a short name
763             */
764            public String getURI(String shortName)
765            {
766                    String qname = ONT_MODEL.expandPrefix(shortName);
767                    if( ONT_MODEL.getOntResource(qname) != null)
768                            return qname;
769                    else
770                        return BASE_NS + shortName;
771            }
772            
773            public String getThingURI()
774            {
775                    return ONT_MODEL.expandPrefix("owl:Thing");
776            }
777            
778            /**************************************************************/
779            /*              Existence Functions                           */
780            /**************************************************************/
781            
782            /**
783             * Returns if a class exists
784             */
785            public boolean existsClass(String name)
786            {
787                    return obtainOntClass(name) != null;
788            }
789            
790            /**
791             * Returns if a property exists
792             */
793            public boolean existsProperty(String name)
794            {
795                    return obtainOntProperty(name) != null;
796            }
797            
798            /**
799             * Returns if an instance exists
800             */
801            public boolean existsInstance(String name)
802            {
803                    return obtainOntResource(name) != null;
804            }
805    
806            /**
807             * Returns if an instance of a concrete class exists
808             */
809            public boolean existsInstance(String instanceName, String className)
810            {
811                    if(!existsInstance(instanceName))
812                            return false;
813                    return isInstanceOf(instanceName, className);
814                    
815            }
816            
817            /**************************************************************/
818            /*                Insertion functions                         */
819            /**************************************************************/        
820            
821            /**
822             * Create a new class in the ontology. The className must not exist.
823             * @param className Class to create
824             */
825            public void createClass(String className)
826            {
827                    String longName;
828                    if(className.contains("#"))
829                            longName = className;
830                    if(className.contains(":"))
831                            longName= ONT_MODEL.expandPrefix(className);
832                    else
833                            longName = BASE_NS + className;
834                    
835                    ONT_MODEL.createClass(longName);
836            }
837            
838            /**
839             * Sets a class as subclass of other.
840             * @param subClass
841             * @param superClass
842             */
843            public void setSubClass(String subClass, String superClass)
844            {
845                    OntClass _sub   = obtainOntClass(subClass);
846                    OntClass _super = obtainOntClass(superClass);
847                    
848                    _sub.setSuperClass(_super);
849            }
850            
851            /**
852             * Creates a new instance of a class. The class must exist but the instance must not.
853             * @param className
854             * @param instanceName
855             */
856            public void createInstance(String className, String instanceName)
857            {
858                    
859                    OntClass c = obtainOntClass(className);
860                    
861                    String longName;
862                    if(instanceName.contains("#"))
863                            longName = instanceName;
864                    if(instanceName.contains(":"))
865                            longName= ONT_MODEL.expandPrefix(instanceName);
866                    else
867                            longName = BASE_NS + instanceName;
868                    
869                    c.createIndividual(longName);
870            }
871            
872            /**
873             * Creates an ontology property between two instances. An ontology property ranges over instances.
874             * If there is other property with the same name this method creates a new one. 
875             * If you want to modify an existing property use the modifyOntProperty() method.
876             * @param sourceInstance
877             * @param propertyName
878             * @param destInstance
879             */
880            public void createOntProperty(String sourceInstance, String propertyName, String destInstance)
881            {
882                    OntResource si = this.obtainOntResource(sourceInstance);
883                    OntResource di = this.obtainOntResource(destInstance);
884                    Property  prop = this.obtainOntProperty(propertyName); 
885                    si.addProperty(prop, di);
886            }
887            
888            /**
889             * Modifies the range of an ontology property. If the property does not exist it creates a new one.
890             * An ontology property ranges over instances.
891             * @param sourceInstance
892             * @param propertyName
893             * @param destInstance
894             */
895            public void modifyOntProperty(String sourceInstance, String propertyName, String destInstance)
896            {
897                    OntResource si = this.obtainOntResource(sourceInstance);
898                    OntResource di = this.obtainOntResource(destInstance);
899                    Property  prop = this.obtainOntProperty(propertyName); 
900                    si.setPropertyValue(prop, di);
901            }
902            
903            /**
904             * Creates an dataType property between two instances. An ontology property ranges over XML-Schema datatypes.
905             * The method tries to find the proper datatype for the value object. (If this fails use the explicit datatyped method).
906             * @param sourceInstance
907             * @param propertyName
908             * @param value The value of the property. The method tries to find the proper datatype for this object.
909             */
910            public void createDataTypeProperty(String sourceInstance, String propertyName, Object value)
911            {
912                    OntResource si = this.obtainOntResource(sourceInstance);
913                    Property  prop = this.obtainOntProperty(propertyName);
914                    si.addProperty(prop, ONT_MODEL.createTypedLiteral(value));      
915            }
916            
917            /**
918             * Creates an dataType property between two instances. An ontology property ranges over XML-Schema datatypes.
919             * The datatype of the value is explicitely defined.
920             * @param sourceInstance
921             * @param propertyName
922             * @param value The value of the property.
923             * @param valueDataType DataType of the value
924             */
925            public void createDataTypeProperty(String sourceInstance, String propertyName, String value, String valueDataType)
926            {
927                    OntResource si = this.obtainOntResource(sourceInstance);
928                    Property  prop = this.obtainOntProperty(propertyName);
929                    si.addProperty(prop, ONT_MODEL.createTypedLiteral(value, valueDataType));       
930            }
931            
932            /**************************************************************/
933            /*                 Delete Functions                          */
934            /**************************************************************/
935            
936            /**
937             * Deletes a class or instance from the model, including all of the properties that have this resource as domain or range.
938             * @param name resource to delete
939             */
940            public void delete(String name)
941            {
942                    OntResource res = this.obtainOntResource(name);
943                    res.remove();
944            }
945            
946            /**************************************************************/
947            /*                Persistence Functions                       */
948            /**************************************************************/
949            
950            /**
951             * Saves the ontology (without imported ontologies data) into a file.
952             * @param fileName file path for saving the ontology
953             */
954            public void save(String fileName)
955            {
956                    try {
957                            FileWriter fw = new FileWriter(fileName);
958                            save(fw);
959                    } catch (Exception e) {
960                            org.apache.commons.logging.LogFactory.getLog(this.getClass()).error(e);
961                    }
962            }
963            
964            public void save(FileWriter fw)
965            {
966                    try {
967                            ONT_MODEL.write(fw,"RDF/XML-ABBREV");
968                            org.apache.commons.logging.LogFactory.getLog(this.getClass()).info( "Saving ontology.");
969                    } catch (Exception e) {
970                            org.apache.commons.logging.LogFactory.getLog(this.getClass()).error(e);
971                    }
972                    
973            }
974            
975            
976            /**************************************************************/
977            /*               Ontology Validation Methods                  */
978            /**************************************************************/
979    
980            /**
981             * Computes if the current ontology is valid. (Created by: Antonio Sanchez)
982             * @param ignorewarnings This param indicates if the method must return true if warnings are found
983             */
984            public boolean isValid(boolean ignorewarnings) {
985                    ValidityReport vr = ONT_MODEL.validate();
986                    if(ignorewarnings)
987                            return vr.isValid();
988                    else
989                            return vr.isClean();
990            }
991            
992            /**
993             * Computes if the current ontology is valid and returns a list of warnings and errors. (Created by: Antonio Sanchez)
994             */
995            public Iterator<String> validate() {
996                    ValidityReport vr = ONT_MODEL.validate();
997                    
998                    Collection<String> reports = new ArrayList<String>();
999                    
1000                    for(Iterator riter = vr.getReports(); riter.hasNext();)
1001                    {
1002                            ValidityReport.Report r = (ValidityReport.Report)riter.next();
1003                            String msg ="";
1004                            if(r.isError())
1005                                    msg += "[ERROR]";
1006                            else
1007                                    msg += "[WARNING]";
1008                            msg+="["+r.getType()+"]";
1009                            msg+=r.getDescription();
1010                            reports.add(msg);
1011                    }
1012                    
1013                    return reports.iterator();
1014            }
1015            
1016            /**************************************************************/
1017            /*                  Extension Method                          */
1018            /**************************************************************/
1019            
1020            /**
1021             * This method allows extensions using the
1022             * Ontology Model used internally by OntoBridge
1023             */
1024            public OntModel getModel()
1025            {
1026                    return this.ONT_MODEL;
1027            }
1028            
1029            
1030            /**************************************************************/
1031            /*                Private functions                           */
1032            /**************************************************************/
1033            
1034            /**
1035             * Returns the JENA OntClass referenced by the string.
1036             * This method checks if the string is a short or long URI.
1037             */
1038            private OntClass obtainOntClass(String ontClass)
1039            {
1040                    OntResource ontR = obtainOntResource(ontClass);
1041                    if(ontR != null)
1042                            if(ontR.canAs(OntClass.class))
1043                                    return ontR.asClass();
1044                    return null;    
1045            }
1046            
1047            
1048            /**
1049             * Returns the JENA OntProperty referenced by the string.
1050             * This method checks if the string is a short or long URI.
1051             */
1052            private OntProperty obtainOntProperty(String ontProperty)
1053            {
1054                    OntResource ontR = obtainOntResource(ontProperty);
1055                    if(ontR != null)
1056                            if(ontR.isProperty())
1057                            {
1058                                    if(ontR.isDatatypeProperty())
1059                                            return ontR.asDatatypeProperty();
1060                                    return ontR.asProperty();
1061                            }
1062                    return null;    
1063            }
1064            
1065            /**
1066             * Returns the JENA OntResource referenced by the string.
1067             * This method checks if the string is a short or long URI.
1068             */
1069            private OntResource obtainOntResource(String ontRes)
1070            {
1071                    OntResource ontR;
1072                    try {
1073                            ontR = ONT_MODEL.getOntResource(ontRes);
1074                            if(ontR != null)
1075                                    return ontR;
1076                    } catch (Exception e) {
1077                    }
1078                    
1079                    try {
1080                            String qname = ONT_MODEL.expandPrefix(ontRes);
1081                            ontR = ONT_MODEL.getOntResource(qname);
1082                            if(ontR != null)
1083                                    return ontR;
1084                    } catch (Exception e) {
1085                    }       
1086                    
1087                    try {
1088                            return ontR = ONT_MODEL.getOntResource(BASE_NS + ontRes);
1089                    } catch (Exception e) {
1090                    }
1091                    
1092                    org.apache.commons.logging.LogFactory.getLog(this.getClass()).error("Ontology Resource not found: "+ ontRes);
1093                    return null;
1094            }
1095            
1096    }