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.aquisitors;
021    
022    import java.util.ArrayList;
023    import java.util.HashMap;
024    import java.util.List;
025    import java.util.Map;
026    import java.util.SortedSet;
027    
028    import org.apache.log4j.Logger;
029    import org.dllearner.kb.sparql.SPARQLTasks;
030    import org.dllearner.kb.sparql.SparqlQueryMaker;
031    import org.dllearner.utilities.JamonMonitorLogger;
032    import org.dllearner.utilities.datastructures.RDFNodeTuple;
033    import org.dllearner.utilities.owl.OWLVocabulary;
034    
035    import com.hp.hpl.jena.query.QuerySolution;
036    import com.hp.hpl.jena.query.ResultSetRewindable;
037    import com.hp.hpl.jena.rdf.model.RDFNode;
038    import com.jamonapi.Monitor;
039    
040    /**
041     * Can execute different queries.
042     * 
043     * @author Sebastian Hellmann
044     * 
045     */
046    public class SparqlTupleAquisitor extends TupleAquisitor {
047            
048            
049            private static Logger logger = Logger.getLogger(SparqlTupleAquisitor.class);
050            protected static final String PREDICATE = "predicate";
051            protected static final String OBJECT = "object";
052            
053            protected SparqlQueryMaker sparqlQueryMaker;
054            protected SPARQLTasks sparqlTasks;
055            
056            
057            
058            
059    
060            public SparqlTupleAquisitor(SparqlQueryMaker sparqlQueryMaker, SPARQLTasks sparqlTasks) {
061                    
062                    this.sparqlQueryMaker = sparqlQueryMaker;
063                    this.sparqlTasks = sparqlTasks;
064            }
065            
066            @Override
067            public SortedSet<RDFNodeTuple> retrieveTupel(String uri){
068                    // getQuery
069                    String sparqlQueryString = sparqlQueryMaker.makeSubjectQueryUsingFilters(uri);
070                    SortedSet<RDFNodeTuple> ret = sparqlTasks.queryAsRDFNodeTuple(sparqlQueryString, PREDICATE, OBJECT);
071                    disambiguateBlankNodes(uri, ret);
072                    
073                    return ret;
074            }
075            @Override
076            public SortedSet<RDFNodeTuple> retrieveClassesForInstances(String uri){
077                    // getQuery
078                    String sparqlQueryString = sparqlQueryMaker.makeClassQueryUsingFilters(uri);
079                    SortedSet<RDFNodeTuple> ret = sparqlTasks.queryAsRDFNodeTuple(sparqlQueryString, PREDICATE, OBJECT);
080                    disambiguateBlankNodes(uri, ret);
081                    return ret;
082                    
083            }
084            @Override
085            public SortedSet<RDFNodeTuple> retrieveTuplesForClassesOnly(String uri){
086                    SortedSet<RDFNodeTuple> ret = retrieveTupel(uri);
087                    //the next line is not necessary
088                    //disambiguateBlankNodes(uri, ret);
089                    return ret;
090            }
091            
092            @Override
093            public SortedSet<RDFNodeTuple> getBlankNode(int id){
094                    return BlankNodeCollector.getBlankNode(id);
095            }
096            
097            public void printHM(){
098                    
099                            for (int j = 0; j <  BlankNodeCollector.getBlankNodeMap().size(); j++) {
100                                    System.out.println(j);
101                                    for(RDFNodeTuple t :BlankNodeCollector.getBlankNodeMap().get(j)){
102                                            System.out.println(t);
103                                    }
104                            }
105                    
106            }
107            
108            // main function for resolving blanknodes
109            @Override
110            protected void disambiguateBlankNodes(String uri, SortedSet<RDFNodeTuple> resultSet){
111                    if(!isDissolveBlankNodes()){
112                            return;
113                    }
114                    Monitor bnodeMonitor = JamonMonitorLogger.getTimeMonitor(SparqlTupleAquisitor.class, "blanknode time").start();
115                    try{
116                    for (RDFNodeTuple tuple : resultSet) {
117                            
118                            if(tuple.b.isAnon()){
119                                    int currentId = BlankNodeCollector.getNextGlobalBNodeId();
120                                    // replace the blanknode
121                                    tuple.b = new RDFBlankNode(currentId, tuple.b);
122                                    //System.out.println(uri+" replaced blanknode "+tuple.b);
123                                    dissolveBlankNodes(currentId, uri, tuple);
124                                    //System.out.println(BlankNodeCollector.getBlankNodeMap());
125                                    
126                            }
127                    }
128                    }catch (Exception e) {
129                            e.printStackTrace();
130                            System.exit(0);
131                    }finally{
132                            bnodeMonitor.stop();
133                    }
134                    
135            }
136            
137            // extends a sparql query as long as there are undissolved blanknodes
138            private void dissolveBlankNodes(int currentId, String uri, RDFNodeTuple tuple){
139                    try{
140                            int currentDepth = 1;
141                            int lastDepth = 1;
142                            ResultSetRewindable rsw=null;
143                            do{
144                            String p = tuple.a.toString();
145                            if(p.equals(OWLVocabulary.RDFS_COMMENT) || p.equals(OWLVocabulary.RDFS_LABEL)  ){
146                                    return ;
147                            }
148                            String q = BlankNodeCollector.makeQuery(uri, p, currentDepth);
149    //                      System.out.println(q);
150                            rsw = sparqlTasks.queryAsResultSet(q);
151                            rsw.reset();
152                            lastDepth = currentDepth;
153                            }while (!BlankNodeCollector.testResultSet(rsw, currentDepth++));
154                            
155                            assignIds( currentId,  rsw, lastDepth);
156                    }catch (Exception e) {
157                            logger.info("An error occurred while dissolving blanknodes");
158                    }
159            }
160            
161            //takes the resultset and assigns internal ids
162            private void assignIds(int currentId, ResultSetRewindable rsw, int lastDepth){
163                    //prepare variables according to last depth
164                    List<String> vars = new ArrayList<String>();
165                    vars.add("o0");
166                    for (int i = 1; i <= lastDepth; i++) {
167                            vars.add("p"+i);
168                            vars.add("o"+i);
169                    }
170                    
171                    final List<String> tmpVars = new ArrayList<String>(); 
172                    
173                    Map<String, Integer> lastNodes = new HashMap<String, Integer>();
174                    // the resultset first variable is o0
175                    // iteration over each tuple of the set
176                    while (rsw.hasNext()){
177                            tmpVars.clear();
178                            tmpVars.addAll(vars);
179                            QuerySolution q = rsw.nextSolution();
180                            
181                            //skip all that do not start with a blanknode
182                            // could be two different blank nodes here, but unlikely
183                            if(!q.get("o0").isAnon()){
184                                    lastNodes.put(q.get("o0").toString(), currentId);
185                                    continue;
186                            }else{
187                                    
188                                    // remove the first node
189                                    tmpVars.remove(0);
190                                    assignIdRec(currentId, q, tmpVars,lastNodes);
191                            }
192                            
193                    
194                    }
195                    rsw.reset();
196                    
197            }
198            
199            private void assignIdRec(int currentId, QuerySolution q, List<String> vars, Map<String, Integer> lastNodes ){
200                    if(vars.isEmpty()){return;}
201                    String pvar = vars.remove(0);
202                    String ovar = vars.remove(0);
203                    
204                    // the next node
205                    RDFNode n = q.get(ovar);
206                    if(n.isAnon()){
207                            int nextId;
208                            if(lastNodes.get(n.toString())==null){
209                                    nextId = BlankNodeCollector.getNextGlobalBNodeId();
210                                    lastNodes.put(n.toString(), nextId);
211                                    //System.out.println(n.toString());
212                            }else{
213                                    nextId = lastNodes.get(n.toString());
214                            }
215                            RDFNodeTuple tuple = new RDFNodeTuple(q.get(pvar), new RDFBlankNode(nextId,n));
216                            BlankNodeCollector.addBlankNode(currentId, tuple);
217                            assignIdRec(nextId, q, vars, lastNodes);
218                    }else{
219                            BlankNodeCollector.addBlankNode(currentId, new RDFNodeTuple(q.get(pvar), n));
220                    }
221                    
222                    
223            }
224            
225            
226            
227    
228    
229            
230            
231            
232            
233            
234            
235    
236    
237    }