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