Logo Search packages:      
Sourcecode: f-spot version File versions  Download package

Remote.cs

using System;
using System.Collections;
using System.IO;
using System.Text;
using System.Web;
using System.Xml;
 
namespace SemWeb.Remote {

      public class SparqlHttpSource : SelectableSource {
      
            string url;
            
            public SparqlHttpSource(string url) {
                  this.url = url;
            }

            public bool Distinct { get { return true; } }
            
            public bool Contains(Statement template) {
                  return Select(template, null, true);
            }
            
            public void Select(StatementSink sink) {
                  Select(Statement.All, sink);
            }
            
            public void Select(Statement template, StatementSink sink) {
                  Select(template, sink, false);
            }
            
            bool Select(Statement template, StatementSink sink, bool ask) {
                  return Select(
                        template.Subject == null ? null : new Entity[] { template.Subject },
                        template.Predicate == null ? null : new Entity[] { template.Predicate },
                        template.Object == null ? null : new Resource[] { template.Object },
                        template.Meta == null ? null : new Entity[] { template.Meta },
                        null,
                        0,
                        sink,
                        ask
                        );
            }
            
            public void Select(SelectFilter filter, StatementSink sink) {
                  Select(filter.Subjects, filter.Predicates, filter.Objects, filter.Metas, filter.LiteralFilters, filter.Limit, sink, false);
            }
            
            bool Select(Entity[] subjects, Entity[] predicates, Resource[] objects, Entity[] metas, LiteralFilter[] litFilters, int limit, StatementSink sink, bool ask) {
                  // TODO: Change meta into named graphs.  Anything but a null or DefaultMeta
                  // meta returns no statements immediately.
                  if (metas != null && (metas.Length != 1 || metas[0] != Statement.DefaultMeta))
                        return false;
            
                  string query;
                  bool nonull = false;
            
                  if (subjects != null && subjects.Length == 1
                        && predicates != null && predicates.Length == 1
                        && objects != null && objects.Length == 1) {
                        query = "ASK WHERE { " + S(subjects[0], null) + " " + S(predicates[0], null) + " " + S(objects[0], null) + "}";
                        nonull = true;
                  } else {
                        if (ask)
                              query = "ASK";
                        else
                              query = "SELECT *";
                        query += " WHERE { ";
                        query += S(subjects, "subject");
                        query += " ";
                        query += S(predicates, "predicate");
                        query += " ";
                        query += S(objects, "object");
                        query += " . ";
                        query += SL(subjects, "subject");
                        query += SL(predicates, "predicate");
                        query += SL(objects, "object");
                        query += " }";
                        
                        // TODO: Pass literal filters to server.
                  }
                  
                  if (limit >= 1)
                        query += " LIMIT " + limit;
                  
                  XmlDocument result = Load(query);
                  
                  if (ask || nonull) {
                        foreach (XmlElement boolean in result.DocumentElement) {
                              if (boolean.Name != "boolean") continue;
                              bool ret = boolean.InnerText == "true";
                              if (ask)
                                    return ret;
                              else if (ret)
                                    sink.Add(new Statement(subjects[0], predicates[0], objects[0]));
                              return false;
                        }
                        throw new ApplicationException("Invalid server response: No boolean node.");
                  }
                  
                  XmlElement bindings = null;
                  foreach (XmlElement e in result.DocumentElement)
                        if (e.Name == "results")
                              bindings = e;
                  if (bindings == null)
                        throw new ApplicationException("Invalid server response: No result node.");
                  
                  MemoryStore distinctCheck = null;
                  if (bindings.GetAttribute("distinct") != "true")
                        distinctCheck = new MemoryStore();
                  
                  Hashtable bnodes = new Hashtable();
                  
                  foreach (XmlNode bindingnode in bindings) {
                        if (!(bindingnode is XmlElement)) continue;
                        XmlElement binding = (XmlElement)bindingnode;
                        Resource subj = GetBinding(binding, "subject", subjects, bnodes);
                        Resource pred = GetBinding(binding, "predicate", predicates, bnodes);
                        Resource obj = GetBinding(binding, "object", objects, bnodes);
                        if (!(subj is Entity) || !(pred is Entity)) continue;
                        Statement s = new Statement((Entity)subj, (Entity)pred, obj);
                        if (distinctCheck != null && distinctCheck.Contains(s)) continue;
                        if (litFilters != null && !LiteralFilter.MatchesFilters(s.Object, litFilters, this)) continue;
                        if (!sink.Add(s)) return true;
                        if (distinctCheck != null) distinctCheck.Add(s);
                  }
                  
                  return true;
            }
            
