001    /**
002     * Copyright (C) 2007-2011, Jens Lehmann
003     *
004     * This file is part of DL-Learner.
005     *
006     * DL-Learner is free software; you can redistribute it and/or modify
007     * it under the terms of the GNU General Public License as published by
008     * the Free Software Foundation; either version 3 of the License, or
009     * (at your option) any later version.
010     *
011     * DL-Learner is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014     * GNU General Public License for more details.
015     *
016     * You should have received a copy of the GNU General Public License
017     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
018     */
019    
020    package org.dllearner.kb.extraction;
021    
022    import java.net.URI;
023    import java.util.ArrayList;
024    import java.util.List;
025    import java.util.SortedSet;
026    import java.util.TreeSet;
027    
028    import org.apache.log4j.Logger;
029    import org.dllearner.kb.aquisitors.TupleAquisitor;
030    import org.dllearner.kb.manipulator.Manipulator;
031    import org.dllearner.utilities.datastructures.RDFNodeTuple;
032    import org.dllearner.utilities.owl.OWLVocabulary;
033    import org.semanticweb.owlapi.model.OWLAnnotation;
034    import org.semanticweb.owlapi.model.OWLAxiom;
035    import org.semanticweb.owlapi.model.OWLClass;
036    import org.semanticweb.owlapi.model.OWLDataFactory;
037    import org.semanticweb.owlapi.model.OWLDataProperty;
038    import org.semanticweb.owlapi.model.OWLIndividual;
039    import org.semanticweb.owlapi.model.OWLNamedIndividual;
040    import org.semanticweb.owlapi.model.OWLObjectProperty;
041    
042    import com.hp.hpl.jena.rdf.model.Literal;
043    
044    /**
045     * A node in the graph that is an instance.
046     * 
047     * @author Sebastian Hellmann
048     * 
049     */
050    public class InstanceNode extends Node {
051            
052            private static Logger logger = Logger
053                    .getLogger(InstanceNode.class);
054    
055            private List<ClassNode> classes = new ArrayList<ClassNode>();
056            //SortedSet<StringTuple> datatypes = new TreeSet<StringTuple>();
057            private List<ObjectPropertyNode> objectProperties = new ArrayList<ObjectPropertyNode>();
058            private List<DatatypePropertyNode> datatypeProperties = new ArrayList<DatatypePropertyNode>();
059    
060            public InstanceNode(String uri) {
061                    super(uri);
062            }
063    
064            // expands all directly connected nodes
065            @Override
066            public List<Node> expand(TupleAquisitor tupelAquisitor, Manipulator manipulator) {
067    
068                    SortedSet<RDFNodeTuple> newTuples = tupelAquisitor.getTupelForResource(uri);
069                    // see Manipulator
070                    newTuples = manipulator.manipulate(this, newTuples);
071                    
072                    List<Node> newNodes = new ArrayList<Node>();
073    
074                    Node tmp;
075                    for (RDFNodeTuple tuple : newTuples) {
076                            
077                            if((tmp = processTuple(tuple))!= null) {
078                                    newNodes.add(tmp);
079                            }                       
080                    }//endfor
081                    expanded = true;
082                    return newNodes;
083            }
084            
085            /**
086             * estimates the type of the retrieved tuple
087             * @param tuple
088             * @return
089             */
090            public Node processTuple( RDFNodeTuple tuple) {
091                    
092                    try {
093                            
094                            //Literal nodes 
095                            if(tuple.b.isLiteral()) {
096                                    datatypeProperties.add(new DatatypePropertyNode(tuple.a.toString(), this, new LiteralNode(tuple.b) ));
097                                    return null;
098                            //Blank nodes 
099                            }else if(tuple.b.isAnon()){
100    //                              @SuppressWarnings("unused")
101    //                              RDFBlankNode n = (RDFBlankNode) tuple.b;
102                                    if(tuple.a.toString().equals(OWLVocabulary.RDF_TYPE)){
103                                            logger.warn("blanknodes for instances not implemented yet (rare frequency). e.g. (instance rdf:type (A and B)"+" " + this+ " in tuple "+tuple);
104                                    }
105                                    else{
106                                            logger.warn("encountered Bnode in InstanceNode "+ this +" in tuple " + tuple);
107                                            logger.warn("In OWL-DL the subject of an object property assertion must be an instance (not a class). Triple will be ignored.");
108                                    }
109                                    return null;
110                            
111                            // basically : if p is rdf:type then o is a class
112                            // else it is an instance
113                            // Class Node 
114                            }else if (tuple.a.toString().equals(OWLVocabulary.RDF_TYPE)) {
115                                    try{
116                                            URI.create(tuple.b.toString());
117                                    }catch (Exception e) {
118                                            logger.warn("uri "+tuple.b.toString()+" is not a valid uri for a class, ignoring");
119                                            return null;
120                                    }
121                                    
122                                    ClassNode tmp = new ClassNode(tuple.b.toString());
123                                    classes.add(tmp);
124                                    return tmp;
125                            // instance node
126                            } else {
127                                    
128                                    try{
129                                            URI.create(tuple.b.toString());
130                                    }catch (Exception e) {
131                                            logger.warn("uri "+tuple.b.toString()+" for objectproperty: "+tuple.a.toString() +" is not valid, ignoring");
132                                            return null;
133                                    }
134                                    InstanceNode tmp = new InstanceNode(tuple.b.toString());
135                                    objectProperties.add(new ObjectPropertyNode(tuple.a.toString(), this, tmp));
136                                    return tmp;
137                            }
138                    } catch (Exception e) {
139                            tail("process tuple: problem with: " + tuple);
140                            e.printStackTrace();
141                            return null;
142                    }
143            }
144            
145            // gets the types for properties recursively
146            @Override
147            public List<BlankNode> expandProperties(TupleAquisitor tupelAquisitor, Manipulator manipulator, boolean dissolveBlankNodes) {
148                    List<BlankNode> ret =  new ArrayList<BlankNode>();
149                    for (ObjectPropertyNode one : objectProperties) {
150                            ret.addAll(one.expandProperties(tupelAquisitor, manipulator, dissolveBlankNodes));
151                    }
152                    
153                    for (DatatypePropertyNode one : datatypeProperties) {
154                            ret.addAll(one.expandProperties(tupelAquisitor, manipulator, dissolveBlankNodes));
155                    }
156                    return ret;
157    
158            }
159    
160            @Override
161            public SortedSet<String> toNTriple() {
162                    SortedSet<String> returnSet = new TreeSet<String>();
163                    returnSet.add("<" + uri + "><" + OWLVocabulary.RDF_TYPE + "><" + OWLVocabulary.OWL_THING + ">.");
164                    for (ClassNode one : classes) {
165                            returnSet.add("<" + uri + "><" + OWLVocabulary.RDF_TYPE + "><" + one.getURIString() + ">.");
166                            returnSet.addAll(one.toNTriple());
167                    }
168                    for (ObjectPropertyNode one : objectProperties) {
169                            returnSet.add("<" + uri + "><" + one.getURIString() + "><" + one.getBPart().getURIString()
170                                            + ">.");
171                            returnSet.addAll(one.toNTriple());
172                            returnSet.addAll(one.getBPart().toNTriple());
173                    }
174                    
175                    for (DatatypePropertyNode one : datatypeProperties) {
176                            returnSet.add("<" + uri + "><" + one.getURIString() + "> " + one.getNTripleFormOfB()
177                                            + " .");
178                    }
179    
180                    return returnSet;
181            }
182            
183            @Override
184            public void toOWLOntology( OWLAPIOntologyCollector owlAPIOntologyCollector){
185                    OWLDataFactory factory =  owlAPIOntologyCollector.getFactory();
186            
187                    
188                    OWLNamedIndividual me = factory.getOWLNamedIndividual(getIRI());
189                    
190                    for (ClassNode one : classes) {
191                            //create Axiom
192                            OWLClass c = factory.getOWLClass(one.getIRI());
193                            OWLAxiom ax = factory.getOWLClassAssertionAxiom(c, me);
194                            //collect
195                            owlAPIOntologyCollector.addAxiom(ax);
196                            //handover
197                            one.toOWLOntology(owlAPIOntologyCollector);
198                    }
199                    for (ObjectPropertyNode one : objectProperties) {
200                            OWLAxiom ax = null;
201                            if(one.getURIString().equals(OWLVocabulary.OWL_DIFFERENT_FROM)){
202                                    OWLIndividual o = factory.getOWLNamedIndividual(one.getBPart().getIRI());
203                                    
204                                    ax = factory.getOWLDifferentIndividualsAxiom(new OWLIndividual[]{me,o});
205                            }else{
206                            
207                                    //create axiom
208                                    OWLIndividual o = factory.getOWLNamedIndividual(one.getBPart().getIRI());
209                                    OWLObjectProperty p = factory.getOWLObjectProperty(one.getIRI());
210                                    ax = factory.getOWLObjectPropertyAssertionAxiom(p, me, o);
211                            }
212                            //collect
213                            owlAPIOntologyCollector.addAxiom(ax);
214                            
215                            //handover
216                            one.toOWLOntology(owlAPIOntologyCollector);
217                            one.getBPart().toOWLOntology(owlAPIOntologyCollector);
218                    }
219                    
220                    for (DatatypePropertyNode one : datatypeProperties) {
221                            OWLDataProperty p = factory.getOWLDataProperty(one.getIRI());
222                            Literal ln = one.getBPart().getLiteral();
223                            
224                            if(one.getURIString().equals(OWLVocabulary.RDFS_COMMENT)){
225                                    //skip
226                                    //OWLCommentAnnotation comment = factory.getOWL(one.b.toString());
227                                    //owlAPIOntologyCollector.addAxiom(factory.getOWLEntityAnnotationAxiom(me, label));
228                            }else if(one.getURIString().equals(OWLVocabulary.RDFS_LABEL)){
229                                    OWLAnnotation annoLabel = factory.getOWLAnnotation(factory.getRDFSLabel(), factory.getOWLStringLiteral(ln.getString()));
230                                    OWLAxiom ax = factory.getOWLAnnotationAssertionAxiom(me.getIRI(), annoLabel);
231                                    owlAPIOntologyCollector.addAxiom(ax);
232                            }else{
233                            
234                            try{
235                                    
236                                    if(one.getBPart().isFloat()){
237                                            owlAPIOntologyCollector.addAxiom(
238                                                            factory.getOWLDataPropertyAssertionAxiom(p, me, ln.getFloat()));
239                                    } else if(one.getBPart().isDouble()){
240                                            owlAPIOntologyCollector.addAxiom(
241                                                            factory.getOWLDataPropertyAssertionAxiom(p, me, ln.getDouble()));
242                                    } else if(one.getBPart().isInt()){
243                                            owlAPIOntologyCollector.addAxiom(
244                                                            factory.getOWLDataPropertyAssertionAxiom(p, me, ln.getInt()));
245                                    } else if(one.getBPart().isBoolean()){
246                                            owlAPIOntologyCollector.addAxiom(
247                                                            factory.getOWLDataPropertyAssertionAxiom(p, me, ln.getBoolean()));
248                                    }else if(one.getBPart().isString()){
249                                            //System.out.println(ln.getString()+" "+one.getBPart().isBoolean());
250                                            owlAPIOntologyCollector.addAxiom(
251                                            factory.getOWLDataPropertyAssertionAxiom(p, me, ln.getString()));
252                                            
253                                    }
254                                    
255                                    else {
256                                            tail("strange dataytype in ontology conversion" + one.getURIString()+" datatype: "+one.getBPart().getNTripleForm());
257                                    }
258                                    
259                                    //handover
260                                    one.toOWLOntology(owlAPIOntologyCollector);
261                            
262                            }catch (Exception e) {
263                                    e.printStackTrace();
264                                    tail("strange dataytype in ontology conversion" + one.getURIString()+" datatype: "+one.getBPart().getNTripleForm());
265                            }
266                            }
267                            //factory.getOWLDataPropertyAssertionAxiom()
268                            //returnSet.add("<" + uri + "><" + one.getURI() + "> " + one.getNTripleFormOfB()
269                            //              + " .");
270                    }
271            }
272    
273    
274            public List<ObjectPropertyNode> getObjectProperties() {
275                    return objectProperties;
276            }
277            
278            public List<DatatypePropertyNode> getDatatypePropertyNode() {
279                    return datatypeProperties;
280            }
281            
282            
283    
284    }