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.List;
023 import java.util.Set;
024 import java.util.SortedSet;
025 import java.util.TreeSet;
026
027 import org.apache.log4j.Logger;
028 import org.dllearner.core.owl.DatatypeProperty;
029 import org.dllearner.core.owl.Entity;
030 import org.dllearner.core.owl.NamedClass;
031 import org.dllearner.core.owl.ObjectProperty;
032 import org.dllearner.utilities.datastructures.RDFNodeTuple;
033 import org.dllearner.utilities.datastructures.StringTuple;
034 import org.dllearner.utilities.owl.OWLVocabulary;
035
036 import com.hp.hpl.jena.query.QuerySolution;
037 import com.hp.hpl.jena.query.ResultSet;
038 import com.hp.hpl.jena.query.ResultSetFactory;
039 import com.hp.hpl.jena.query.ResultSetFormatter;
040 import com.hp.hpl.jena.query.ResultSetRewindable;
041
042 /**
043 * Convenience class for SPARQL queries initialized
044 * with a SparqlEndpoint. A Cache can also be used to further improve
045 * query time. Some methods allow basic reasoning
046 *
047 * @author Sebastian Hellmann
048 * @author Jens Lehmann
049 */
050 public class SPARQLTasks {
051
052 private static Logger logger = Logger.getLogger(SPARQLTasks.class);
053
054 private final Cache cache;
055
056 private final SparqlEndpoint sparqlEndpoint;
057
058 /**
059 * @param sparqlEndpoint
060 * the Endpoint the sparql queries will be send to
061 */
062 public SPARQLTasks(final SparqlEndpoint sparqlEndpoint) {
063 // super();
064 this.cache = null;
065 this.sparqlEndpoint = sparqlEndpoint;
066 }
067
068 /**
069 * @param cache
070 * a cache object
071 * @param sparqlEndpoint
072 * the Endpoint the sparql queries will be send to
073 */
074 public SPARQLTasks(final Cache cache, final SparqlEndpoint sparqlEndpoint) {
075 // super();
076 this.cache = cache;
077 this.sparqlEndpoint = sparqlEndpoint;
078 }
079
080 /**
081 * get all superclasses up to a certain depth, 1 means direct superclasses
082 * only.
083 *
084 * @param classURI
085 * the uri of the class with no quotes for which the superclasses
086 * will be retrieved
087 * @param maxDepth
088 * how far the RDF graph will be explored (1 means only direct
089 * SuperClasses)
090 * @return a Sorted String Set of all ClassNames, including the starting
091 * class
092 */
093 public SortedSet<String> getSuperClasses(final String classURI,
094 final int maxDepth) {
095 // TODO check for quotes in uris
096 return getRecursiveSuperOrSubClasses(classURI, maxDepth, false);
097 }
098
099 public SortedSet<String> getParallelClasses(String classURI, int limit) {
100 String query = "SELECT ?sub WHERE { <" + classURI + "> <http://www.w3.org/2000/01/rdf-schema#subClassOf> ?super .";
101 query += "?sub <http://www.w3.org/2000/01/rdf-schema#subClassOf> ?super .";
102 query += "FILTER( ?sub != <" + classURI + ">) . } LIMIT " + limit;
103 return queryAsSet(query, "?sub");
104 // SparqlQuery sq = new SparqlQuery(query, sparqlEndpoint);
105 // ResultSet rs = sq.send();
106
107 }
108
109 /**
110 * This is the underlying function to get Super and SubClasses.
111 *
112 * @param classURI
113 * the uri of the class with no quotes for which the classes will
114 * be retrieved
115 * @param maxDepth
116 * how far the RDF graph will be explored (1 means only direct
117 * related Classes)
118 * @return a Sorted String Set of all retrieved ClassNames, including the
119 * starting class
120 */
121 private SortedSet<String> getRecursiveSuperOrSubClasses(
122 final String classURI, final int maxDepth, boolean subclasses) {
123 // TODO check for quotes in uris
124 int depth = maxDepth;
125
126 final SortedSet<String> toBeRetrieved = new TreeSet<String>();
127 toBeRetrieved.add(classURI);
128
129 final SortedSet<String> returnSet = new TreeSet<String>();
130 final SortedSet<String> tmpSet = new TreeSet<String>();
131
132 // collect super/subclasses for the depth
133 for (; (depth > 0) && (!toBeRetrieved.isEmpty()); depth--) {
134 // collect super/subclasses for each class in toBeRetrieved
135 // accumulate in tmpSet
136 for (String oneClass : toBeRetrieved) {
137 if (subclasses) {
138 tmpSet.addAll(getDirectSubClasses(oneClass));
139 } else {
140 tmpSet.addAll(getDirectSuperClasses(oneClass));
141 }
142
143 }// end inner for
144
145 // remember all queried classes to return them.
146 returnSet.addAll(toBeRetrieved);
147 // then discard them
148 toBeRetrieved.clear();
149 // all that are to be retrieved the next time.
150 toBeRetrieved.addAll(tmpSet);
151 // small optimization, remove all that have been processed already:
152 toBeRetrieved.removeAll(returnSet);
153 // reset
154 tmpSet.clear();
155 }// end outer for
156
157 returnSet.addAll(toBeRetrieved);
158
159 return returnSet;
160 }
161
162 /**
163 * gets a SortedSet of all subclasses up to a certain depth
164 *
165 * TODO the mentioned method does not exist
166 * conceptRewrite(String descriptionKBSyntax, SparqlEndpoint se, Cache
167 * c, boolean simple )
168 * @param classURI An URI string with no quotes
169 * @param maxDepth
170 * @return TreeSet of subclasses including classURI
171 */
172 public SortedSet<String> getSubClasses(final String classURI,
173 final int maxDepth) {
174 // TODO check for quotes in uris
175 return getRecursiveSuperOrSubClasses(classURI, maxDepth, true);
176 }
177
178 /**
179 * returns all direct subclasses of String concept
180 *
181 * @param concept
182 * An URI string with no quotes
183 * @return SortedSet of direct subclasses as String
184 */
185 private SortedSet<String> getDirectSubClasses(String concept) {
186 return queryPatternAsSet("?subject", "<" + OWLVocabulary.RDFS_SUBCLASS_OF + ">", "<"
187 + concept + ">", "subject", 0, false);
188 }
189
190 private SortedSet<String> getDirectSuperClasses(String concept) {
191 return queryPatternAsSet("<" + concept + ">", "<" + OWLVocabulary.RDFS_SUBCLASS_OF + ">",
192 "?object", "object", 0, false);
193 }
194
195 /**
196 * Retrieves all resource for a fixed role and object. These instances are
197 * distinct. QUALITY: buggy because role doesn't work sometimes get subject
198 * with fixed role and object
199 *
200 * @param role
201 * An URI string with no quotes
202 * @param object
203 * An URI string with no quotes
204 * @param sparqlResultLimit
205 * Limits the ResultSet size
206 * @return SortedSet with the resulting subjects
207 */
208 public SortedSet<String> retrieveDISTINCTSubjectsForRoleAndObject(
209 String role, String object, int sparqlResultLimit) {
210 return queryPatternAsSet("?subject", "<" + role + ">", "<" + object
211 + ">", "subject", sparqlResultLimit, true);
212 }
213
214 /**
215 * @param subject
216 * An URI string with no quotes
217 * @param role
218 * An URI string with no quotes
219 * @param sparqlResultLimit
220 * Limits the ResultSet size
221 * @return SortedSet with the resulting objects
222 */
223 public SortedSet<String> retrieveObjectsForSubjectAndRole(String subject,
224 String role, int sparqlResultLimit) {
225 return queryPatternAsSet("<" + subject + ">", "<" + role + ">",
226 "?object", "object", sparqlResultLimit, true);
227 }
228
229 /**
230 * all instances for a SKOS concept.
231 *
232 * @param skosConcept
233 * An URI string with no quotes
234 * @param sparqlResultLimit
235 * Limits the ResultSet size
236 * @return SortedSet with the instances
237 */
238 public SortedSet<String> retrieveInstancesForSKOSConcept(
239 String skosConcept, int sparqlResultLimit) {
240 return queryPatternAsSet("?subject", "?predicate", "<" + skosConcept
241 + ">", "subject", sparqlResultLimit, false);
242 }
243
244 /**
245 * get all instances for a complex concept / class description in KBSyntax.
246 *
247 * @param conceptKBSyntax
248 * A description string in KBSyntax
249 * @param sparqlResultLimit
250 * Limits the ResultSet size
251 * @return SortedSet with the instance uris
252 */
253 public SortedSet<String> retrieveInstancesForClassDescription(
254 String conceptKBSyntax, int sparqlResultLimit) {
255
256 String sparqlQueryString = "";
257 try {
258 sparqlQueryString = SparqlQueryDescriptionConvertVisitor
259 .getSparqlQuery(conceptKBSyntax, sparqlResultLimit, false, false);
260 } catch (Exception e) {
261 logger.warn(e.getMessage());
262 }
263 return queryAsSet(sparqlQueryString, "subject");
264 }
265
266 /**
267 * same as <code>retrieveInstancesForClassDescription</code> including
268 * RDFS Reasoning.
269 *
270 * @param conceptKBSyntax
271 * A description string in KBSyntax
272 * @param sparqlResultLimit
273 * Limits the ResultSet size
274 * @return SortedSet with the instance uris
275 */
276 public SortedSet<String> retrieveInstancesForClassDescriptionIncludingSubclasses(
277 String conceptKBSyntax, int sparqlResultLimit, int maxDepth) {
278
279 String sparqlQueryString = "";
280 try {
281 sparqlQueryString = SparqlQueryDescriptionConvertVisitor
282 .getSparqlQueryIncludingSubclasses(conceptKBSyntax,
283 sparqlResultLimit, this, maxDepth);
284
285
286 } catch (Exception e) {
287 logger.warn(e.getMessage());
288 }
289 return queryAsSet(sparqlQueryString, "subject");
290 }
291
292 /**
293 * get all direct Classes of an instance.
294 *
295 * @param instance
296 * An URI string with no quotes
297 * @param sparqlResultLimit
298 * Limits the ResultSet size
299 */
300 public SortedSet<String> getClassesForInstance(String instance,
301 int sparqlResultLimit) {
302
303 // String sparqlQueryString = "SELECT ?subject WHERE { \n " + "<" +
304 // instance
305 // + ">" + " a " + "?subject " + "\n" + "} " + limit(sparqlResultLimit);
306 return queryPatternAsSet("<" + instance + ">", "a", "?object",
307 "object", sparqlResultLimit, false);
308 // return queryAsSet(sparqlQueryString, "subject");
309 }
310
311 /**
312 * Returns all instances that are in the prefield (subject) of the
313 * property/role.
314 *
315 * Cave: These have to fulfill the following requirements: 1. They are not
316 * literals 2. They have at least a Class assigned 3. DISTINCT is used in
317 * the query
318 *
319 * TODO there might be a better name for the function
320 *
321 * @param role
322 * An URI of a property/role
323 * @param sparqlResultLimit
324 * ResultSet limit
325 * @return A String Set of instances
326 */
327 public SortedSet<String> getDomainInstances(String role,
328 int sparqlResultLimit) {
329
330 String sparqlQueryString = "SELECT DISTINCT ?domain " + "WHERE { \n"
331 + "?domain <" + role + "> " + " ?o. \n" + "?domain a []\n."
332 + "FILTER (!isLiteral(?domain))." + "}\n"
333 + limit(sparqlResultLimit);
334
335 return queryAsSet(sparqlQueryString, "domain");
336
337 }
338
339 /**
340 * Returns all instances that are fillers of the property/role. Cave: These
341 * have to fulfill the following requirements: 1. The fillers are not
342 * literals 2. The fillers have at least a Class assigned 3. DISTINCT is
343 * used in the query
344 *
345 * TODO there might be a better name for the function
346 *
347 * @param role
348 * An URI of a property/role
349 * @param sparqlResultLimit
350 * ResultSet limit
351 * @return A String Set of instances
352 */
353 public SortedSet<String> getRangeInstances(String role,
354 int sparqlResultLimit) {
355
356 String sparqlQueryString = "SELECT DISTINCT ?range " + "WHERE { \n"
357 + "?s <" + role + "> " + " ?range. \n" + "?range a [].\n"
358 + "FILTER (!isLiteral(?range))." + "}\n"
359 + limit(sparqlResultLimit);
360
361 return queryAsSet(sparqlQueryString, "range");
362
363 }
364
365 /**
366 * query a pattern with a standard SPARQL query. The Query will be of the
367 * form SELECT * WHERE { subject predicate object } LIMIT X. It has a high
368 * degree of freedom, but only one variabla can be retrieved.
369 *
370 * usage example 1 : queryPatternAsSet( "?subject", "<http://somerole>",
371 * "?object", "subject" ). retrieves all subjects, that have the role,
372 * somerole
373 *
374 * usage example 1 : queryPatternAsSet( "?subject", "<http://somerole>",
375 * "?object", "object" ). retrieves all objects, that have the role,
376 * somerole
377 *
378 * @param subject
379 * An URI string enclosed in <> or a SPARQL variable e.g.
380 * "?subject"
381 * @param predicate
382 * An URI string enclosed in <> or a SPARQL variable e.g.
383 * "?predicate"
384 * @param object
385 * An URI string enclosed in <> or a SPARQL variable e.g.
386 * "?object"
387 * @param variable
388 * The variable to be retrieved and put into the SortedSet
389 * @param sparqlResultLimit
390 * 0 means all
391 * @param distinct
392 * determines whether distinct is used
393 * @return a String Set with the Bindings of the variable in variable
394 */
395 public SortedSet<String> queryPatternAsSet(String subject,
396 String predicate, String object, String variable,
397 int sparqlResultLimit, boolean distinct) {
398 String sparqlQueryString = "SELECT " + ((distinct) ? "DISTINCT" : "")
399 + " * WHERE { \n " + " " + subject + " " + predicate + " "
400 + object + " \n" + "} " + limit(sparqlResultLimit);
401 return queryAsSet(sparqlQueryString, variable);
402 }
403
404 @Deprecated
405 public SortedSet<StringTuple> queryAsTuple(String subject, boolean filterLiterals) {
406 ResultSetRewindable rs = null;
407 String p = "predicate";
408 String o = "object";
409 String lits = (filterLiterals)? ".FILTER (!isLiteral(?"+o+"))." : "";
410 String sparqlQueryString = "SELECT * WHERE { <"+subject+"> ?"+p+" ?"+o+" "+lits+" } ";
411
412 try {
413 String jsonString = query(sparqlQueryString);
414 rs = SparqlQuery.convertJSONtoResultSet(jsonString);
415
416 } catch (Exception e) {
417 logger.warn(e.getMessage());
418 }
419
420 //SimpleClock sc = new SimpleClock();
421 //rw = ResultSetFactory.makeRewindable(rs);
422 //sc.printAndSet("rewindable");
423 return getTuplesFromResultSet(rs, p, o);
424 }
425
426 @Deprecated
427 public SortedSet<StringTuple> queryAsTuple(String sparqlQueryString, String var1, String var2) {
428 ResultSetRewindable rs = null;
429 try {
430 String jsonString = query(sparqlQueryString);
431 rs = SparqlQuery.convertJSONtoResultSet(jsonString);
432
433 } catch (Exception e) {
434 logger.warn(e.getMessage());
435 }
436
437 //SimpleClock sc = new SimpleClock();
438 //rw = ResultSetFactory.makeRewindable(rs);
439 //sc.printAndSet("rewindable");
440 return getTuplesFromResultSet(rs, var1, var2);
441 }
442
443 @SuppressWarnings("unchecked")
444 public SortedSet<RDFNodeTuple> queryAsRDFNodeTuple(String sparqlQueryString, String var1, String var2) {
445 ResultSetRewindable rsw = null;
446 SortedSet<RDFNodeTuple> returnSet = new TreeSet<RDFNodeTuple>();
447
448 try {
449 String jsonString = query(sparqlQueryString);
450 rsw = SparqlQuery.convertJSONtoResultSet(jsonString);
451
452
453
454 List<QuerySolution> l = ResultSetFormatter.toList(rsw);
455 for (QuerySolution resultBinding : l) {
456 returnSet.add(new RDFNodeTuple(resultBinding.get(var1),resultBinding.get(var2)));
457 }
458
459 rsw.reset();
460 } catch (Exception e) {
461 logger.info("ignoring (see log for details): Exception caught in SPARQLTasks, passing emtpy result: "+e.getMessage());
462 }
463
464 return returnSet;
465 }
466
467
468 /**
469 * little higher level, executes query ,returns all resources for a
470 * variable.
471 *
472 * @param sparqlQueryString
473 * The query
474 * @param variable
475 * The single variable used in the query
476 */
477 public SortedSet<String> queryAsSet(String sparqlQueryString,
478 String variable) {
479 ResultSet rs = null;
480 try {
481 String jsonString = query(sparqlQueryString);
482 rs = SparqlQuery.convertJSONtoResultSet(jsonString);
483
484 } catch (Exception e) {
485 logger.warn(e.getMessage());
486 }
487 return getStringSetForVariableFromResultSet(ResultSetFactory
488 .makeRewindable(rs), variable);
489 }
490
491 /**
492 * low level, executes query returns ResultSet.
493 *
494 * @param sparqlQueryString
495 * The query
496 * @return jena ResultSet
497 */
498 public ResultSetRewindable queryAsResultSet(String sparqlQueryString) {
499 SparqlQuery sq = new SparqlQuery(sparqlQueryString, sparqlEndpoint);
500 if(cache == null) {
501 return sq.send();
502 } else {
503 // get JSON from cache and convert to result set
504 String json = cache.executeSparqlQuery(sq);
505 return SparqlQuery.convertJSONtoResultSet(json);
506 }
507 }
508
509 /**
510 * variable must be ?count
511 * @param sparqlQueryString
512 * @return -1 on failure count on success
513 */
514 public int queryAsCount(String sparqlQueryString) {
515 SparqlQuery sq = new SparqlQuery(sparqlQueryString, sparqlEndpoint);
516 ResultSetRewindable rsw = null;
517 if(cache == null) {
518 rsw = sq.send();
519 } else {
520 // get JSON from cache and convert to result set
521 String json = cache.executeSparqlQuery(sq);
522 rsw = SparqlQuery.convertJSONtoResultSet(json);
523 }
524 int ret = -1;
525 while(rsw.hasNext()){
526 QuerySolution qs = rsw.nextSolution();
527 ret = qs.getLiteral("count").getInt();
528
529 }
530 return ret;
531
532 }
533
534 /**
535 * low level, executes query returns JSON.
536 *
537 * @param sparqlQueryString
538 * The query
539 */
540 public String query(String sparqlQueryString) {
541 String jsonString;
542 if (cache == null) {
543
544 SparqlQuery sq = new SparqlQuery(sparqlQueryString, sparqlEndpoint);
545 //SimpleClock sc = new SimpleClock();
546 sq.send();
547 //sc.printAndSet("querysend");
548 jsonString = sq.getJson();
549
550 } else {
551 jsonString = cache.executeSparqlQuery(new SparqlQuery(
552 sparqlQueryString, sparqlEndpoint));
553 }
554 return jsonString;
555 }
556
557 public boolean ask(String askQueryString) {
558 if(cache == null) {
559 SparqlQuery sq = new SparqlQuery(askQueryString, sparqlEndpoint);
560 return sq.sendAsk();
561 } else {
562 return cache.executeSparqlAskQuery(new SparqlQuery(askQueryString, sparqlEndpoint));
563 }
564 }
565
566 /**
567 * a String Helper which constructs the limit clause of a sparql query. if
568 * sparqlResultLimit is zero, returns nothing
569 *
570 * @param sparqlResultLimit
571 * the resultsetlimit
572 * @return LIMIT sparqlResultLimit if bigger than zero, else returns "";
573 */
574 private String limit(int sparqlResultLimit) {
575 return (sparqlResultLimit > 0) ? (" LIMIT " + sparqlResultLimit) : "";
576 }
577
578 public static SortedSet<String> getStringSetForVariableFromResultSet(
579 ResultSetRewindable rs, String variable) {
580 final SortedSet<String> result = new TreeSet<String>();
581
582 @SuppressWarnings("unchecked")
583 final List<QuerySolution> l = ResultSetFormatter.toList(rs);
584
585 for (QuerySolution resultBinding : l) {
586 result.add(resultBinding.get(variable).toString());
587 }
588 rs.reset();
589 return result;
590
591 }
592
593 private static SortedSet<StringTuple> getTuplesFromResultSet(
594 ResultSetRewindable rs, String predicate, String object) {
595 final SortedSet<StringTuple> returnSet = new TreeSet<StringTuple>();
596 //SimpleClock sc = new SimpleClock();
597 @SuppressWarnings("unchecked")
598 final List<QuerySolution> l = ResultSetFormatter.toList(rs);
599 for (QuerySolution resultBinding : l) {
600 returnSet.add(new StringTuple(resultBinding.get(predicate).toString(),resultBinding.get(object).toString()));
601 }
602 //sc.printAndSet("allTuples");
603 rs.reset();
604 //sc.printAndSet("reset");
605 return returnSet;
606
607 }
608
609 public SparqlEndpoint getSparqlEndpoint() {
610 return sparqlEndpoint;
611 }
612
613 public static SPARQLTasks getPredefinedSPARQLTasksWithCache(String endpointName) {
614 return new SPARQLTasks( Cache.getDefaultCache(), SparqlEndpoint.getEndpointByName(endpointName) );
615 }
616
617 // tries to detect the type of the resource
618 public Entity guessResourceType(String resource) {
619 SortedSet<String> types = retrieveObjectsForSubjectAndRole(resource, "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", 10000);
620 // System.out.println(types);
621 if(types.contains("http://www.w3.org/2002/07/owl#ObjectProperty")) {
622 return new ObjectProperty(resource);
623 } else if(types.contains("http://www.w3.org/2002/07/owl#DatatypeProperty")) {
624 return new DatatypeProperty(resource);
625 } else if(types.contains("http://www.w3.org/2002/07/owl#Class")) {
626 return new NamedClass(resource);
627 } else {
628 return null;
629 }
630 }
631
632 public Set<ObjectProperty> getAllObjectProperties() {
633 Set<ObjectProperty> properties = new TreeSet<ObjectProperty>();
634 String query = "PREFIX owl: <http://www.w3.org/2002/07/owl#> SELECT ?p WHERE {?p a owl:ObjectProperty}";
635 SparqlQuery sq = new SparqlQuery(query, sparqlEndpoint);
636 ResultSet q = sq.send();
637 while (q.hasNext()) {
638 QuerySolution qs = q.next();
639 properties.add(new ObjectProperty(qs.getResource("p").getURI()));
640 }
641 return properties;
642 }
643
644 public Set<DatatypeProperty> getAllDataProperties() {
645 Set<DatatypeProperty> properties = new TreeSet<DatatypeProperty>();
646 String query = "PREFIX owl: <http://www.w3.org/2002/07/owl#> SELECT ?p WHERE {?p a owl:DatatypeProperty}";
647 SparqlQuery sq = new SparqlQuery(query, sparqlEndpoint);
648 ResultSet q = sq.send();
649 while (q.hasNext()) {
650 QuerySolution qs = q.next();
651 properties.add(new DatatypeProperty(qs.getResource("p").getURI()));
652 }
653 return properties;
654 }
655
656 public Set<NamedClass> getAllClasses() {
657 Set<NamedClass> classes = new TreeSet<NamedClass>();
658 String query = "PREFIX owl: <http://www.w3.org/2002/07/owl#> SELECT ?c WHERE {?c a owl:Class}";
659 SparqlQuery sq = new SparqlQuery(query, sparqlEndpoint);
660 ResultSet q = sq.send();
661 while (q.hasNext()) {
662 QuerySolution qs = q.next();
663 classes.add(new NamedClass(qs.getResource("c").getURI()));
664 }
665 return classes;
666 }
667
668 }
669
670 /*
671 * here are some old functions, which were workarounds:
672 *
673 *
674 * workaround for a sparql glitch {?a owl:subclassOf ?b} returns an
675 * empty set on some endpoints. returns all direct subclasses of String concept
676 *
677 * @param concept An URI string with no quotes @return SortedSet of direct
678 * subclasses as String
679 *
680 * private SortedSet<String> getDirectSubClasses(String concept) {
681 *
682 * String sparqlQueryString; SortedSet<String> subClasses = new TreeSet<String>();
683 * ResultSet resultSet;
684 *
685 * sparqlQueryString = "SELECT * \n " + "WHERE { \n" + " ?subject ?predicate <" +
686 * concept + "> \n" + "}\n";
687 *
688 * resultSet = queryAsResultSet(sparqlQueryString);
689 *
690 * @SuppressWarnings("unchecked") List<ResultBinding> bindings =
691 * ResultSetFormatter.toList(resultSet); String subject = ""; String predicate =
692 * "";
693 *
694 * for (ResultBinding resultBinding : bindings) {
695 *
696 * subject = ((resultBinding.get("subject").toString())); predicate =
697 * ((resultBinding.get("predicate").toString())); if (predicate
698 * .equalsIgnoreCase("http://www.w3.org/2000/01/rdf-schema#subClassOf")) {
699 * subClasses.add(subject); } } return subClasses; }
700 *
701 *
702 *
703 *
704 *
705 *
706 *
707 */
708