            string S(Resource[] r, string v) {
                  if (r == null || r.Length != 1) return "?" + v;
                  return S(r[0], null);
            }
            string SL(Resource[] r, string v) {
                  if (r == null || r.Length <= 1) return "";
                  StringBuilder ret = new StringBuilder();
                  ret.Append("FILTER(");
                  bool first = true;
                  for (int i = 0; i < r.Length; i++) {
                        if (r[i].Uri == null) continue;
                        if (!first) ret.Append(" || "); first = false;
                        ret.Append('?');
                        ret.Append(v);
                        ret.Append("=<");
                        if (r[i].Uri != null)
                              ret.Append(r[i].Uri);
                        ret.Append('>');
                  }
                  ret.Append(").");
                  if (first) return "";
                  return ret.ToString();
            }
            
            string S(Resource r, string v) {
                  if (r == null) {
                        return v;
                  } else if (r is Literal) {
                        return r.ToString();
                  } else if (r.Uri != null) {
                        if (r.Uri.IndexOf('>') != -1)
                              throw new ArgumentException("Invalid URI: " + r.Uri);
                        return "<" + r.Uri + ">";
                  } else {
                        throw new ArgumentException("Blank node in select not supported.");
                  }
            }
            
            Resource GetBinding(XmlElement binding, string v, Resource[] values, Hashtable bnodes) {
                  if (values != null && values.Length == 1) return values[0];
                  
                  XmlElement b = (XmlElement)binding.FirstChild;
                  while (b != null && b.GetAttribute("name") != v)
                        b = (XmlElement)b.NextSibling;
                  if (b == null)
                        throw new ApplicationException("Invalid server response: Not all bindings present (" + v + "): " + binding.OuterXml);
                  
                  b = (XmlElement)b.FirstChild;
                  if (b.Name == "uri")
                        return new Entity(b.InnerText);
                  else if (b.Name == "literal")
                        return new Literal(b.InnerText); // datatype/lang
                  else if (b.Name == "bnode") {
                        string id = b.InnerText;
                        if (bnodes.ContainsKey(id)) return (Entity)bnodes[id];
                        Entity ret = new BNode();
                        bnodes[id] = ret;
                        return ret;
                  }
                  throw new ApplicationException("Invalid server response: " + b.OuterXml);
            }
            
            XmlDocument Load(string query) {
                  string qstr = "query=" + System.Web.HttpUtility.UrlEncode(query);
                  
                  string method = "POST";
                  
                  System.Net.WebRequest rq;
                  
                  if (method == "GET") {
                        string qurl = url + "?" + qstr;
                        rq = System.Net.WebRequest.Create(qurl);
                  } else {
                        ASCIIEncoding encoding = new ASCIIEncoding(); // ?
                        byte[] data = encoding.GetBytes(qstr);

                        rq = System.Net.WebRequest.Create(url);
                        rq.Method = "POST";
                        rq.ContentType="application/x-www-form-urlencoded";
                        rq.ContentLength = data.Length;
                        
                        using (Stream stream = rq.GetRequestStream())
                              stream.Write(data, 0, data.Length);
                  }
                  
                  System.Net.WebResponse resp = rq.GetResponse();
                  
                  string mimetype = resp.ContentType;
                  if (mimetype.IndexOf(';') > -1)
                        mimetype = mimetype.Substring(0, mimetype.IndexOf(';'));
                  
                  if (mimetype != "application/sparql-results+xml")
                        throw new ApplicationException("The result of the query was not a SPARQL Results document.");

                  XmlDocument ret = new XmlDocument();
                  ret.Load(new StreamReader(resp.GetResponseStream(), System.Text.Encoding.UTF8));
                                    
                  if (ret.DocumentElement.Name != "sparql")
                        throw new ApplicationException("Invalid server response: Not a sparql results document.");
                  
                  return ret;
            }
            
            public Entity[] FindEntities(Statement[] graph) {
                  string query = "SELECT ?entity WHERE { ";
                  
                  foreach (Statement s in graph) {
                        query += S(s.Subject, "?entity");
                        query += " ";
                        query += S(s.Predicate, "?entity");
                        query += " ";
                        query += S(s.Object, "?entity");
                        query += " . ";
                        if (s.Meta != Statement.DefaultMeta) return new Entity[0];
                  }
                  
                  query += "}";
                  
                  XmlDocument result = Load(query);
                  
                  XmlElement bindings = null;
                  foreach (XmlElement e in result.DocumentElement)
                        if (e.Name == "results")
                              bindings = e;
                  if (bindings == null)
                        throw new ApplicationException("Invalid server response: No result node.");
                  
                  Hashtable bnodes = new Hashtable();
                  ArrayList ret = new ArrayList();
                  
                  foreach (XmlElement binding in bindings) {
                        Entity e = (Entity)GetBinding(binding, "entity", null, bnodes);
                        ret.Add(e);
                  }
                  
                  return (Entity[])ret.ToArray(typeof(Entity));
            }

      }
}


Generated by  Doxygen 1.6.0   Back to index