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