public override void Init(Variable[] variables) { vars = new Variable[variables.Length]; for (int i = 0; i < variables.Length; i++) { vars[i] = (Variable)variableNames[variables[i].LocalName]; } sink.Init(vars); }
public void Query(Statement[] graph, QueryOptions options, QueryResultSink sink) { if (options.DistinguishedVariables != null && options.DistinguishedVariables.Count == 0) { throw new ArgumentException("options.DistinguishedVariables cannot be an empty list."); } StringBuilder query = new StringBuilder(); query.Append("SELECT "); // Get a list of variables and map them to fresh names #if !DOTNET2 Hashtable variableNames = new Hashtable(); #else Dictionary <Variable, string> variableNames = new Dictionary <Variable, string>(); #endif Hashtable variableNames2 = new Hashtable(); foreach (Statement s in graph) { for (int j = 0; j < 3; j++) { Variable v = s.GetComponent(j) as Variable; if (v == null) { continue; } if (variableNames.ContainsKey(v)) { continue; } variableNames2["v" + variableNames.Count] = v; variableNames[v] = "?v" + variableNames.Count; } } // What variables will we select on? ArrayList selectedVars = new ArrayList(); foreach (Variable v in options.DistinguishedVariables != null ? options.DistinguishedVariables : variableNames.Keys) { if (!variableNames.ContainsKey(v)) { continue; // in case distinguished variables list } // has more than what actually appears in query if (selectedVars.Contains(v)) { continue; // don't select more than once } query.Append(variableNames[v]); query.Append(' '); selectedVars.Add(v); } if (selectedVars.Count == 0) { if (options.DistinguishedVariables == null) { throw new ArgumentException("There were no variables in the query."); } else { throw new ArgumentException("None of the variables in the query were distinguished."); } } // Bnodes are not allowed here -- we can't query on them. foreach (Statement s in graph) { for (int j = 0; j < 3; j++) { if (s.GetComponent(j) is BNode && !(s.GetComponent(j) is Variable)) { Variable[] varArray = (Variable[])selectedVars.ToArray(typeof(Variable)); sink.Init(varArray); sink.Finished(); return; } } } // Build the graph pattern. query.Append("WHERE {\n"); ResSet firstVarUse = new ResSet(); foreach (Statement s in graph) { for (int j = 0; j < 3; j++) { Resource r = s.GetComponent(j); query.Append(S(r, r is Variable && variableNames.ContainsKey((Variable)r) ? (string)variableNames[(Variable)r] : null)); query.Append(" "); } query.Append(" . \n"); if (options.VariableKnownValues != null) { for (int j = 0; j < 3; j++) { Resource r = s.GetComponent(j); if (firstVarUse.Contains(r)) { continue; } firstVarUse.Add(r); if (r is Variable && variableNames.ContainsKey((Variable)r) && #if !DOTNET2 options.VariableKnownValues.Contains(r) #else options.VariableKnownValues.ContainsKey((Variable)r) #endif ) { query.Append(SL(options.VariableKnownValues[(Variable)r], (string)variableNames[(Variable)r], true)); } } } // And what about meta...? } query.Append("}"); if (options.Limit > 0) { query.Append(" LIMIT "); query.Append(options.Limit); } Load(query.ToString(), new QueryResultsWrapper(sink, variableNames2)); }
private static void ProcessResponse(string mimetype, Stream stream, object outputObj) { // If the user wants the output sent to a TextWriter, copy the response from // the response stream to the TextWriter. TODO: Get encoding from HTTP header. if (outputObj is TextWriter) { TextWriter tw = (TextWriter)outputObj; using (StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8)) { char[] buffer = new char[512]; while (true) { int len = reader.Read(buffer, 0, buffer.Length); if (len <= 0) { break; } tw.Write(buffer, 0, len); if (Debug) { Console.Error.WriteLine(">> " + new String(buffer, 0, len)); } } } tw.Flush(); return; } // If the user wants a boolean out of this, then we're expecting a // SPARQL XML Results document with a boolean response element. if (outputObj is BooleanWrap) { BooleanWrap bw = (BooleanWrap)outputObj; if (mimetype != null && mimetype != "application/sparql-results+xml" && mimetype != "text/xml" && mimetype != "application/xml") { throw new ApplicationException("The result of the query was not a SPARQL Results document."); } XmlReader xmldoc = new XmlTextReader(stream); { // Move to the document element while (xmldoc.Read()) { if (xmldoc.NodeType == XmlNodeType.Element) { break; } } // Just check that it has the right local name. if (xmldoc.LocalName != "sparql" || xmldoc.IsEmptyElement) { throw new ApplicationException("Invalid server response: Not a SPARQL results document."); } // Move to the next node. while (xmldoc.Read()) { if (xmldoc.NodeType == XmlNodeType.Element) { break; } } // If it's a head node, skip it. if (xmldoc.LocalName == "head") { xmldoc.Skip(); // Move to the 'boolean' element, it better be next while (xmldoc.Read()) { if (xmldoc.NodeType == XmlNodeType.Element) { break; } } } if (xmldoc.LocalName != "boolean") { throw new ApplicationException("Invalid server response: Missing 'boolean' element."); } string value = xmldoc.ReadElementString(); bw.value = (value == "true"); } if (Debug) { Console.Error.WriteLine(">> " + bw.value); } return; } // If the user wants statements out of the response, read it with an RDFReader. if (outputObj is StatementSink) { // If the mime type is application/sparql-results+xml, just try to // read it as if it were an RDF/XML MIME type. if (mimetype != null && mimetype == "application/sparql-results+xml") { mimetype = "text/xml"; } using (RdfReader reader = RdfReader.Create(mimetype, stream)) reader.Select((StatementSink)outputObj); if (Debug) { Console.Error.WriteLine(">> (read as statements)"); } return; } // If the user wants query result bindings, read the response XML. if (outputObj is QueryResultSink) { QueryResultSink sink = (QueryResultSink)outputObj; if (mimetype != null && mimetype != "application/sparql-results+xml" && mimetype != "text/xml") { throw new ApplicationException("The result of the query was not a SPARQL Results document."); } ArrayList variableNames = new ArrayList(); ArrayList variables = new ArrayList(); Variable[] variablesArray = null; Hashtable bnodes = new Hashtable(); XmlReader xmldoc = new XmlTextReader(stream); { // Move to the document element while (xmldoc.Read()) { if (xmldoc.NodeType == XmlNodeType.Element) { break; } } // Just check that it has the right local name. if (xmldoc.LocalName != "sparql" || xmldoc.IsEmptyElement) { throw new ApplicationException("Invalid server response: Not a SPARQL results document."); } // Move to the 'head' node, it better be the first element while (xmldoc.Read()) { if (xmldoc.NodeType == XmlNodeType.Element) { break; } } if (xmldoc.LocalName != "head" || xmldoc.IsEmptyElement) { throw new ApplicationException("Invalid server response: Missing head full element."); } // Read the head element while (xmldoc.Read()) { if (xmldoc.NodeType == XmlNodeType.Element && xmldoc.LocalName == "variable") { if (xmldoc.GetAttribute("name") == null) { throw new ApplicationException("Invalid server response: Head/variable node missing name attribute."); } variableNames.Add(xmldoc.GetAttribute("name")); variables.Add(new Variable(xmldoc.GetAttribute("name"))); if (!xmldoc.IsEmptyElement) { xmldoc.Skip(); } } else if (xmldoc.NodeType == XmlNodeType.EndElement) { break; } } // Move to the 'results' element, it better be next while (xmldoc.Read()) { if (xmldoc.NodeType == XmlNodeType.Element) { break; } } if (xmldoc.LocalName != "results") { throw new ApplicationException("Invalid server response: Missing results element."); } variablesArray = (Variable[])variables.ToArray(typeof(Variable)); sink.Init(variablesArray); // Read the results while (xmldoc.Read()) { if (xmldoc.NodeType == XmlNodeType.Element && xmldoc.LocalName == "result") { // Read the bindings in this result Resource[] valuesArray = new Resource[variablesArray.Length]; while (xmldoc.Read()) { if (xmldoc.NodeType == XmlNodeType.Element && xmldoc.LocalName == "binding") { if (xmldoc.IsEmptyElement) { throw new ApplicationException("Invalid server response: Binding element empty."); } if (xmldoc.GetAttribute("name") == null) { throw new ApplicationException("Invalid server response: Result binding node missing name attribute."); } int vIndex = variableNames.IndexOf(xmldoc.GetAttribute("name")); if (vIndex == -1) { throw new ApplicationException("Invalid server response: Result binding name does not match a variable in the head."); } Resource value = null; while (xmldoc.Read()) { if (xmldoc.NodeType == XmlNodeType.Whitespace || xmldoc.NodeType == XmlNodeType.SignificantWhitespace) { continue; } if (xmldoc.NodeType == XmlNodeType.Element && xmldoc.LocalName == "uri") { value = new Entity(xmldoc.ReadElementString()); if (!xmldoc.IsEmptyElement) { xmldoc.Skip(); } } else if (xmldoc.NodeType == XmlNodeType.Element && xmldoc.LocalName == "literal") { string lang = xmldoc.XmlLang; if (lang == "") { lang = null; } string dt = xmldoc.GetAttribute("datatype"); value = new Literal(xmldoc.ReadElementString(), lang, dt); if (!xmldoc.IsEmptyElement) { xmldoc.Skip(); } } else if (xmldoc.NodeType == XmlNodeType.Element && xmldoc.LocalName == "bnode") { string id = xmldoc.ReadElementString(); if (bnodes.ContainsKey(id)) { value = (BNode)bnodes[id]; } else { value = new BNode(id); bnodes[id] = value; } if (!xmldoc.IsEmptyElement) { xmldoc.Skip(); } } else { throw new ApplicationException("Invalid server response: Invalid content in binding node."); } break; } if (value == null) { throw new ApplicationException("Invalid server response: Result binding value is invalid."); } valuesArray[vIndex] = value; } else if (xmldoc.NodeType == XmlNodeType.EndElement) { break; } } sink.Add(new VariableBindings(variablesArray, valuesArray)); if (Debug) { Console.Error.WriteLine(">> " + new VariableBindings(variablesArray, valuesArray)); } } else if (xmldoc.NodeType == XmlNodeType.EndElement) { break; } } sink.Finished(); } } }