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