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.sparql; 020 021import org.dllearner.utilities.datastructures.StringTuple; 022import org.dllearner.utilities.owl.OWLVocabulary; 023 024import java.util.ArrayList; 025import java.util.List; 026import java.util.Set; 027import java.util.TreeSet; 028 029/** 030 * Can assemble sparql queries. can make queries for subject, predicate, object 031 * according to the filter settings object SparqlQueryType, which gives the 032 * predicate and object lists 033 * 034 * @author Sebastian Hellmann 035 * 036 */ 037public class SparqlQueryMaker { 038 039 private static final String MODE_ALLOW = "allow"; 040 041 private static final String MODE_FORBID = "forbid"; 042 043 private static final String lineend = "\n"; 044 045 // allow false is forbid 046 private boolean allowMode = false; 047 048 private boolean assembled = false; 049 050 private String filter = ""; 051 052 private Set<String> objectFilterList; 053 054 private Set<String> predicateFilterList; 055 056 private Set<StringTuple> predicateobjectFilterList; 057 058 private boolean literals = false; 059 060 public void setLiterals(boolean literals) { 061 this.literals = literals; 062 } 063 064 public SparqlQueryMaker(Set<String> objectFilterList, 065 Set<String> predicateFilterList, boolean literals) { 066 super(); 067 this.objectFilterList = objectFilterList; 068 this.predicateFilterList = predicateFilterList; 069 this.predicateobjectFilterList = new TreeSet<>(); 070 this.literals = literals; 071 } 072 073 public SparqlQueryMaker(boolean allowMode, 074 Set<String> objectFilterList, 075 Set<String> predicateFilterList, boolean literals) { 076 077 this(objectFilterList, predicateFilterList, literals); 078 this.allowMode = allowMode; 079 } 080 081 public SparqlQueryMaker(String mode, Set<String> objectFilterList, 082 Set<String> predicateFilterList, boolean literals) { 083 this(objectFilterList, predicateFilterList, literals); 084 if (mode.equalsIgnoreCase(MODE_ALLOW)) { 085 this.allowMode = true; 086 } else if (mode.equalsIgnoreCase(MODE_FORBID)) { 087 this.allowMode = false; 088 } else { 089 this.allowMode = false; 090 } 091 } 092 093 public String makeSubjectQueryUsingFilters(String subject) { 094 095 // String filter = internalFilterAssemblySubject(); 096 if (!assembled) { 097 filter = internalFilterAssemblySubject("predicate", "object"); 098 filter = (filter.length() > 0) ? "FILTER( " + lineend + filter 099 + "). " : " "; 100 assembled = true; 101 } 102 103 String returnString = "SELECT * WHERE { " + lineend + "<" + subject 104 + "> ?predicate ?object. " + lineend + filter + " } "; 105 106 return returnString; 107 } 108 109 //QUALITY optimize 110 public String makeClassQueryUsingFilters(String subject) { 111 112 // String filter = internalFilterAssemblySubject(); 113 String tmpFilter = internalFilterAssemblySubject("predicate", "object"); 114 tmpFilter = (tmpFilter.length() > 0) ? "FILTER( " + lineend + tmpFilter 115 + "). " : " "; 116 117 String returnString = "SELECT * WHERE {" +lineend + 118 "<" + subject + "> ?predicate ?object;" + 119 "a ?object . "+lineend+ 120 tmpFilter + "}"; 121 122 //String returnString = "SELECT * WHERE {" +lineend + 123 // "<" + subject + "> <"+OWLVocabulary.RDF_TYPE+"> ?object. " +lineend+ 124 // tmpFilter + "}"; 125 126 return returnString; 127 } 128 129 public String makeSubjectQueryLevel(String subject, int level) { 130 131 // String filter = internalFilterAssemblySubject(); 132 // if (!assembled) { 133 String filtertmp = ""; 134 filtertmp = internalFilterAssemblySubject("predicate0", "object0"); 135 filtertmp = (filtertmp.length() > 0) ? "FILTER( " + filtertmp + "). " 136 : " "; 137 138 StringBuffer sbuff = new StringBuffer(1400); 139 sbuff.append("SELECT * WHERE { " + lineend + "{<").append(subject).append("> ?predicate0 ?object0 .").append(lineend); 140 sbuff.append(filtertmp).append("} ").append(lineend); 141 142 // " + lineend + filter +" } "; 143 for (int i = 1; i < level; i++) { 144 sbuff.append("OPTIONAL { "); 145 sbuff.append("?object").append(i - 1).append(" ?predicate").append(i).append(" ?object").append(i).append(" . ").append(lineend); 146 147 filtertmp = internalFilterAssemblySubject("predicate" + i, "object" 148 + i); 149 filtertmp = (filtertmp.length() > 0) ? "FILTER " + filtertmp + ". " 150 : " "; 151 152 sbuff.append(filtertmp).append(" }"); 153 } 154 155 sbuff.append(lineend + "} "); 156 157 return sbuff.toString(); 158 } 159 160 private String internalFilterAssemblySubject(String predicateVariable, 161 String objectVariable) { 162 predicateVariable = (predicateVariable.startsWith("?")) ? predicateVariable 163 : "?" + predicateVariable; 164 objectVariable = (objectVariable.startsWith("?")) ? objectVariable 165 : "?" + objectVariable; 166 167 List<String> terms = new ArrayList<>(); 168 String not = (isAllowMode()) ? "" : "!"; 169 /*new filter type */ 170 171 for (StringTuple tuple : getPredicateObjectFilterList()) { 172 List<String> tmpterms = new ArrayList<>(); 173 tmpterms.add(not + "regex(str(" + predicateVariable + "), '" + tuple.a+ "')"); 174 tmpterms.add(not + "regex(str(" + objectVariable + "), '" + tuple.b+ "')"); 175 terms.add(assembleTerms(tmpterms, "&&")); 176 } 177 178 for (String pred : getPredicateFilterList()) { 179 terms.add(not + "regex(str(" + predicateVariable + "), '" + pred 180 + "')"); 181 } 182 for (String obj : getObjectFilterList()) { 183 terms 184 .add(not + "regex(str(" + objectVariable + "), '" + obj 185 + "')"); 186 } 187 String assembled = assembleTerms(terms, getOperator()); 188 189 terms = new ArrayList<>(); 190 // the next line could be removed as it is included in assemble terms 191 if(!assembled.isEmpty()){ 192 terms.add(assembled); 193 } 194 if (!isLiterals()) { 195 terms.add("!isLiteral(" + objectVariable + ")"); 196 } 197 return assembleTerms(terms, "&&"); 198 199 200 } 201 202 private String getOperator(){ 203 return (isAllowMode())?"||":"&&"; 204 205 } 206 207 208 private String assembleTerms(List<String> terms, String operator) { 209 if((!operator.equals("||")) && (!operator.equals("&&"))){ 210 System.out.println("in SparqlQuerymaker assembleTerms recieved wrong operator"); 211 System.exit(0); 212 } 213 214 if (terms.isEmpty()) 215 return ""; 216 else if (terms.size() == 1) 217 return (terms.get(0).isEmpty())?"": brackets(terms.get(0)); 218 else { 219 StringBuffer sbuf = new StringBuffer(1400); 220 String first = terms.remove(0); 221 sbuf.append(brackets(first)); 222 for (String term : terms) { 223 sbuf.append(lineend).append(operator); 224 sbuf.append(brackets(term)); 225 } 226 return brackets(sbuf.toString()); 227 } 228 229 } 230 231 private static String brackets(String s) { 232 return "(" + s + ")"; 233 } 234 235 public boolean isLiterals() { 236 return literals; 237 } 238 239 public boolean isAllowMode() { 240 return allowMode; 241 } 242 243 public Set<String> getObjectFilterList() { 244 return objectFilterList; 245 } 246 247 public Set<String> getPredicateFilterList() { 248 return predicateFilterList; 249 } 250 public Set<StringTuple> getPredicateObjectFilterList() { 251 return predicateobjectFilterList; 252 } 253 254 public void addPredicateFilter(String newFilter) { 255 assembled = false; 256 predicateFilterList.add(newFilter); 257 } 258 259 public void addObjectFilter(String newFilter) { 260 assembled = false; 261 objectFilterList.add(newFilter); 262 } 263 public void addPredicateObjectFilter(String pred, String object) { 264 assembled = false; 265 predicateobjectFilterList.add(new StringTuple(pred, object)); 266 } 267 268 public void combineWith(SparqlQueryMaker sqm){ 269 predicateFilterList.addAll(sqm.predicateFilterList); 270 objectFilterList.addAll(sqm.objectFilterList); 271 } 272 273 public static SparqlQueryMaker getSparqlQueryMakerByName(String name) { 274 275 if (name.equalsIgnoreCase("YAGO")) 276 return getAllowYAGOFilter(); 277 else if (name.equalsIgnoreCase("SKOS")) 278 return getAllowSKOSFilter(); 279 else if (name.equalsIgnoreCase("YAGOSKOS")) 280 return getAllowYAGOandSKOSFilter(); 281 else if (name.equalsIgnoreCase("YAGOSPECIALHIERARCHY")) 282 return getYagoSpecialHierarchyFilter(); 283 else if (name.equalsIgnoreCase("YAGOONLY")) 284 return getAllowYAGO_ONLYFilter(); 285 else if (name.equalsIgnoreCase("TEST")) 286 return getTestFilter(); 287 else if (name.equalsIgnoreCase("DBPEDIA-NAVIGATOR")) 288 return getDBpediaNavigatorFilter(); 289 else 290 return null; 291 } 292 293 private void addFiltersForDBpediaSKOS() { 294 addPredicateFilter("http://www.w3.org/2004/02/skos/core"); 295 addObjectFilter("http://www.w3.org/2004/02/skos/core"); 296 addObjectFilter("http://dbpedia.org/resource/Category:"); 297 addObjectFilter("http://dbpedia.org/resource/Template"); 298 } 299 300 private void addFiltersForDBpediaUMBEL() { 301 addObjectFilter("http://umbel.org/umbel/"); 302 } 303 @SuppressWarnings("unused") 304 private void addFiltersForDBpediaOntology() { 305 addObjectFilter("http://dbpedia.org/ontology/"); 306 } 307 @SuppressWarnings("unused") 308 private void addFiltersForDBpediaCyc() { 309 addObjectFilter("http://sw.opencyc.org/2008/06/10/concept/"); 310 } 311 312 private void addFiltersForYago() { 313 addObjectFilter("http://dbpedia.org/class/yago"); 314 315 } 316 317 private void addFiltersForOWLSameAs() { 318 addPredicateFilter("http://www.w3.org/2002/07/owl#sameAs"); 319 } 320 private void addFiltersForFOAF() { 321 addPredicateFilter("http://xmlns.com/foaf/0.1/"); 322 addObjectFilter("http://xmlns.com/foaf/0.1/"); 323 324 } 325 326 private void addFiltersForWordNet() { 327 addObjectFilter("http://www.w3.org/2006/03/wn/wn20/instances/synset"); 328 329 } 330 private void addFiltersForGeonames() { 331 addObjectFilter("http://www.geonames.org"); 332 333 } 334 private void addFiltersForFlickrwrappr() { 335 addObjectFilter("http://www4.wiwiss.fu-berlin.de/flickrwrappr"); 336 337 } 338 339 private void addFiltersForDBpedia() { 340 addPredicateFilter("http://dbpedia.org/property/reference"); 341 addPredicateFilter("http://dbpedia.org/property/website"); 342 addPredicateFilter("http://dbpedia.org/property/wikipage"); 343 addPredicateFilter("http://dbpedia.org/property/wikiPageUsesTemplate"); 344 addPredicateFilter("http://dbpedia.org/property/relatedInstance"); 345 addPredicateFilter("http://dbpedia.org/property/owner"); 346 addPredicateFilter("http://dbpedia.org/property/standard"); 347 addObjectFilter("http://upload.wikimedia.org/wikipedia/commons"); 348 addObjectFilter("http://upload.wikimedia.org/wikipedia"); 349 } 350 351 public static SparqlQueryMaker getAllowSKOSFilter() { 352 SparqlQueryMaker sqm = new SparqlQueryMaker("forbid", new TreeSet<>(), new TreeSet<>(), false); 353 sqm.combineWith(getAllowYAGOandSKOSFilter()); 354 sqm.addFiltersForYago(); 355 356 sqm.addPredicateFilter("http://www.w3.org/2004/02/skos/core#narrower"); 357 sqm.addObjectFilter("http://dbpedia.org/resource/Template"); 358 359 return sqm; 360 } 361 362 public static SparqlQueryMaker getAllowYAGOFilter() { 363 SparqlQueryMaker sqm = new SparqlQueryMaker("forbid", new TreeSet<>(), new TreeSet<>(), false); 364 sqm.combineWith(getAllowYAGOandSKOSFilter()); 365 sqm.addFiltersForDBpediaSKOS(); 366 return sqm; 367 } 368 369 public static SparqlQueryMaker getAllowYAGO_ONLYFilter() { 370 SparqlQueryMaker sqm = new SparqlQueryMaker("forbid", new TreeSet<>(), new TreeSet<>(), false); 371 sqm.combineWith(getAllowYAGOandSKOSFilter()); 372 sqm.addFiltersForDBpediaSKOS(); 373 sqm.addFiltersForDBpediaUMBEL(); 374 return sqm; 375 } 376 377 public static SparqlQueryMaker getDBpediaNavigatorFilter() { 378// SparqlQueryMaker sqm = new SparqlQueryMaker("allow", new TreeSet<String>(), new TreeSet<String>(), false); 379 SparqlQueryMaker sqm = new SparqlQueryMaker("allow", new TreeSet<>(), new TreeSet<>(), true); 380// sqm.addPredicateFilter("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); 381// sqm.addPredicateFilter("http://www.w3.org/2000/01/rdf-schema#subClassOf"); 382// sqm.addPredicateFilter("http://www.w3.org/2003/01/geo/wgs84_pos#lat"); 383// sqm.addPredicateFilter("http://www.w3.org/2003/01/geo/wgs84_pos#long"); 384// sqm.addPredicateFilter("http://www.w3.org/2000/01/rdf-schema#label"); 385 386 String dbont = "http://dbpedia.org/ontology/"; 387 sqm.addPredicateFilter(dbont); 388 sqm.addPredicateFilter(OWLVocabulary.RDFS_range); 389 sqm.addPredicateFilter(OWLVocabulary.RDFS_domain); 390 sqm.addPredicateObjectFilter(dbont, dbont); 391 sqm.addPredicateObjectFilter(OWLVocabulary.RDF_TYPE, dbont); 392 sqm.addPredicateObjectFilter(OWLVocabulary.RDFS_SUBCLASS_OF, dbont); 393 sqm.setLiterals(true); 394 395 // pred.add("http://dbpedia.org/property/wikipage"); 396 // pred.add("http://dbpedia.org/property/wikiPageUsesTemplate"); 397 // pred.add("http://dbpedia.org/property/relatedInstance"); 398 // pred.add("http://dbpedia.org/property/owner"); 399 // pred.add("http://dbpedia.org/property/standard"); 400 return sqm; 401 } 402 403 public static SparqlQueryMaker getYagoSpecialHierarchyFilter() { 404 SparqlQueryMaker sqm = new SparqlQueryMaker("forbid", new TreeSet<>(), new TreeSet<>(), false); 405 sqm.combineWith(getAllowYAGOFilter()); 406 sqm.addPredicateFilter("http://dbpedia.org/property/monarch"); 407 return sqm; 408 } 409 410 411 412 public static SparqlQueryMaker getAllowYAGOandSKOSFilter() { 413 SparqlQueryMaker sqm = new SparqlQueryMaker("forbid", new TreeSet<>(), new TreeSet<>(), false); 414 sqm.addFiltersForFOAF(); 415 sqm.addFiltersForDBpedia(); 416 417 sqm.addFiltersForGeonames(); 418 sqm.addFiltersForWordNet(); 419 sqm.addFiltersForFlickrwrappr(); 420 sqm.addFiltersForOWLSameAs(); 421 422 sqm.addPredicateFilter("http://www.w3.org/2004/02/skos/core#narrower"); 423 sqm.addObjectFilter("http://dbpedia.org/resource/Template"); 424 return sqm; 425 } 426 427 public static SparqlQueryMaker getTestFilter() { 428 SparqlQueryMaker sqm = new SparqlQueryMaker("forbid", new TreeSet<>(), new TreeSet<>(), true); 429 sqm.combineWith(getAllowYAGOFilter()); 430 return sqm; 431 } 432 433 public static void main(String[] args) { 434 435 String uri = "http://dbpedia.org/resource/Angela_Merkel"; 436 // System.out.println(getSparqlQueryMakerByName("YAGO").makeSubjectQueryUsingFilters(uri)); 437 // System.out.println(getSparqlQueryMakerByName("YAGO").makeSubjectQueryUsingFilters(uri).length()); 438 // System.out.println(getDBpediaNavigatorFilter().makeSubjectQueryUsingFilters(uri)); 439 System.out.println(); 440 System.out.println(getSparqlQueryMakerByName("YAGO") 441 .makeSubjectQueryLevel(uri, 3)); 442 443 } 444 445 446}