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 org.apache.log4j.Logger;
022import org.dllearner.kb.aquisitors.RDFBlankNode;
023import org.dllearner.kb.aquisitors.TupleAquisitor;
024import org.dllearner.kb.manipulator.Manipulator;
025import org.dllearner.utilities.datastructures.RDFNodeTuple;
026import org.dllearner.utilities.datastructures.StringTuple;
027import org.dllearner.utilities.owl.OWLVocabulary;
028import org.semanticweb.owlapi.model.IRI;
029import org.semanticweb.owlapi.model.OWLClassExpression;
030import org.semanticweb.owlapi.model.OWLDataFactory;
031import org.semanticweb.owlapi.model.OWLObjectProperty;
032
033import java.util.*;
034
035public class BlankNode extends Node {
036        private static Logger logger = Logger
037        .getLogger(BlankNode.class);
038        
039        RDFBlankNode bNode;
040        
041        String inboundEdge;
042        
043        
044        private List<BlankNode> blankNodes = new ArrayList<>();
045        private SortedSet<StringTuple> otherNodes = new TreeSet<>();
046        private List<DatatypePropertyNode> datatypeProperties = new ArrayList<>();
047        
048        //private List<ObjectPropertyNode> objectProperties = new ArrayList<ObjectPropertyNode>();
049        //private List<OWLDataPropertyNode> datatypeProperties = new ArrayList<OWLDataPropertyNode>();
050
051        
052        public BlankNode(RDFBlankNode bNode, String inboundEdge){
053                super(""+bNode.getBNodeId());
054                this.bNode=bNode;
055                this.inboundEdge = inboundEdge;
056        }
057
058        
059        
060        @Override
061        public List<Node> expand(TupleAquisitor tupleAquisitor,
062                        Manipulator manipulator) {
063                List<Node> newNodes = new ArrayList<>();
064                SortedSet<RDFNodeTuple> s = tupleAquisitor.getBlankNode(bNode.getBNodeId());
065                //System.out.println("entering "+bNode.getBNodeId());
066                
067        
068                for (RDFNodeTuple tuple : s) {
069                        if(tuple.b.isLiteral()) {
070                                //System.out.println("adding dtype: "+tuple);
071                                datatypeProperties.add(new DatatypePropertyNode(tuple.a.toString(), this, new LiteralNode(tuple.b) ));
072                                //connectedNodes.add(new DatatypePropertyNode(tuple.a.toString(), this, new LiteralNode(tuple.b) ));
073                        }else if(tuple.b.isAnon()){
074                                //System.out.println("adding bnode: "+tuple);
075                                BlankNode tmp = new BlankNode( (RDFBlankNode)tuple.b, tuple.a.toString());
076                                //objectProperties.add(new ObjectPropertyNode(tuple.a.toString(), this, tmp ));
077                                //connectedNodes.add(new BlankNode( (RDFBlankNode)tuple.b, tuple.a.toString()));
078                                blankNodes.add(tmp);
079                                newNodes.add(tmp);
080                        }else{
081                                //System.out.println("adding other: "+tuple);
082                                otherNodes.add(new StringTuple(tuple.a.toString(), tuple.b.toString()));
083                                //objectProperties.add(new ObjectPropertyNode(tuple.a.toString(), this, new ClassNode(tuple.b.toString()) ));
084                                //connectedNodes.add(new ObjectPropertyNode(tuple.a.toString(), this, new ClassNode(tuple.b.toString()) ));
085                        }
086                }
087                
088                //System.out.println("finished");
089        
090                return newNodes;
091        }
092
093        @Override
094        public List<BlankNode>  expandProperties(TupleAquisitor TupelAquisitor,
095                        Manipulator manipulator, boolean dissolveBlankNodes) {
096                return new ArrayList<>();
097        }
098
099        @Override
100        public SortedSet<String> toNTriple() {
101                SortedSet<String> returnSet = new TreeSet<>();
102                //String subject = getNTripleForm();
103                /*for (OWLObjectPropertyNode one : objectProperties) {
104                        returnSet.add(subject + one.getNTripleForm() + one.getBPart().getNTripleForm()+" . ");
105                        returnSet.addAll(one.getBPart().toNTriple());
106                }*/
107                return returnSet;
108        }
109        
110        @Override
111        public String getNTripleForm(){
112                return " "+uri+" ";
113        }
114        
115        @Override
116        public String toString(){
117                return "id: "+bNode.getBNodeId()+" inbound: "+getInBoundEdge();
118                
119        }
120        
121        @Override
122        public IRI getIRI(){
123                return IRI.create("http://www.empty.org/empty#empty");
124        }
125        
126        @Override
127        public void toOWLOntology( OWLAPIOntologyCollector owlAPIOntologyCollector){
128                logger.error("toOWLOntology called in blanknodes ");
129                //FIXME robably not needed
130        }
131        
132        public String getInBoundEdge(){
133                return inboundEdge;
134        }
135                
136        public OWLClassExpression getAnonymousClass(OWLAPIOntologyCollector owlAPIOntologyCollector){
137                OWLDataFactory factory =  owlAPIOntologyCollector.getFactory();
138                OWLClassExpression ret = factory.getOWLClass(IRI.create("http://dummy.org/dummy"));
139                
140                //System.out.println(inboundEdge);
141                
142                if(
143                        (inboundEdge.equals(OWLVocabulary.OWL_intersectionOf))||
144                        (inboundEdge.equals(OWLVocabulary.OWL_complementOf))||
145                        (inboundEdge.equals(OWLVocabulary.OWL_unionOf))
146                 ){
147                        Set<OWLClassExpression> target = new HashSet<>();
148                        List<BlankNode> tmp = new ArrayList<>();
149                        tmp.add(this);
150                        while(!tmp.isEmpty()){
151                                BlankNode next = tmp.remove(0);
152                                //next.printAll();
153                                
154                                if(next.otherNodes.contains(new StringTuple(OWLVocabulary.RDF_REST, OWLVocabulary.RDF_NIL))){
155                                        for(StringTuple t : next.otherNodes){
156                                                if(t.a.equals(OWLVocabulary.RDF_FIRST)){
157                                                        target.add(factory.getOWLClass(IRI.create(t.b)));
158                                                        //System.out.println("added "+t.b);
159                                                }
160                                        }
161                                        //System.out.println("nil found");
162                                        //do nothing
163                                }else{
164                                        StringTuple firstOtherNodes = null;
165                                        try{
166                                                firstOtherNodes = next.otherNodes.first();
167                                                if(firstOtherNodes.a.equals(OWLVocabulary.RDF_FIRST)){
168                                                        target.add(factory.getOWLClass(IRI.create(firstOtherNodes.b)));
169                                                        tmp.add(next.blankNodes.get(0));
170                                                        //System.out.println("bnode added");
171                                                }else{
172                                                        
173                                                        tail("double nesting not supported yet");
174                                                        
175                                                }
176                                                
177                                                
178                                        }catch (NoSuchElementException e) {
179                                                logger.warn("something strange happened here: "+firstOtherNodes);
180                                                logger.warn("and here: "+next.otherNodes);
181                                                e.printStackTrace();
182                                        }
183                                        
184                                }
185                        }//end while
186
187                        switch (inboundEdge) {
188                                case OWLVocabulary.OWL_intersectionOf:
189                                        return factory.getOWLObjectIntersectionOf(target);
190                                case OWLVocabulary.OWL_unionOf:
191                                        return factory.getOWLObjectUnionOf(target);
192                                case OWLVocabulary.OWL_complementOf:
193                                        if (target.size() > 1) {
194                                                tail("more than one complement" + target);
195
196                                        } else {
197                                                return factory.getOWLObjectComplementOf(new ArrayList<>(target).remove(0));
198                                        }
199                                        break;
200                                default:
201                                        printAll();
202                                        tail("bnode: wrong type: " + inboundEdge + this);
203                                        break;
204                        }
205                }
206                
207                // restriction
208                if(otherNodes.contains(
209                                new StringTuple(OWLVocabulary.RDF_TYPE, OWLVocabulary.OWL_RESTRICTION))){
210                        return getRestriction( owlAPIOntologyCollector);
211                        
212                }
213                
214                if(!blankNodes.isEmpty()){
215                        return blankNodes.get(0).getAnonymousClass(owlAPIOntologyCollector);
216                }
217                
218                
219                return ret;
220                
221        }
222        
223        public void printAll(){
224                logger.debug(this);
225                
226                logger.debug("otherNodes");
227                for (StringTuple t : otherNodes) {
228                        logger.debug(""+t);
229                }
230                logger.debug("***************");
231                logger.debug("dtype ");
232                for (DatatypePropertyNode d : datatypeProperties) {
233                        logger.debug(d.getURIString()+" "+d.getNTripleFormOfB());
234                }
235                logger.debug("***************");
236                logger.debug("other bnodes");
237                for (BlankNode b : blankNodes) {
238                        logger.debug(b);
239                }
240                logger.debug("***************");
241                
242        }
243        
244        private OWLClassExpression getRestriction(OWLAPIOntologyCollector owlAPIOntologyCollector){
245                OWLDataFactory factory =  owlAPIOntologyCollector.getFactory();
246                OWLObjectProperty property = null;
247                OWLClassExpression concept = null;
248                OWLClassExpression dummy = factory.getOWLClass(IRI.create("http://dummy.org/dummy"));
249                
250                int total = otherNodes.size()+blankNodes.size()+datatypeProperties.size();
251                if(total >=4 ){
252                        logger.info("qualified p restrictions not supported currently");
253                }
254                
255                // get Objectproperty
256                for(StringTuple n : otherNodes) {
257                        if(n.a.equals(OWLVocabulary.OWL_ON_PROPERTY)){
258                                property = factory.getOWLObjectProperty(IRI.create(n.b)); 
259                        }
260                }
261                
262                // has an Integer value
263                if(!datatypeProperties.isEmpty()){
264                        DatatypePropertyNode d = datatypeProperties.get(0);
265                        String p = d.getURIString();
266                        switch (p) {
267                                case OWLVocabulary.OWL_cardinality:
268                                        return factory.getOWLObjectExactCardinality(d.getBPart().getLiteral().getInt(), property);
269                                case OWLVocabulary.OWL_maxCardinality:
270                                        return factory.getOWLObjectMaxCardinality(d.getBPart().getLiteral().getInt(), property);
271                                case OWLVocabulary.OWL_minCardinality:
272                                        return factory.getOWLObjectMinCardinality(d.getBPart().getLiteral().getInt(), property);
273                                default:
274                                        tail(p + d + " in " + this);
275                                        break;
276                        }
277                }
278                
279                if(!blankNodes.isEmpty()){
280                        concept = blankNodes.get(0).getAnonymousClass(owlAPIOntologyCollector);
281                }else{
282                        for(StringTuple n : otherNodes) {
283                                String p = n.a;
284                                String o = n.b;
285                                if(
286                                        (p.equals(OWLVocabulary.OWL_ALL_VALUES_FROM)) ||
287                                        (p.equals(OWLVocabulary.OWL_SOME_VALUES_FROM)) ||
288                                        (p.equals(OWLVocabulary.OWL_HAS_VALUE))
289                                  ){
290                                        concept = factory.getOWLClass(IRI.create(o));
291                                }
292                        }
293                }
294                
295                for(StringTuple n : otherNodes) {
296                        String p = n.a;
297                        switch (p) {
298                                case OWLVocabulary.OWL_ALL_VALUES_FROM:
299                                        return factory.getOWLObjectAllValuesFrom(property, concept);
300                                case OWLVocabulary.OWL_SOME_VALUES_FROM:
301                                        return factory.getOWLObjectSomeValuesFrom(property, concept);
302                                case OWLVocabulary.OWL_HAS_VALUE:
303                                        logger.warn("OWL_hasValue not implemented yet");
304                                        return dummy;
305                        }
306                }
307                return dummy;
308        }
309        
310        
311        
312        
313        /*private boolean isOfType(String type){
314                for (Node n : connectedNodes) {
315                        if((n  instanceof BlankNode )
316                                        && 
317                                ((BlankNode)n).getInBoundEdge().equals(type)) {
318                                return true;
319                        }else if((n  instanceof ObjectPropertyNode )
320                                        && 
321                                ((OWLObjectPropertyNode)n).getAPart().toString().equals(type)) {
322                                return true;
323                        }
324                }
325                return false;
326        }
327        
328        private boolean containsDataTypeProperties(){
329                for (Node n : connectedNodes) {
330                        if(n  instanceof DatatypePropertyNode) {
331                                return true;
332                        }
333                }
334                return false;
335        }*/
336
337}