001 /***************************************************************************/
002 /* Copyright (C) 2010-2011, Sebastian Hellmann */
003 /* Note: If you need parts of NLP2RDF in another licence due to licence */
004 /* incompatibility, please mail hellmann@informatik.uni-leipzig.de */
005 /* */
006 /* This file is part of NLP2RDF. */
007 /* */
008 /* NLP2RDF is free software; you can redistribute it and/or modify */
009 /* it under the terms of the GNU General Public License as published by */
010 /* the Free Software Foundation; either version 3 of the License, or */
011 /* (at your option) any later version. */
012 /* */
013 /* NLP2RDF is distributed in the hope that it will be useful, */
014 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
015 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
016 /* GNU General Public License for more details. */
017 /* */
018 /* You should have received a copy of the GNU General Public License */
019 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
020 /***************************************************************************/
021
022 package org.nlp2rdf.ontology.olia;
023
024 import com.hp.hpl.jena.ontology.*;
025 import com.hp.hpl.jena.rdf.model.*;
026 import com.hp.hpl.jena.util.iterator.ExtendedIterator;
027 import com.hp.hpl.jena.vocabulary.RDFS;
028 import org.mindswap.pellet.jena.PelletReasonerFactory;
029 import org.nlp2rdf.ontology.ClassIndexer;
030 import org.nlp2rdf.ontology.OntologyLoader;
031 import org.slf4j.Logger;
032 import org.slf4j.LoggerFactory;
033
034 import java.util.*;
035
036 /**
037 * @author Sebastian Hellmann - http://bis.informatik.uni-leipzig.de/SebastianHellmann
038 */
039 public class OLiAOntology {
040 private static Logger log = LoggerFactory.getLogger(OLiAOntology.class);
041 public static String hasTagURI = "http://purl.org/olia/system.owl#hasTag";
042
043 private final String ontologyUrl;
044 private final OntModel model;
045 private final ClassIndexer classIndexer = new ClassIndexer();
046 private final Map<String, Individual> tagToIndividualMap = new HashMap<String, Individual>();
047 private final DatatypeProperty hasTag;
048
049 public OLiAOntology(String ontologyUrl, OntologyLoader ontologyLoader) {
050 this.ontologyUrl = ontologyUrl;
051 this.model = ontologyLoader.loadOntology(ontologyUrl, PelletReasonerFactory.THE_SPEC);
052
053 ontologyLoader.loadImports(model);
054 log.info("finished loading imports");
055 classIndexer.index(model);
056 log.info("finished indexing");
057
058 hasTag = model.getDatatypeProperty(hasTagURI);
059 assert (hasTag != null) : "hasTag was null";
060
061 fillMap();
062 }
063
064
065 public String getIndividualURIForTag(String tag) {
066 Individual ind = tagToIndividualMap.get(tag);
067 if (ind == null) {
068 log.error("Individual for tag " + tag + " not found returning null, this indicates a mismatch between OLiA and the annotations actually used: " + ontologyUrl);
069 return null;
070 } else {
071 return ind.getURI();
072 }
073 }
074
075
076 public Set<String> getClassURIsForTag(String tag) {
077 Individual ind = tagToIndividualMap.get(tag);
078 log.info("Tag: " + tag + " is matching Individual: " + ind);
079 if (ind == null) {
080 return new HashSet<String>();
081 } else {
082 Set<String> s = new HashSet<String>();
083 for (ExtendedIterator<OntClass> it = ind.listOntClasses(true); it.hasNext(); ) {
084 OntClass oc = it.next();
085 if (!oc.isAnon()) {
086 s.add(oc.getURI());
087 log.debug("found class " + oc + " for ind: " + ind);
088 } else {
089 log.debug("skipping anon " + oc + " for ind: " + ind);
090 }
091 }
092 log.info("returning classes: " + s);
093 return s;
094 }
095 }
096
097
098 public OntModel getHierarchy(String classURI) {
099 return classIndexer.getHierarchyForClassURI(classURI);
100 }
101
102 private void fillMap() {
103 StringBuilder debug = new StringBuilder();
104 debug.append(ontologyUrl + " - Filling Tag2Uri Map\n");
105
106 //get all individuals of the anotation model
107 for (ExtendedIterator<Individual> it = model.listIndividuals(); it.hasNext(); ) {
108 Individual ind = it.next();
109
110
111 if (ind.isAnon()) {
112 log.error(ind + " was a blanknode, SKIPPING it");
113 continue;
114 }
115
116 //get the tag (should be exactly one)
117 List<RDFNode> l = ind.listPropertyValues(hasTag).toList();
118 if (l.size() == 1) {
119 Literal tag = l.get(0).asLiteral();
120 Individual previous = null;
121 //put it in the map, check, if there is something in there already
122 if ((previous = tagToIndividualMap.put(tag.getLexicalForm(), ind)) != null) {
123 //then something smells
124 log.error(ind.toString() + " has an ambigue tag: " + tag.toString() + " previous " + previous.getURI() + " " + ontologyUrl);
125 }
126
127 debug.append("[ " + tag.getLexicalForm() + " -> " + ind.getURI() + " ]\n");
128 } else if (l.size() == 0) {
129 //skip bnodes
130 log.error("Action: SKIPPING");
131 continue;
132 } else if (l.size() != 1) {
133 //then something smells
134 log.error(ind.toString() + " has not exactly one " + hasTag + " property value, but " + l.size() + " " + ontologyUrl);
135 for (RDFNode n : l) {
136 log.error("" + n);
137 }
138 }
139
140 }
141 log.trace(debug.toString());
142 log.debug("total tags: " + tagToIndividualMap.size());
143 }
144
145 public static void classHierarchy2PropertyHierarchy(OntModel hierarchy, OntModel out, String allowedNamespace) {
146 for (StmtIterator stm = hierarchy.listStatements(null, RDFS.subClassOf, (RDFNode) null); stm.hasNext(); ) {
147 Statement current = stm.nextStatement();
148 Resource subject = current.getSubject();
149
150 if (!(subject.getURI().startsWith(allowedNamespace))) {
151 continue;
152 }
153 if (subject.isAnon()) {
154 continue;
155 }
156 if (current.getObject().isAnon()) {
157 continue;
158 }
159 String objectURI = current.getObject().asResource().getURI();
160 if (!(objectURI.startsWith(allowedNamespace))) {
161 continue;
162 }
163 ObjectProperty op = out.createObjectProperty(subject.getURI());
164 op.addSuperProperty(out.createObjectProperty(objectURI));
165 }
166 }
167
168 public String getOntologyUrl() {
169 return ontologyUrl;
170 }
171
172 public Map<String, Individual> getTagToIndividualMap() {
173 return tagToIndividualMap;
174 }
175 }