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.util.ArrayList;
022import java.util.List;
023import java.util.SortedSet;
024import java.util.TreeSet;
025
026import org.apache.log4j.Logger;
027import org.dllearner.kb.aquisitors.RDFBlankNode;
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.OWLClassExpression;
036import org.semanticweb.owlapi.model.OWLDataFactory;
037
038/**
039 * Is a node in the graph, that is a class.
040 * 
041 * @author Sebastian Hellmann
042 */
043public class ClassNode extends Node {
044        
045        private static Logger logger = Logger
046                .getLogger(ClassNode.class);
047        
048        List<ObjectPropertyNode> classProperties = new ArrayList<>();
049        List<DatatypePropertyNode> datatypeProperties = new ArrayList<>();
050        List<BlankNode> blankNodes = new ArrayList<>();
051        
052        public ClassNode(String uri) {
053                super(uri);
054        }
055
056        // expands all directly connected nodes
057        @Override
058        public List<Node> expand(TupleAquisitor tupelAquisitor, Manipulator manipulator) {
059
060                SortedSet<RDFNodeTuple> newTuples = tupelAquisitor.getTupelForResource(this.uri);
061                // see manipulator
062                newTuples = manipulator.manipulate(this, newTuples);
063                        
064                List<Node> newNodes = new ArrayList<>();
065                Node tmp;
066                for (RDFNodeTuple tuple : newTuples) {
067                        if((tmp = processTuple(tuple,tupelAquisitor.isDissolveBlankNodes()))!= null) {
068                                newNodes.add(tmp);
069                        }               
070                }
071                return newNodes;
072        }
073        
074        private Node processTuple( RDFNodeTuple tuple, boolean dissolveBlankNodes) {
075                
076                try {
077                        String property = tuple.a.toString();
078                        if(tuple.b.isLiteral()) {
079                                datatypeProperties.add(new DatatypePropertyNode(tuple.a.toString(), this, new LiteralNode(tuple.b) ));
080                                return null;
081                        }else if(tuple.b.isAnon()){
082                                if(dissolveBlankNodes){
083                                        RDFBlankNode n = (RDFBlankNode) tuple.b;
084                                        BlankNode tmp = new BlankNode( n, tuple.a.toString()); 
085                                        //add it to the graph
086                                        blankNodes.add(tmp);
087                                        //return tmp;
088                                        return tmp;
089                                }else{
090                                        //do nothing
091                                        return null;
092                                }
093                         // substitute rdf:type with owl:subclassof
094                        }else if (property.equals(OWLVocabulary.RDF_TYPE) || 
095                                        OWLVocabulary.isStringSubClassVocab(property)) {
096                                ClassNode tmp = new ClassNode(tuple.b.toString());
097                                classProperties.add(new ObjectPropertyNode( OWLVocabulary.RDFS_SUBCLASS_OF, this,       tmp));
098                                return tmp;
099                        } else {
100                                // further expansion stops here
101                                ClassNode tmp = new ClassNode(tuple.b.toString());
102                                classProperties.add(new ObjectPropertyNode(tuple.a.toString(), this, tmp));
103                                return tmp; //is missing on purpose
104                        }
105                } catch (Exception e) {
106                        logger.warn("Problem with: " + this + " in tuple " + tuple);
107                        e.printStackTrace();
108                        
109                } 
110                return null;
111        }
112
113        // gets the types for properties recursively
114        @Override
115        public List<BlankNode>  expandProperties(TupleAquisitor tupelAquisitor, Manipulator manipulator, boolean dissolveBlankNodes) {
116                return new ArrayList<>();
117        }
118        
119
120
121        /*
122         * (non-Javadoc)
123         * 
124         * @see org.dllearner.kb.sparql.datastructure.Node#toNTriple()
125         */
126        @Override
127        public SortedSet<String> toNTriple() {
128                SortedSet<String> returnSet = new TreeSet<>();
129                String subject = getNTripleForm();
130                returnSet.add(subject+"<" + OWLVocabulary.RDF_TYPE + "><" + OWLVocabulary.OWL_CLASS + ">.");
131
132                for (ObjectPropertyNode one : classProperties) {
133                        returnSet.add(subject + one.getNTripleForm() + 
134                                        one.getBPart().getNTripleForm()+" .");
135                        returnSet.addAll(one.getBPart().toNTriple());
136                }
137                for (DatatypePropertyNode one : datatypeProperties) {
138                        returnSet.add(subject+ one.getNTripleForm() + one.getNTripleFormOfB()
139                                        + " .");
140                }
141
142                return returnSet;
143        }
144        
145        @Override
146        public void toOWLOntology( OWLAPIOntologyCollector owlAPIOntologyCollector){
147                try{
148                OWLDataFactory factory =  owlAPIOntologyCollector.getFactory();
149                
150                OWLClass me =factory.getOWLClass(getIRI());
151                for (ObjectPropertyNode one : classProperties) {
152                        OWLClass c = factory.getOWLClass(one.getBPart().getIRI());
153                        if(OWLVocabulary.isStringSubClassVocab(one.getURIString())){
154                                owlAPIOntologyCollector.addAxiom(factory.getOWLSubClassOfAxiom(me, c));
155                        }else if(one.getURIString().equals(OWLVocabulary.OWL_DISJOINT_WITH)){
156                                owlAPIOntologyCollector.addAxiom(factory.getOWLDisjointClassesAxiom(me, c));
157                        }else if(one.getURIString().equals(OWLVocabulary.OWL_EQUIVALENT_CLASS)){
158                                owlAPIOntologyCollector.addAxiom(factory.getOWLEquivalentClassesAxiom(me, c));
159                        }else if(one.getURIString().equals(OWLVocabulary.RDFS_IS_DEFINED_BY)){
160                                logger.warn("IGNORING: "+OWLVocabulary.RDFS_IS_DEFINED_BY);
161                                continue;
162                        }else {
163                                tail(true, "in ontology conversion"+" object property is: "+one.getURIString()+" connected with: "+one.getBPart().getURIString());
164                                continue;
165                        }
166                        one.getBPart().toOWLOntology(owlAPIOntologyCollector);
167                }
168                for (DatatypePropertyNode one : datatypeProperties) {
169                        //FIXME add languages
170                        // watch for tail
171                        switch (one.getURIString()) {
172                                case OWLVocabulary.RDFS_COMMENT: {
173                                        OWLAnnotation annoComment = factory.getOWLAnnotation(factory.getRDFSComment(), factory.getOWLLiteral(one.getBPart().getLiteral().getString()));
174                                        OWLAxiom ax = factory.getOWLAnnotationAssertionAxiom(me.getIRI(), annoComment);
175                                        owlAPIOntologyCollector.addAxiom(ax);
176
177                                        break;
178                                }
179                                case OWLVocabulary.RDFS_LABEL: {
180                                        OWLAnnotation annoLabel = factory.getOWLAnnotation(factory.getRDFSLabel(), factory.getOWLLiteral(one.getBPart().getLiteral().getString()));
181                                        OWLAxiom ax = factory.getOWLAnnotationAssertionAxiom(me.getIRI(), annoLabel);
182                                        owlAPIOntologyCollector.addAxiom(ax);
183                                        break;
184                                }
185                                default:
186                                        tail(true, "in ontology conversion: no other datatypes, but annotation is allowed for classes." + " data property is: " + one.getURIString() + " connected with: " + one.getBPart().getNTripleForm());
187
188                                        break;
189                        }
190                
191                }
192                for (BlankNode bn : blankNodes) {
193                        OWLClassExpression target = bn.getAnonymousClass(owlAPIOntologyCollector);
194                        
195                        if(OWLVocabulary.isStringSubClassVocab(bn.getInBoundEdge())){
196                                owlAPIOntologyCollector.addAxiom(factory.getOWLSubClassOfAxiom(me, target));
197                        }else if(bn.getInBoundEdge().equals(OWLVocabulary.OWL_DISJOINT_WITH)){
198                                owlAPIOntologyCollector.addAxiom(factory.getOWLDisjointClassesAxiom(me, target));
199                        }else if(bn.getInBoundEdge().equals(OWLVocabulary.OWL_EQUIVALENT_CLASS)){
200                                owlAPIOntologyCollector.addAxiom(factory.getOWLEquivalentClassesAxiom(me, target));
201                        }else {
202                                tail( "in ontology conversion"+" bnode is: "+bn.getInBoundEdge()+"||"+ bn );
203                                
204                        }
205                        
206                }
207                }catch (Exception e) {
208                        System.out.println("aaa"+getURIString());
209                        e.printStackTrace();
210                }
211        }
212                
213
214}