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