1 // © 2020 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 4 package org.unicode.cldr.rdf; 5 6 import java.io.IOException; 7 import java.nio.charset.StandardCharsets; 8 import java.util.Iterator; 9 10 import org.apache.jena.ext.com.google.common.io.Resources; 11 import org.apache.jena.query.Query; 12 import org.apache.jena.query.QueryExecutionFactory; 13 import org.apache.jena.query.QueryFactory; 14 import org.apache.jena.query.QuerySolution; 15 import org.apache.jena.query.ResultSet; 16 import org.apache.jena.rdf.model.Literal; 17 import org.apache.jena.rdf.model.RDFNode; 18 import org.apache.jena.rdf.model.Resource; 19 import org.apache.jena.sparql.engine.http.QueryEngineHTTP; 20 import org.unicode.cldr.util.Timer; 21 22 /** 23 * Class to aid in SPARQL queries 24 * @author srl295 25 * 26 */ 27 public class QueryClient { 28 final static class QueryClientHelper { 29 private static QueryClient INSTANCE = new QueryClient(); 30 } 31 getInstance()32 public static final QueryClient getInstance() { 33 return QueryClientHelper.INSTANCE; 34 } 35 36 public static final String DEFAULT_CLDR_DBPEDIA_SPARQL_SERVER = "https://dbpedia.org/sparql/"; 37 public static final String DBPEDIA_SPARQL_SERVER = System.getProperty("CLDR_DBPEDIA_SPARQL_SERVER", DEFAULT_CLDR_DBPEDIA_SPARQL_SERVER); 38 39 public static final String DEFAULT_CLDR_WIKIDATA_SPARQL_SERVER = "https://query.wikidata.org/sparql"; 40 public static final String WIKIDATA_SPARQL_SERVER = System.getProperty("CLDR_WIKIDATA_SPARQL_SERVER", DEFAULT_CLDR_WIKIDATA_SPARQL_SERVER); 41 42 public static final String PREFIX_PLG = "http://purl.org/linguistics/gold/"; 43 public static final String PREFIX_RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; 44 public static final String PREFIX_DBO = "http://dbpedia.org/ontology/"; 45 public static final String PREFIX_DBP = "http://dbpedia.org/property/"; 46 public static final String PREFIX_DBR = "http://dbpedia.org/resource/"; 47 public static final String PREFIX_YAGO = "http://dbpedia.org/class/yago/"; 48 public static final String abstractLang = "en"; // for now 49 getLiteralOrNull(final QuerySolution qs, final String k)50 public static final String getLiteralOrNull(final QuerySolution qs, final String k) { 51 final Literal l = qs.getLiteral(k); 52 return getLiteralOrNull(l); 53 } 54 getLiteralOrNull(final Literal l)55 private static String getLiteralOrNull(final Literal l) { 56 if(l == null) return null; 57 return l.getString(); 58 } 59 60 /** 61 * Convert the specified parameter into a String, or null if not found. 62 * @param qs 63 * @param k 64 * @return 65 */ getStringOrNull(final QuerySolution qs, final String k)66 public static final String getStringOrNull(final QuerySolution qs, final String k) { 67 RDFNode node = qs.get(k); 68 return getStringOrNull(node); 69 } 70 getStringOrNull(RDFNode node)71 private static String getStringOrNull(RDFNode node) { 72 if(node == null) { 73 return null; // not found 74 } else if(node.isLiteral()) { 75 return getLiteralOrNull(node.asLiteral()); 76 } else if(node.isResource()) { 77 return getResourceOrNull(node.asResource()); 78 } else { 79 throw new UnsupportedOperationException("Not supported: node type " + node.toString()); 80 } 81 } 82 getResourceOrNull(final QuerySolution qs, final String k)83 public static final String getResourceOrNull(final QuerySolution qs, final String k) { 84 final Resource l = qs.getResource(k); 85 return getResourceOrNull(l); 86 } getResourceOrNull(final Resource l)87 private static String getResourceOrNull(final Resource l) { 88 if(l == null) return null; 89 return l.getURI(); 90 } 91 92 /** 93 * Run a query 94 * @param q 95 * @return 96 */ execSelect(Query q)97 public ResultSet execSelect(Query q) { 98 return execSelect(q, QueryClient.DBPEDIA_SPARQL_SERVER); 99 } 100 execSelect(Query q, final String server)101 public ResultSet execSelect(Query q, final String server) { 102 Timer t = new Timer(); 103 QueryEngineHTTP qEngine = QueryExecutionFactory.createServiceRequest(server, q); 104 // qEngine.setHttpContext(httpContext); 105 ResultSet results = qEngine.execSelect(); 106 System.out.println("SparQL query complete in " + t); 107 return results; 108 } 109 110 /** 111 * @param resName resource such as "wikidata-childToParent.sparql" 112 * @param server server name 113 * @return 114 * @throws IOException 115 */ execSelectFromSparql(final String resName, final String server)116 public ResultSet execSelectFromSparql(final String resName, final String server) throws IOException { 117 final Query q = loadSparql(resName); 118 return execSelect(q, server); 119 } 120 121 /** 122 * A little routine to dump a ResultSet out to the command line. 123 * Note that it is destructive to the ResultSet, so can't be combined with other processing. 124 * @param rs 125 */ dumpResults(ResultSet rs)126 public static void dumpResults(ResultSet rs) { 127 System.out.println("RESULTS:" + rs.getResultVars()); 128 for(;rs.hasNext();) { 129 QuerySolution qs = rs.next(); 130 Iterator<String> vn = qs.varNames(); 131 for(;vn.hasNext();) { 132 final String k = vn.next(); 133 System.out.println(k+"="+qs.get(k).toString()); 134 } 135 System.out.println(); 136 } 137 } 138 /** 139 * Load a query from a resource 140 * @param resName 141 * @return 142 * @throws IOException 143 */ loadSparql(final String resName)144 public static Query loadSparql(final String resName) throws IOException { 145 final String str = Resources.toString(Resources.getResource(QueryClient.class, "sparql/"+resName+".sparql"), StandardCharsets.UTF_8); 146 return QueryFactory.create(str); 147 } 148 } 149 150 151