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 }