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