beagle r4770 - in trunk/beagle: . Util/SemWeb
- From: dbera svn gnome org
- To: svn-commits-list gnome org
- Subject: beagle r4770 - in trunk/beagle: . Util/SemWeb
- Date: Mon, 2 Jun 2008 11:28:04 +0000 (UTC)
Author: dbera
Date: Mon Jun 2 11:28:03 2008
New Revision: 4770
URL: http://svn.gnome.org/viewvc/beagle?rev=4770&view=rev
Log:
Update SemWeb. Make a note that we are incorporating SemWeb under the GPLv3 license. Merge the upstream changes into a single file.
Added:
trunk/beagle/Util/SemWeb/README.txt
- copied, changed from r4763, /trunk/beagle/Util/SemWeb/README
trunk/beagle/Util/SemWeb/upstream-change.diff
Removed:
trunk/beagle/Util/SemWeb/README
trunk/beagle/Util/SemWeb/upstream-change-01.diff
trunk/beagle/Util/SemWeb/upstream-change-02.diff
Modified:
trunk/beagle/COPYING
trunk/beagle/Util/SemWeb/AssemblyInfo.cs
trunk/beagle/Util/SemWeb/Euler.cs
trunk/beagle/Util/SemWeb/GraphMatch.cs
trunk/beagle/Util/SemWeb/Inference.cs
trunk/beagle/Util/SemWeb/Interfaces.cs
trunk/beagle/Util/SemWeb/N3Reader.cs
trunk/beagle/Util/SemWeb/N3Writer.cs
trunk/beagle/Util/SemWeb/Query.cs
trunk/beagle/Util/SemWeb/RdfReader.cs
trunk/beagle/Util/SemWeb/RdfXmlReader.cs
trunk/beagle/Util/SemWeb/Resource.cs
trunk/beagle/Util/SemWeb/SQLStore.cs
trunk/beagle/Util/SemWeb/SparqlClient.cs
trunk/beagle/Util/SemWeb/SpecialRelations.cs
trunk/beagle/Util/SemWeb/Store.cs
trunk/beagle/Util/SemWeb/UriMap.cs
trunk/beagle/Util/SemWeb/Util.cs
Modified: trunk/beagle/COPYING
==============================================================================
--- trunk/beagle/COPYING (original)
+++ trunk/beagle/COPYING Mon Jun 2 11:28:03 2008
@@ -9,7 +9,7 @@
* Hal# - MIT License
* HtmlAgilityPack - BSD License
* Parts of libegg (eggaccelerators.c and eggtrayicon.c) - GNU LGPL v2
- * SemWeb - Creative Commons Attribution License
+ * SemWeb - GPLv3
* System.Windows.Forms.RTF - MIT License
* jslib - Mozilla Public License v1.1
* xdgmime - Academic Free License v2.0 or GNU LGPL v2
Modified: trunk/beagle/Util/SemWeb/AssemblyInfo.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/AssemblyInfo.cs (original)
+++ trunk/beagle/Util/SemWeb/AssemblyInfo.cs Mon Jun 2 11:28:03 2008
@@ -10,7 +10,7 @@
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("1.0.3.0")]
+[assembly: AssemblyVersion("1.0.6.0")]
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]
Modified: trunk/beagle/Util/SemWeb/Euler.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/Euler.cs (original)
+++ trunk/beagle/Util/SemWeb/Euler.cs Mon Jun 2 11:28:03 2008
@@ -17,7 +17,11 @@
public class Euler : Reasoner {
+ #if !SILVERLIGHT
static bool Debug = System.Environment.GetEnvironmentVariable("SEMWEB_DEBUG_EULER") != null;
+ #else
+ static bool Debug = false;
+ #endif
Hashtable rules;
@@ -25,12 +29,14 @@
static Euler() {
RdfRelation[] rs = new RdfRelation[] {
+ #if !SILVERLIGHT
new SemWeb.Inference.Relations.MathAbsoluteValueRelation(), new SemWeb.Inference.Relations.MathCosRelation(), new SemWeb.Inference.Relations.MathDegreesRelation(), new SemWeb.Inference.Relations.MathEqualToRelation(),
new SemWeb.Inference.Relations.MathNegationRelation(), new SemWeb.Inference.Relations.MathRoundedRelation(), new SemWeb.Inference.Relations.MathSinRelation(), new SemWeb.Inference.Relations.MathSinhRelation(), new SemWeb.Inference.Relations.MathTanRelation(), new SemWeb.Inference.Relations.MathTanhRelation(),
new SemWeb.Inference.Relations.MathAtan2Relation(), new SemWeb.Inference.Relations.MathDifferenceRelation(), new SemWeb.Inference.Relations.MathExponentiationRelation(), new SemWeb.Inference.Relations.MathIntegerQuotientRelation(),
new SemWeb.Inference.Relations.MathQuotientRelation(), new SemWeb.Inference.Relations.MathRemainderRelation(),
new SemWeb.Inference.Relations.MathSumRelation(), new SemWeb.Inference.Relations.MathProductRelation(),
new SemWeb.Inference.Relations.MathGreaterThanRelation(), new SemWeb.Inference.Relations.MathLessThanRelation(), new SemWeb.Inference.Relations.MathNotGreaterThanRelation(), new SemWeb.Inference.Relations.MathNotLessThanRelation(), new SemWeb.Inference.Relations.MathNotEqualToRelation()
+ #endif
};
builtInRelations = new Hashtable();
@@ -232,9 +238,8 @@
public Hashtable env; // substitution environment: Resource => Resource
public ArrayList ground;
- public QueueItem Clone() {
- return (QueueItem)MemberwiseClone();
- }
+ public int liveChildren = 0;
+ public StatementList solutions;
public override string ToString() {
string ret = "";
@@ -265,6 +270,8 @@
if (world != null) // cache our queries to the world, if a world is provided
world = new SemWeb.Stores.CachedSource(world);
+ StatementMap cached_subproofs = new StatementMap();
+
// Create the queue and add the first item.
ArrayList queue = new ArrayList();
{
@@ -335,15 +342,20 @@
r.rule = c.parent.rule;
r.src = c.parent.src;
r.ind = c.parent.ind;
- r.parent = c.parent.parent != null
- ? c.parent.parent.Clone()
- : null;
+ r.parent = c.parent.parent;
r.env = (Hashtable)c.parent.env.Clone();
r.ground = g;
unify(c.rule.head, c.env, r.rule.body[r.ind], r.env, true);
r.ind++;
queue.Add(r);
if (Debug) Console.Error.WriteLine("Euler: Queue Advancement: " + r);
+
+ // The number of live children for this parent is decremented since we are
+ // done with this subproof, but we store the result for later.
+ if (c.parent.solutions == null)
+ c.parent.solutions = new StatementList();
+ c.parent.solutions.Add(evaluate(r.rule.body[r.ind-1], r.env));
+ decrementLife(c.parent, cached_subproofs);
}
// this sequent still has parts of the body left to be proved; try to
@@ -409,6 +421,12 @@
r.ground = g;
r.ind++;
queue.Add(r);
+
+ // Note: Since we are putting something back in for c, we don't touch the life counter on the parent.
+
+ } else {
+ // If the predicate fails, decrement the life of the parent.
+ decrementLife(c.parent, cached_subproofs);
}
continue;
}
@@ -418,48 +436,64 @@
Statement t_resolved = evaluate(t, c.env);
- // If resolving this statement requires putting a
- // literal in subject or predicate position, we
+ // If resolving this statement requires putting a literal in subject or predicate position, we
// can't prove it.
- if (t_resolved == Statement.All)
+ if (t_resolved == Statement.All) {
+ decrementLife(c.parent, cached_subproofs);
continue;
+ }
ArrayList tcases = new ArrayList();
- // get all of the rules that apply to the predicate in question
- if (t_resolved.Predicate != null && cases.ContainsKey(t_resolved.Predicate))
- tcases.AddRange((IList)cases[t_resolved.Predicate]);
-
- /*if (cases.ContainsKey("WILDCARD")) // not supported yet -- infinite regress not handled
- tcases.AddRange((IList)cases["WILDCARD"]);*/
-
- // if t has no unbound variables and we've matched something from
- // the axioms, don't bother looking at the world, and don't bother
- // proving it any other way than by the axiom.
- bool lookAtWorld = true;
- foreach (Sequent seq in tcases) {
- if (seq.body.Length == 0 && seq.head == t_resolved) {
- lookAtWorld = false;
- tcases.Clear();
- tcases.Add(seq);
- break;
+ // See if we have already tried to prove this.
+ if (cached_subproofs.ContainsKey(t_resolved)) {
+ StatementList cached_solutions = (StatementList)cached_subproofs[t_resolved];
+ if (cached_solutions == null) {
+ if (Debug) Console.Error.WriteLine("Euler: Dropping queue item because we have already failed to prove it: " + t_resolved);
+ } else {
+ foreach (Statement s in cached_solutions) {
+ if (Debug) Console.Error.WriteLine("Euler: Using Cached Axiom: " + s);
+ Sequent seq = new Sequent(s);
+ tcases.Add(seq);
+ }
}
- }
-
- // if there is a seprate world, get all of the world
- // statements that witness t
- if (world != null && lookAtWorld) {
- MemoryStore w = new MemoryStore();
-
- if (Debug) Console.WriteLine("Euler: Ask World: " + t_resolved);
- world.Select(t_resolved, w);
- foreach (Statement s in w) {
- if (Debug) Console.WriteLine("Euler: World Select Response: " + s);
- Sequent seq = new Sequent(s);
- tcases.Add(seq);
+ } else {
+ // get all of the rules that apply to the predicate in question
+ if (t_resolved.Predicate != null && cases.ContainsKey(t_resolved.Predicate))
+ tcases.AddRange((IList)cases[t_resolved.Predicate]);
+
+ if (cases.ContainsKey("WILDCARD"))
+ tcases.AddRange((IList)cases["WILDCARD"]);
+
+ // if t has no unbound variables and we've matched something from
+ // the axioms, don't bother looking at the world, and don't bother
+ // proving it any other way than by the axiom.
+ bool lookAtWorld = true;
+ foreach (Sequent seq in tcases) {
+ if (seq.body.Length == 0 && seq.head == t_resolved) {
+ lookAtWorld = false;
+ tcases.Clear();
+ tcases.Add(seq);
+ break;
+ }
+ }
+
+ // if there is a seprate world, get all of the world
+ // statements that witness t
+ if (world != null && lookAtWorld) {
+ MemoryStore w = new MemoryStore();
+
+ if (Debug) Console.Error.WriteLine("Running " + c);
+ if (Debug) Console.Error.WriteLine("Euler: Ask World: " + t_resolved);
+ world.Select(t_resolved, w);
+ foreach (Statement s in w) {
+ if (Debug) Console.Error.WriteLine("Euler: World Select Response: " + s);
+ Sequent seq = new Sequent(s);
+ tcases.Add(seq);
+ }
}
}
-
+
// If there is no evidence or potential evidence (i.e. rules)
// for t, then we will dump this QueueItem by not queuing any
// subproofs.
@@ -483,17 +517,35 @@
if (ep.src == c.src && unify(ep.rule.head, ep.env, c.rule.head, c.env, false))
break;
if (ep == null) {
- queue.Insert(0, r);
+ // It is better for caching subproofs to work an entire proof out before
+ // going on, which means we want to put the new queue item at the
+ // top of the stack.
+ queue.Add(r);
+ c.liveChildren++;
if (Debug) Console.Error.WriteLine("Euler: Queue from Axiom: " + r);
}
}
}
+
+ // If we did not add anything back into the queue for this item, then
+ // we decrement the life of the parent.
+ if (c.liveChildren == 0)
+ decrementLife(c.parent, cached_subproofs);
}
}
return evidence;
}
+ private static void decrementLife(QueueItem q, StatementMap cached_subproofs) {
+ q.liveChildren--;
+ if (q.liveChildren == 0) {
+ Statement t = evaluate(q.rule.body[q.ind], q.env);
+ cached_subproofs[t] = q.solutions;
+ if (Debug && q.solutions == null) Console.Error.WriteLine("Euler: Died: " + q);
+ }
+ }
+
private static bool unify(Resource s, Hashtable senv, Resource d, Hashtable denv, bool f) {
if (s is Variable) {
Resource sval = evaluate(s, senv);
Modified: trunk/beagle/Util/SemWeb/GraphMatch.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/GraphMatch.cs (original)
+++ trunk/beagle/Util/SemWeb/GraphMatch.cs Mon Jun 2 11:28:03 2008
@@ -121,13 +121,23 @@
}
public override void Run(SelectableSource targetModel, QueryResultSink result) {
- QueryPart[] parts = new QueryPart[graph.Count];
- for (int i = 0; i < graph.Count; i++)
- parts[i] = new QueryPart(graph[i], targetModel);
+ Statement[] newgraph = ReorderQuery(graph.ToArray(), toArray(knownValues), targetModel, null);
+
+ QueryPart[] parts = new QueryPart[newgraph.Length];
+ for (int i = 0; i < newgraph.Length; i++)
+ parts[i] = new QueryPart(newgraph[i], targetModel);
RunGeneralQuery(parts, knownValues, litFilters, distinguishedVars.Count == 0 ? null : distinguishedVars, ReturnStart, ReturnLimit, false, result);
}
+ internal static Variable[] toArray(VarKnownValuesType2 kv) {
+ Variable[] ret = new Variable[kv.Count];
+ int ctr = 0;
+ foreach (Variable v in kv.Keys)
+ ret[ctr++] = v;
+ return ret;
+ }
+
internal struct QueryPart {
public readonly Statement[] Graph;
public readonly SelectableSource[] Sources;
@@ -369,7 +379,11 @@
vars = null;
matches = null;
+ string src = "";
foreach (QueryableSource source in part.Sources) {
+ if (src != "") src += ", ";
+ src += source;
+
if (localLimit > 0) {
opts.Limit = localLimit - (matches == null ? 0 : matches.Count);
if (opts.Limit <= 0)
@@ -407,7 +421,7 @@
foreach (Statement s in part.Graph)
qs += "\n\t" + s;
- result.AddComments("QUERY: " + qs + (returnLimit > 0 ? " [limit " + returnLimit + "/" + localLimit + "]" : "") + " => " + matches.Count);
+ result.AddComments("QUERY: " + src + qs + (returnLimit > 0 ? " [limit " + returnLimit + "/" + localLimit + "]" : "") + " => " + matches.Count);
// If we got back at least as many rows as our local (adaptive) limit,
// then we know that the limiting (possibly) had an effect and we may
@@ -676,5 +690,96 @@
}
return false;
}
+
+ public static Statement[] ReorderQuery(Statement[] graph, Variable[] fixedVariables, SelectableSource schema, bool[,] groupingPreference) {
+ // Find an optimal order of the statements in the graph to run the
+ // query in, assuming each statement is executed one at a time.
+ // This is a greedy algorithm: at each step, choose the statement
+ // that has the fewest unseen variables, or failing that, if we have
+ // schema information, the statement that is expected to have the
+ // fewest results based on functional and inverse functional property
+ // typing, and failing that if we have a preference for which statements
+ // to group together (because they will be answered by the same data source),
+ // then grouping that way.
+
+ bool[] used = new bool[graph.Length];
+ int[] permutation = new int[graph.Length];
+
+ ResSet selectedVars = new ResSet();
+ selectedVars.AddRange(fixedVariables);
+
+ Entity rdf_type = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";
+ Entity owl_inversefunctional = "http://www.w3.org/2002/07/owl#InverseFunctionalProperty";
+ Entity owl_functional = "http://www.w3.org/2002/07/owl#FunctionalProperty";
+
+ for (int i = 0; i < graph.Length; i++) {
+ // Choose the best alternative.
+ int best_index = -1, best_score = -1;
+
+ for (int j = 0; j < graph.Length; j++) {
+ if (used[j]) continue;
+
+ // Compute a 'data complexity' for the graph statement.
+ int score = 1;
+
+ // For each component of the graph statement...
+ for (int k = 0; k < 4; k++) {
+ Resource v = graph[j].GetComponent(k);
+ if (!(v is Variable)) continue;
+ if (selectedVars.Contains(v)) continue;
+
+ int cscore = 3;
+ if (schema != null) {
+ // Don't penalize so much if the predicate is functional or inverse functional and
+ // the other side of the statement has already been selected.
+ Entity predicate = (Entity)graph[j].GetComponent(1);
+ if (k == 0 && selectedVars.Contains(graph[j].GetComponent(2)) && schema.Contains(new Statement(predicate, rdf_type, owl_inversefunctional)))
+ cscore = 2;
+ if (k == 2 && selectedVars.Contains(graph[j].GetComponent(0)) && schema.Contains(new Statement(predicate, rdf_type, owl_functional)))
+ cscore = 2;
+ }
+
+ score *= cscore;
+ }
+
+ //Console.WriteLine(j + ") " + score + " " + graph[j] + " " + ((i > 0 && groupingPreference != null
+ // && groupingPreference[permutation[i-1], j]) ? "GROUP" : ""));
+
+ // If we found something with a better score, than use this statement next.
+ if (score < best_score || best_index == -1) {
+ best_score = score;
+ best_index = j;
+ }
+
+ // If we found something with the same score, but we have a preference for
+ // grouping this statement with the previous, than use this statement next.
+ if (score == best_score && i > 0 && groupingPreference != null
+ && !groupingPreference[permutation[i-1], best_index]
+ && groupingPreference[permutation[i-1], j]) {
+ best_score = score;
+ best_index = j;
+ }
+ }
+
+ // At this point we've picked the best statement to use next.
+ //Console.WriteLine("Chose " + best_index);
+ used[best_index] = true;
+ permutation[i] = best_index;
+ for (int k = 0; k < 4; k++) {
+ Resource v = graph[best_index].GetComponent(k);
+ if (!(v is Variable)) continue;
+ selectedVars.Add(v);
+ }
+ }
+
+ // We've chosen a new permutation.
+ Statement[] neworder = new Statement[graph.Length];
+ for (int i = 0; i < graph.Length; i++) {
+ neworder[i] = graph[permutation[i]];
+ }
+
+ return neworder;
+ }
+
}
}
Modified: trunk/beagle/Util/SemWeb/Inference.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/Inference.cs (original)
+++ trunk/beagle/Util/SemWeb/Inference.cs Mon Jun 2 11:28:03 2008
@@ -197,6 +197,17 @@
ret.Append(step.Substitutions[v]);
ret.Append("\n");
}
+ if (vars.Count > 0) {
+ foreach (Statement s in step.Rule.Consequent) {
+ Statement ss = s;
+ foreach (Variable v in vars)
+ ss = ss.Replace(v, (Resource)step.Substitutions[v]);
+
+ ret.Append("\t\t=> ");
+ ret.Append(ss.ToString());
+ ret.Append("\n");
+ }
+ }
}
return ret.ToString();
Modified: trunk/beagle/Util/SemWeb/Interfaces.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/Interfaces.cs (original)
+++ trunk/beagle/Util/SemWeb/Interfaces.cs Mon Jun 2 11:28:03 2008
@@ -1,6 +1,5 @@
using System;
using System.Collections;
-//using System.Data;
using SemWeb.Util;
@@ -69,4 +68,4 @@
}
-}
+}
\ No newline at end of file
Modified: trunk/beagle/Util/SemWeb/N3Reader.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/N3Reader.cs (original)
+++ trunk/beagle/Util/SemWeb/N3Reader.cs Mon Jun 2 11:28:03 2008
@@ -14,6 +14,8 @@
Resource BaseResource = new Literal("@base");
TextReader sourcestream;
+ bool closed;
+
NamespaceManager namespaces = new NamespaceManager();
Entity entRDFTYPE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";
@@ -34,6 +36,12 @@
BaseUri = "file:" + sourcefile + "#";
}
+ protected override void Dispose() {
+ if (!closed)
+ sourcestream.Close();
+ closed = true;
+ }
+
private struct ParseContext {
public MyReader source;
public StatementSink store;
@@ -60,6 +68,8 @@
context.meta = Meta;
while (ReadStatement(context)) { }
+
+ Dispose();
}
private bool ReadStatement(ParseContext context) {
@@ -612,13 +622,13 @@
if (str[0] == '?') {
string name = str.Substring(1);
- Entity var = (Entity)context.variables[name];
- if (var == null) {
- var = new Variable(name);
- AddVariable((Variable)var);
- context.variables[name] = var;
+ Entity varb = (Entity)context.variables[name];
+ if (varb == null) {
+ varb = new Variable(name);
+ AddVariable((Variable)varb);
+ context.variables[name] = varb;
}
- return var;
+ return varb;
}
// QNAME
@@ -707,7 +717,18 @@
// In Turtle, numbers are restricted to [0-9]+, and are datatyped xsd:integer.
double numval;
+ #if !SILVERLIGHT
if (double.TryParse(str, System.Globalization.NumberStyles.Any, null, out numval)) {
+ #else
+ bool ok = true;
+ numval = 0;
+ try {
+ numval = double.Parse(str);
+ } catch (Exception) {
+ ok = false;
+ }
+ if (ok) {
+ #endif
if (numval >= long.MinValue && numval <= long.MaxValue && numval == (double)(long)numval)
return new Literal(((long)numval).ToString(), null, NS.XMLSCHEMA + "integer");
else
Modified: trunk/beagle/Util/SemWeb/N3Writer.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/N3Writer.cs (original)
+++ trunk/beagle/Util/SemWeb/N3Writer.cs Mon Jun 2 11:28:03 2008
@@ -59,9 +59,11 @@
}
private string Literal(Literal literal) {
+ #if !SILVERLIGHT
if (format == Formats.NTriples || literal.DataType == null) return literal.ToString();
if (literal.DataType == xsdInteger) return literal.ParseValue().ToString();
if (literal.DataType == xsdDouble && format == Formats.Notation3) return literal.ParseValue().ToString();
+ #endif
return literal.ToString();
}
Modified: trunk/beagle/Util/SemWeb/Query.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/Query.cs (original)
+++ trunk/beagle/Util/SemWeb/Query.cs Mon Jun 2 11:28:03 2008
@@ -149,7 +149,11 @@
public virtual string MimeType {
get {
+ #if !SILVERLIGHT
return SparqlXmlQuerySink.MimeType;
+ #else
+ throw new NotSupportedException();
+ #endif
}
set {
throw new NotSupportedException();
@@ -157,7 +161,11 @@
}
public virtual void Run(SelectableSource source, TextWriter output) {
+ #if !SILVERLIGHT
Run(source, new SparqlXmlQuerySink(output));
+ #else
+ throw new NotSupportedException();
+ #endif
}
public abstract void Run(SelectableSource source, QueryResultSink resultsink);
@@ -230,7 +238,11 @@
#endif
}
- public class VariableBindings {
+ public class VariableBindings : IComparable
+ #if DOTNET2
+ , IComparable<VariableBindings>
+ #endif
+ {
Variable[] vars;
Resource[] vals;
@@ -288,6 +300,25 @@
}
return ret;
}
+
+ int IComparable.CompareTo(object other) {
+ return CompareTo((VariableBindings)other);
+ }
+ public int CompareTo(VariableBindings other) {
+ for (int i = 0; i < vars.Length; i++) {
+ Resource a = vals[i];
+ Resource b = other.vals[i];
+ if (a == null && b == null)
+ continue;
+ if (a == null)
+ return -1;
+ if (b == null)
+ return 1;
+ int c = a.CompareTo(b);
+ if (c != 0) return c;
+ }
+ return 0;
+ }
}
}
Copied: trunk/beagle/Util/SemWeb/README.txt (from r4763, /trunk/beagle/Util/SemWeb/README)
==============================================================================
--- /trunk/beagle/Util/SemWeb/README (original)
+++ trunk/beagle/Util/SemWeb/README.txt Mon Jun 2 11:28:03 2008
@@ -1,16 +1,125 @@
-Semantic Web Library for C#/.NET
-================================
+SemWeb: A Semantic Web Library for C#/.NET
+==========================================
-By Joshua Tauberer <tauberer for net>
+By Joshua Tauberer <http://razor.occams.info>
-http://taubz.for.net/code/semweb
-
-Copyright 2005 Joshua Tauberer. This package is released
-under the terms of the Creative Commons Attribution License:
-
- http://creativecommons.org/licenses/by/2.0/
-
-The license basically means you can copy, distribute and
-modify this package however you like, but you need to
-give me due credit. I think that's fair.
+http://razor.occams.info/code/semweb
+USAGE
+-----
+
+SemWeb is a library for use in other C# and .NET applications on either
+Mono or Microsoft's .NET. The library comes as a collection of
+.NET assemblies. There are two directories for the compiled assemblies:
+
+ bin: Binaries compiled for .NET 1.1 (no generics).
+ bin_generics: Binaries compiled for .NET 2.0 (generics).
+
+Each directory contains the files:
+
+ SemWeb.dll
+ This is the core library.
+
+ SemWeb.MySQLStore.dll, SemWeb.PostgreSQLStore.dll, SemWeb.SqliteStore.dll
+ Assemblies providing SQLStore implementations for
+ those RDBMSs. (details to be entered here later)
+
+ SemWeb.Sparql.dll
+ An assembly providing the SPARQL engine class. It requires
+ the auxiliary assemblies listed next.
+
+ IKVM.GNU.Classpath.dll, IKVM.Runtime.dll
+ sparql-core.dll
+ Auxiliary assemblies required for SPARQL.
+
+ rdfstorage.exe
+ A command-line tool for converting files between RDF formats
+ and loading RDF files into databases.
+
+ rdfquery.exe
+ A command-line tool for running SPARQL and simple graph
+ matching (in N3) queries against a data source.
+
+ euler.exe
+ A command-line tool for performing general rule-based
+ reasoning.
+
+ Mono.GetOptions.dll
+ This library from Mono is a dependency of all of the command-line
+ tools listed above.
+
+ .mdb files are debugging symbol files for Mono. Running
+ under MS .NET, they are useless. Running under Mono, they
+ are optional unless you want debugging info in stack traces.
+
+ To use any of the .dll assemblies, reference them in your
+ project, and make sure they and any of their dependencies
+ are findable at runtime (which in MS .NET is usually the
+ case if you just reference them).
+
+
+DOCUMENTATION
+-------------
+
+For more information, view doc/index.html and the API documentation
+in apidocs/index.html.
+
+
+BUILD INSTRUCTIONS
+------------------
+
+Run make if you're in Linux. Nothing complicated here. You'll need
+Mono installed (and the MySQL/Connector and Sqlite Client DLLs for SQL
+database support, optionally). It'll build .NET 1.1 binaries to the
+bin directory and .NET 2.0 binaries with generics to the bin_generics
+directory.
+
+A MonoDevelop solution file (semweb.mds) and a Visual Studio 2005 solution
+file (SemWeb.sln) are included too. They build .NET 2.0 binaries with
+generics to the bin_generics directory.
+
+If you build the MySQL and SQLite .cs files, you'll need to reference
+MySQL's MySql.Data.dll and Sqlite Client assemblies (see www.mono-project.com). Otherwise just leave out those .cs files.
+Put MySql.Data.dll in a "lib" directory within the SemWeb directory.
+
+The sources are set up with a conditional compilation flag "DOTNET2" so
+that the sources can be compiled for both .NET 1.1 and 2.0, taking
+advantage of generics.
+
+
+LICENSE
+-------
+
+The portions of this library not written by someone else are Copyright 2007
+Joshua Tauberer, and are dual-licensed under both the GNU GPL (version 2
+or later) and the Creative Commons Attribution license. See below for
+licensing information on the 3rd-party components of the library. Everything
+not listed below was written originally by me.
+
+In short, you can use the library if the program it is incorporated
+into either 1) is licensed under the GNU GPL, or 2) credits me for
+the use of the SemWeb library. However, this does not cover any obligations
+you may have for using the components of the library derived from
+other projects.
+
+
+IMPORTED FILES FROM OTHER PROJECTS & CREDITS
+--------------------------------------------
+
+sparql-core.dll is based on the SPARQL Engine by Ryan Levering,
+which is covered by the GNU LGPL. The original Java JAR was
+coverted to a .NET assembly using IKVM (see below). Actually, I've
+made numerous changes to the library so it can take advantage of
+faster API paths in SemWeb.
+See: http://sparql.sourceforge.net/
+
+IKVM*.dll are auxiliary assemblies for running the SPARQL
+engine. IKVM was written by Jeroen Frijters. See http://www.ikvm.net.
+The IVKM license is the zlib license, which is GPL compatible.
+
+Euler.cs is adapted from Jos De Roo's JavaScript Euler inferencing
+engine. See: http://www.agfa.com/w3c/euler/ The original source
+code (and thus this derived file) was licensed under the W3C Software
+License, which is GPL compatible. The packaged SemWeb.dll contains
+this source code, and is thus (as is) released under the GPL license
+only (not the CC license).
Modified: trunk/beagle/Util/SemWeb/RdfReader.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/RdfReader.cs (original)
+++ trunk/beagle/Util/SemWeb/RdfReader.cs Mon Jun 2 11:28:03 2008
@@ -71,7 +71,11 @@
public abstract void Select(StatementSink sink);
- public virtual void Dispose() {
+ protected virtual void Dispose() {
+ }
+
+ void IDisposable.Dispose() {
+ Dispose();
}
internal static string NormalizeMimeType(string type) {
@@ -118,7 +122,7 @@
}
}
- /*
+ #if false
public static RdfReader LoadFromUri(Uri webresource) {
// TODO: Add Accept header for HTTP resources.
@@ -152,7 +156,7 @@
return reader;
}
- */
+ #endif
internal static TextReader GetReader(string file) {
if (file == "-") return Console.In;
@@ -170,6 +174,7 @@
return uri;
}
if (uri.IndexOf(':') != -1) return uri;
+ #if !SILVERLIGHT
try {
UriBuilder b = new UriBuilder(baseuri);
b.Fragment = null; // per W3 RDF/XML test suite
@@ -177,6 +182,9 @@
} catch (UriFormatException) {
return baseuri + uri;
}
+ #else
+ return baseuri + uri;
+ #endif
}
}
Modified: trunk/beagle/Util/SemWeb/RdfXmlReader.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/RdfXmlReader.cs (original)
+++ trunk/beagle/Util/SemWeb/RdfXmlReader.cs Mon Jun 2 11:28:03 2008
@@ -11,6 +11,7 @@
// TODO: Make some of the errors warnings.
XmlReader xml;
+ bool closed;
Hashtable blankNodes = new Hashtable();
UriMap namedNodes = new UriMap();
@@ -36,14 +37,31 @@
#endif
public RdfXmlReader(XmlReader document) {
- XmlValidatingReader reader = new XmlValidatingReader(document); // decodes entity definitions
- reader.ValidationType = ValidationType.None;
+ #if !DOTNET2
+ XmlValidatingReader reader = new XmlValidatingReader(document); // decodes entity definitions
+ reader.ValidationType = ValidationType.None;
+ #elif SILVERLIGHT
+ XmlReader reader = document;
+ #else
+ XmlReaderSettings settings = new XmlReaderSettings();
+ settings.ValidationType = ValidationType.None;
+ settings.ProhibitDtd = false;
+ settings.CloseInput = true;
+ XmlReader reader = XmlReader.Create(document, settings);
+ #endif
+
xml = new XmlBaseAwareReader(reader);
LoadNamespaces();
}
+ #if !SILVERLIGHT
public RdfXmlReader(TextReader document) : this(new XmlTextReader(document)) {
}
+ #else
+ public RdfXmlReader(TextReader document) {
+ throw new NotSupportedException("Reading RDF/XML from a TextReader is not supported in the Silverlight build of the SemWeb library. Someone needs to fix this.");
+ }
+ #endif
public RdfXmlReader(Stream document) : this(new StreamReader(document)) {
}
@@ -61,6 +79,12 @@
public RdfXmlReader(string file) : this(GetReader(file), "file:///" + file) {
}
+ protected override void Dispose() {
+ if (!closed)
+ xml.Close();
+ closed = true;
+ }
+
private void LoadNamespaces() {
// Move to the document element and load any namespace
// declarations on the node.
@@ -114,8 +138,8 @@
}
break;
}
-
- xml.Close();
+
+ Dispose();
}
private string CurNode() {
@@ -414,7 +438,11 @@
if (xml.IsEmptyElement) {
objct = new Literal("", null, datatype);
} else {
+ #if !DOTNET2
objct = new Literal(xml.ReadString(), null, datatype);
+ #else
+ objct = new Literal(xml.ReadElementContentAsString(), null, datatype);
+ #endif
if (xml.NodeType != XmlNodeType.EndElement)
OnError("XML markup may not appear in a datatyped literal property.");
}
@@ -596,26 +624,27 @@
public override bool MoveToElement () { return _reader.MoveToElement(); }
public override bool MoveToFirstAttribute () { return _reader.MoveToFirstAttribute(); }
public override bool MoveToNextAttribute () { return _reader.MoveToNextAttribute(); }
- public override bool ReadAttributeValue () { return _reader.ReadAttributeValue(); }
- public override string ReadElementString () { return _reader.ReadElementString(); }
- public override string ReadElementString (string name) { return _reader.ReadElementString(name); }
- public override string ReadElementString (string localName, string namespaceName) { return _reader.ReadElementString(localName, namespaceName); }
public override void ReadEndElement () { _reader.ReadEndElement(); }
public override string ReadInnerXml () { return _reader.ReadInnerXml(); }
public override string ReadOuterXml () { return _reader.ReadOuterXml(); }
public override void ReadStartElement () { _reader.ReadStartElement(); }
public override void ReadStartElement (string name) { _reader.ReadStartElement(name); }
public override void ReadStartElement (string localName, string namespaceName) { _reader.ReadStartElement(localName, namespaceName); }
+ public override void Skip () { _reader.Skip(); }
+
+ #if !SILVERLIGHT
+ public override bool ReadAttributeValue () { return _reader.ReadAttributeValue(); }
+ public override string ReadElementString () { return _reader.ReadElementString(); }
+ public override string ReadElementString (string name) { return _reader.ReadElementString(name); }
+ public override string ReadElementString (string localName, string namespaceName) { return _reader.ReadElementString(localName, namespaceName); }
public override string ReadString () { return _reader.ReadString(); }
public override void ResolveEntity () { _reader.ResolveEntity(); }
- public override void Skip () { _reader.Skip(); }
+ #endif
public override int AttributeCount { get { return _reader.AttributeCount; } }
- public override bool CanResolveEntity { get { return _reader.CanResolveEntity; } }
public override int Depth { get { return _reader.Depth; } }
public override bool EOF { get { return _reader.EOF; } }
public override bool HasAttributes { get { return _reader.HasAttributes; } }
- public override bool HasValue { get { return _reader.HasValue; } }
public override bool IsDefault { get { return _reader.IsDefault; } }
public override bool IsEmptyElement { get { return _reader.IsEmptyElement; } }
public override string this [int i] { get { return _reader[i]; } }
@@ -627,11 +656,16 @@
public override XmlNameTable NameTable { get { return _reader.NameTable; } }
public override XmlNodeType NodeType { get { return _reader.NodeType; } }
public override string Prefix { get { return _reader.Prefix; } }
- public override char QuoteChar { get { return _reader.QuoteChar; } }
public override ReadState ReadState { get { return _reader.ReadState; } }
public override string Value { get { return _reader.Value; } }
public override string XmlLang { get { return _reader.XmlLang; } }
public override XmlSpace XmlSpace { get { return _reader.XmlSpace; } }
+
+ #if !SILVERLIGHT
+ public override bool CanResolveEntity { get { return _reader.CanResolveEntity; } }
+ public override bool HasValue { get { return _reader.HasValue; } }
+ public override char QuoteChar { get { return _reader.QuoteChar; } }
+ #endif
}
}
}
Modified: trunk/beagle/Util/SemWeb/Resource.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/Resource.cs (original)
+++ trunk/beagle/Util/SemWeb/Resource.cs Mon Jun 2 11:28:03 2008
@@ -4,8 +4,10 @@
namespace SemWeb {
- public abstract class Resource :
- IComparable
+ public abstract class Resource : IComparable
+#if DOTNET2
+ , IComparable<Resource>
+#endif
{
internal object ekKey, ekValue;
internal ArrayList extraKeys;
@@ -67,14 +69,17 @@
extraKeys.Add(k);
}
- public int CompareTo(object other) {
+ int IComparable.CompareTo(object other) {
+ return CompareTo((Resource)other);
+ }
+ public int CompareTo(Resource other) {
// We'll make an ordering over resources.
// First named entities, then bnodes, then literals.
// Named entities are sorted by URI.
// Bnodes by hashcode.
// Literals by their value, language, datatype.
- Resource r = (Resource)other;
+ Resource r = other;
if (Uri != null && r.Uri == null) return -1;
if (Uri == null && r.Uri != null) return 1;
if (this is BNode && r is Literal) return -1;
@@ -510,6 +515,7 @@
return new Literal(value, lang, datatype);
}
+ #if !SILVERLIGHT
public object ParseValue() {
string dt = DataType;
if (dt == null || !dt.StartsWith(NS.XMLSCHEMA)) return Value;
@@ -542,6 +548,7 @@
if (DataType == null) return this;
return new Literal(ParseValue().ToString(), Language, DataType);
}
+ #endif
public static Literal FromValue(float value) {
return new Literal(value.ToString(), null, NS.XMLSCHEMA + "float");
Modified: trunk/beagle/Util/SemWeb/SQLStore.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/SQLStore.cs (original)
+++ trunk/beagle/Util/SemWeb/SQLStore.cs Mon Jun 2 11:28:03 2008
@@ -44,6 +44,8 @@
* not in this table or in the _literals table.
*/
+#if !SILVERLIGHT
+
using System;
using System.Collections;
using System.Collections.Specialized;
@@ -124,7 +126,6 @@
// Debugging flags from environment variables.
static bool Debug = System.Environment.GetEnvironmentVariable("SEMWEB_DEBUG_SQL") != null;
static bool DebugLogSpeed = System.Environment.GetEnvironmentVariable("SEMWEB_DEBUG_SQL_LOG_SPEED") != null;
- static bool NoSQLView = System.Environment.GetEnvironmentVariable("SEMWEB_SQL_NOVIEWS") != null;
static string InitCommands = System.Environment.GetEnvironmentVariable("SEMWEB_SQL_INIT_COMMANDS");
// This guy is reused in various calls to avoid allocating a new one of
@@ -183,6 +184,7 @@
protected abstract string InsertIgnoreCommand { get; }
protected abstract bool SupportsInsertCombined { get; }
protected abstract bool SupportsSubquery { get; }
+ protected virtual bool SupportsLimitClause { get { return true; } }
protected virtual bool SupportsViews { get { return false; } }
protected virtual int MaximumUriLength { get { return -1; } }
@@ -368,13 +370,18 @@
if (ret != null) return (int)ret;
} else {
StringBuilder b = cmdBuffer; cmdBuffer.Length = 0;
- b.Append("SELECT id FROM ");
+ b.Append("SELECT ");
+ if (!SupportsLimitClause)
+ b.Append("TOP 1 ");
+ b.Append("id FROM ");
b.Append(table);
b.Append("_literals WHERE hash =");
b.Append(quote);
b.Append(GetLiteralHash(literal));
b.Append(quote);
- b.Append(" LIMIT 1;");
+ if (SupportsLimitClause)
+ b.Append(" LIMIT 1");
+ b.Append(';');
object id = RunScalar(b.ToString());
if (id != null) return AsInt(id);
@@ -1139,6 +1146,7 @@
void PrefetchResourceIds(IList resources) {
Hashtable seen_e = new Hashtable();
Hashtable seen_l = new Hashtable();
+ Hashtable res_map = new Hashtable();
int resStart = 0;
while (resStart < resources.Count) {
@@ -1165,7 +1173,14 @@
ctr++;
if (r.Uri != null) {
- if (seen_e.ContainsKey(r.Uri)) continue;
+ if (seen_e.ContainsKey(r.Uri)) {
+ // We can only query for a URI once, but it might be that multiple objects
+ // coming in have the same URI, so when we see a duplicate, associate the
+ // duplicate with the first instance of the URI we saw.
+ if ((object)r != (object)seen_e[r.Uri])
+ res_map[r] = seen_e[r.Uri];
+ continue;
+ }
if (hasEnts)
cmd_e.Append(" , ");
EscapedAppend(cmd_e, r.Uri);
@@ -1176,7 +1191,14 @@
Literal lit = r as Literal;
if (lit != null) {
string hash = GetLiteralHash(lit);
- if (seen_l.ContainsKey(hash)) continue;
+ if (seen_l.ContainsKey(hash)) {
+ // We can only query for a literal value once, but it might be that multiple objects
+ // coming in have the same value, so when we see a duplicate, associate the
+ // duplicate with the first instance of the value we saw.
+ if ((object)lit != (object)seen_l[hash])
+ res_map[lit] = seen_l[hash];
+ continue;
+ }
if (hasLiterals)
cmd_l.Append(" , ");
@@ -1211,6 +1233,10 @@
}
}
+
+ foreach (Resource r in res_map.Keys) {
+ SetResourceKey(r, GetResourceKey((Resource)res_map[r]));
+ }
}
public void Select(Statement template, StatementSink result) {
@@ -1253,8 +1279,11 @@
}*/
// Have to select something
- if (!columns.SubjectId && !columns.PredicateId && !columns.ObjectId && !columns.MetaId)
+ bool fakeSubjectIdSelect = false;
+ if (!columns.SubjectId && !columns.PredicateId && !columns.ObjectId && !columns.MetaId) {
columns.SubjectId = true;
+ fakeSubjectIdSelect = true;
+ }
// Pre-cache the IDs of resources in a MultiRes. TODO: Pool these into one array.
foreach (Resource r in new Resource[] { templateSubject, templatePredicate, templateObject, templateMeta }) {
@@ -1272,6 +1301,11 @@
// exclude the results of the join.
System.Text.StringBuilder cmd = new System.Text.StringBuilder("SELECT ");
+ if (!SupportsLimitClause && limit >= 1) {
+ cmd.Append("TOP ");
+ cmd.Append(limit);
+ cmd.Append(' ');
+ }
if (!HasUniqueStatementsConstraint)
cmd.Append("DISTINCT ");
SelectFilterColumns(columns, cmd);
@@ -1297,7 +1331,7 @@
}
}
- if (limit >= 1) {
+ if (SupportsLimitClause && limit >= 1) {
cmd.Append(" LIMIT ");
cmd.Append(limit);
}
@@ -1337,7 +1371,7 @@
if (columns.ObjectData) { ot = reader.GetInt32(col++); ouri = AsString(reader[col++]); lv = AsString(reader[col++]); ll = AsString(reader[col++]); ld = AsString(reader[col++]);}
if (columns.MetaUri) { muri = AsString(reader[col++]); }
- Entity subject = GetSelectedEntity(sid, suri, templateSubject, columns.SubjectId, columns.SubjectUri, entMap);
+ Entity subject = GetSelectedEntity(sid, suri, templateSubject, columns.SubjectId && !fakeSubjectIdSelect, columns.SubjectUri, entMap);
Entity predicate = GetSelectedEntity(pid, puri, templatePredicate, columns.PredicateId, columns.PredicateUri, entMap);
Resource objec = GetSelectedResource(oid, ot, ouri, lv, ll, ld, templateObject, columns.ObjectId, columns.ObjectData, entMap);
Entity meta = GetSelectedEntity(mid, muri, templateMeta, columns.MetaId, columns.MetaUri, templateMeta != null ? entMap : null);
@@ -1359,7 +1393,48 @@
public void Query(Statement[] graph, SemWeb.Query.QueryOptions options, SemWeb.Query.QueryResultSink sink) {
if (graph.Length == 0) throw new ArgumentException("graph array must have at least one element");
-
+
+ // This method translates the graph pattern into a single SQL statement. Each graph statement
+ // corresponds to a new use of the _statements table in the FROM clause. For instance:
+ // ?a foaf:knows ?b . ?b foaf:name ?c .
+ // translates to
+ // SELECT
+ // g0.subject, v0.value,
+ // g0.object, v1.value,
+ // g1.object, v2.value, v2lit.value, v2lit.language, v2lit.datatype
+ // FROM
+ // db_tables as g0 LEFT JOIN db_entities AS v0 ON g0.subject=v0.id LEFT JOIN db_entities AS v1 ON g0.object=v1.id,
+ // db_tables as g1 LEFT JOIN db_entities AS v2 ON g1.object=v2.id LEFT JOIN db_literals AS v2lit ON g1.object=v2lit.id
+ // WHERE
+ // g0.predicate = <the id of the foaf:knows entity> AND
+ // g1.predicate = <the id of the foaf:name entity> AND
+ // g0.object = g1.subject
+ //
+ // If any variable column is an *undistinguished* variable --- which is to say that the caller
+ // says it is a variable, but is not concerned with its values --- then we want to apply
+ // DISTINCT to the SELECT statement. This is because while in the normal case we may get
+ // duplicates, we expect that to not occur more than the caller expects, but in the latter
+ // case there will often be many duplicates. Consider the SPARQL query:
+ // SELECT DISTINCT ?p WHERE { ?s ?p ?o }
+ // to get a list of predicates in the dataset, which corresponds to the graph query
+ // ?s ?p ?o
+ // where only ?p is distinguished.
+ // This normally translates to:
+ // SELECT
+ // g0.predicate, v0.value,
+ // FROM
+ // db_tables as g0 LEFT JOIN db_entities AS v0 ON g0.predicate=v0.id
+ // which of course is going to return a result for every triple in the database.
+ // So we add DISTINCT to beginning ("SELECT DISTINCT").
+ // Unfortunately, MySQL performs the DISTINCT bit only after the LEFT JOINs (which makes sense normally).
+ // That means that MySQL is repeatedly fetching the URI values of the predicates and checking
+ // if a new unique row has been created, and this is very slow. What we want is to get the distinct
+ // IDs of the predicates first, and then get their URIs.
+ // I first tried implementing this with VIEWs, but it didn't always speed things up, and it was
+ // difficult to manage the creation and deletion of VIEWs.
+ // So instead, in this case, we do the query in two parts. First we get the IDs of the variables,
+ // and then we get their URIs.
+
options = options.Clone(); // because we modify the knownvalues array
// Order the variables mentioned in the graph.
@@ -1406,8 +1481,6 @@
varOrder[ctr++] = v;
}
- bool useView = useDistinct && SupportsViews && !NoSQLView;
-
// Set the initial bindings to the result sink
sink.Init(varOrder);
@@ -1474,8 +1547,12 @@
string[] colnames = { "subject", "predicate", "object", "meta" };
+ // we initialize these things while locked, but use them after we release the lock
+ ArrayList results = new ArrayList();
+ Hashtable resourceCache = new Hashtable(); // map resource ID to Resource instances
+
// Lock the store and make sure we are initialized and any pending add's have been committed.
-
+
lock (syncroot) {
Init();
@@ -1483,15 +1560,14 @@
// Compile the SQL statement.
- Hashtable varRef_Inner = new Hashtable(); // the column name representing the variable: if we're using VIEWs, then within the VIEW (i.e. name of column in underlying table)
- Hashtable varRef_Outer = new Hashtable(); // if we're using VIEWs, then the column name representing the variable of the VIEW itself
- Hashtable varRef2 = new Hashtable();
- Hashtable varSelectedLiteral = new Hashtable();
+ Hashtable varRef = new Hashtable(); // the column name representing the variable, as in "g0.subject"
+ Hashtable varRef2 = new Hashtable(); // the index of the variable, for accessing the entities and literals joined tables
+ Hashtable varSelectedLiteral = new Hashtable(); // whether the variable is in a literal column and a LEFT JOIN for the literals table was used for it
+ Hashtable varCouldBeLiteral = new Hashtable(); // whether the variable is only in literal columns
+ Hashtable varSelectedEntity = new Hashtable(); // whether a LEFT JOIN for the entities table was used for a variable
StringBuilder fromClause = new StringBuilder();
StringBuilder whereClause = new StringBuilder();
- StringBuilder outerSelectJoins = new StringBuilder();
- StringBuilder outerWhereClause = new StringBuilder();
for (int f = 0; f < graph.Length; f++) {
// For each filter, we select FROM the statements table with an
@@ -1505,6 +1581,7 @@
// For each component of the filter...
for (int i = 0; i < 4; i++) {
+ // This has the name of the column corresponding to this variable (i.e. "g1.predicate").
string myRef = "g" + f + "." + colnames[i];
Variable v = graph[f].GetComponent(i) as Variable;
@@ -1520,47 +1597,56 @@
// that the proper columns here and in a previous
// filter are forced to have the same value.
- if (!varRef_Inner.ContainsKey(v)) {
- varRef_Inner[v] = myRef;
- varRef_Outer[v] = "v" + Array.IndexOf(varOrder, v);
+ if (!varRef.ContainsKey(v)) {
+ // This is the first time we are seeing this variable.
+
+ // Record the column name for the variable (i.e. g0.subject).
+ varRef[v] = myRef;
- int vIndex = varRef_Inner.Count;
+ // Record an index for the variable (i.e. 0, 1, 2, ...)
+ int vIndex = varRef.Count;
varRef2[v] = vIndex;
+ varCouldBeLiteral[v] = (i == 2);
+
+ // LEFT JOIN the entities table for this variable to get its URI
+ // only if it is a distinguished variable and we are not using DISTINCT.
+ varSelectedEntity[v] = false;
+ if (!useDistinct && distinguishedVars.Contains(v)) {
+ varSelectedEntity[v] = true; // Record that we are selecting the entities table for this variable.
+ fromClause.Append(" LEFT JOIN ");
+ fromClause.Append(table);
+ fromClause.Append("_entities AS vent");
+ fromClause.Append(vIndex);
+ fromClause.Append(" ON ");
+ fromClause.Append(myRef);
+ fromClause.Append("=");
+ fromClause.Append("vent" + vIndex + ".id ");
+ }
+
+ // LEFT JOIN the literals table for this variable:
+ // if it is in an object position
+ // to get its value, language, and datatype only if it is a distinguished variable and we are not using DISTINCT
+ // to apply a literal value filter (which will be done later)
#if !DOTNET2
bool hasLitFilter = (options.VariableLiteralFilters != null && options.VariableLiteralFilters[v] != null);
#else
bool hasLitFilter = (options.VariableLiteralFilters != null && options.VariableLiteralFilters.ContainsKey(v));
#endif
- if (distinguishedVars.Contains(v) || hasLitFilter) {
- StringBuilder joinTarget = fromClause;
- if (useView) joinTarget = outerSelectJoins;
-
- string onRef = (string)(!useView ? varRef_Inner : varRef_Outer)[v];
-
- joinTarget.Append(" LEFT JOIN ");
- joinTarget.Append(table);
- joinTarget.Append("_entities AS vent");
- joinTarget.Append(vIndex);
- joinTarget.Append(" ON ");
- joinTarget.Append(onRef);
- joinTarget.Append("=");
- joinTarget.Append("vent" + vIndex + ".id ");
-
- varSelectedLiteral[v] = (i == 2);
-
- if (i == 2) { // literals cannot be in any other column
- joinTarget.Append(" LEFT JOIN ");
- joinTarget.Append(table);
- joinTarget.Append("_literals AS vlit");
- joinTarget.Append(vIndex);
- joinTarget.Append(" ON ");
- joinTarget.Append(onRef);
- joinTarget.Append("=");
- joinTarget.Append("vlit" + vIndex + ".id ");
- }
+ varSelectedLiteral[v] = false;
+ if (i == 2 && ((!useDistinct && distinguishedVars.Contains(v)) || hasLitFilter)) {
+ varSelectedLiteral[v] = true; // Record that we are selecting the literals table for this variable.
+ fromClause.Append(" LEFT JOIN ");
+ fromClause.Append(table);
+ fromClause.Append("_literals AS vlit");
+ fromClause.Append(vIndex);
+ fromClause.Append(" ON ");
+ fromClause.Append(myRef);
+ fromClause.Append("=");
+ fromClause.Append("vlit" + vIndex + ".id ");
}
+ // If this variable has known values, then we must restrict what values can appear using a WHERE clause.
if (options.VariableKnownValues != null) {
ICollection values = null;
#if DOTNET2
@@ -1582,17 +1668,24 @@
}
} else {
+ // We've seen this variable before, so link up the column in this
+ // statement to the corresponding column in a previous (or this) statement.
if (whereClause.Length != 0) whereClause.Append(" AND ");
whereClause.Append('(');
- whereClause.Append((string)varRef_Inner[v]);
+ whereClause.Append((string)varRef[v]);
whereClause.Append('=');
whereClause.Append(myRef);
whereClause.Append(')');
+ if (i != 2)
+ varCouldBeLiteral[v] = false;
}
} else {
// If this is not a variable, then it is a resource.
+ // Append something into the WHERE clause to make sure this component gets
+ // the right fixed value. If we cannot add the component to the WHERE clause
+ // because the fixed value isn't even known in the data source, we can stop early.
if (!WhereItem(myRef, graph[f].GetComponent(i), whereClause, whereClause.Length != 0)) {
// We know at this point that the query cannot return any results.
sink.Finished();
@@ -1623,52 +1716,39 @@
string s = FilterToSQL(filter, "vlit" + (int)varRef2[v] + ".value");
if (s == null) continue;
- StringBuilder where = whereClause;
- if (useView) where = outerWhereClause;
-
- if (where.Length != 0) where.Append(" AND ");
- where.Append(s);
+ if (whereClause.Length != 0) whereClause.Append(" AND ");
+ whereClause.Append(s);
}
}
// Put the parts of the SQL statement together
StringBuilder cmd = new StringBuilder();
- StringBuilder outercmd = new StringBuilder();
- string viewname = "queryview" + Math.Abs(GetHashCode());
- if (useView) {
- cmd.Append("DROP VIEW IF EXISTS ");
- cmd.Append(viewname);
- cmd.Append("; CREATE VIEW ");
- cmd.Append(viewname);
- cmd.Append(" AS ");
-
- outercmd.Append("SELECT ");
- }
cmd.Append("SELECT ");
+
+ if (!SupportsLimitClause && options.Limit > 0) {
+ cmd.Append("TOP ");
+ cmd.Append(options.Limit);
+ cmd.Append(' ');
+ }
if (useDistinct) cmd.Append("DISTINCT ");
- for (int i = 0; i < varOrder.Length; i++) {
- if (i > 0) cmd.Append(',');
- cmd.Append((string)varRef_Inner[varOrder[i]]);
+ // Add all of the distinguished variables to the SELECT clause.
+ bool firstvar = true;
+ foreach (Variable v in varOrder) {
+ if (!firstvar) cmd.Append(','); firstvar = false;
+
+ cmd.Append((string)varRef[v]);
- StringBuilder c = cmd;
- if (useView) {
- cmd.Append(" AS ");
- cmd.Append((string)varRef_Outer[varOrder[i]]);
-
- if (i > 0) outercmd.Append(',');
- outercmd.Append((string)varRef_Outer[varOrder[i]]);
- c = outercmd;
- }
-
- c.Append(", vent" + (int)varRef2[varOrder[i]] + ".value");
- if ((bool)varSelectedLiteral[varOrder[i]]) {
- c.Append(", vlit" + (int)varRef2[varOrder[i]] + ".value");
- c.Append(", vlit" + (int)varRef2[varOrder[i]] + ".language");
- c.Append(", vlit" + (int)varRef2[varOrder[i]] + ".datatype");
+ if ((bool)varSelectedEntity[v]) {
+ cmd.Append(", vent" + (int)varRef2[v] + ".value");
+ }
+ if ((bool)varSelectedLiteral[v]) {
+ cmd.Append(", vlit" + (int)varRef2[v] + ".value");
+ cmd.Append(", vlit" + (int)varRef2[v] + ".language");
+ cmd.Append(", vlit" + (int)varRef2[v] + ".datatype");
}
}
@@ -1679,83 +1759,170 @@
cmd.Append(" WHERE ");
cmd.Append(whereClause.ToString());
- if (options.Limit > 0) {
+ if (SupportsLimitClause && options.Limit > 0) {
cmd.Append(" LIMIT ");
cmd.Append(options.Limit);
}
cmd.Append(';');
- if (useView) {
- outercmd.Append(" FROM ");
- outercmd.Append(viewname);
- outercmd.Append(outerSelectJoins);
-
- if (outerWhereClause.Length > 0)
- outercmd.Append(" WHERE ");
- outercmd.Append(outerWhereClause.ToString());
- }
-
-
if (Debug) {
string cmd2 = cmd.ToString();
//if (cmd2.Length > 80) cmd2 = cmd2.Substring(0, 80);
Console.Error.WriteLine(cmd2);
- if (useView)
- Console.Error.WriteLine(outercmd.ToString());
- }
-
- // Execute the query
-
- Hashtable entityCache = new Hashtable();
-
- if (useView) {
- RunCommand(cmd.ToString());
- cmd = outercmd;
}
- try {
+ // Execute the query.
+
+ // When we use DISTINCT and don't select URI and literal values at first,
+ // we have to select them after. And since we can't maintain two IDataReaders
+ // simultaneously, that means we have to pull the first set of results into
+ // memory. It would be nice to not have to do that when we don't use DISTINCT,
+ // but in practice it doesn't really matter since in SPARQL it's all sucked
+ // into memory anyway.
+
using (IDataReader reader = RunReader(cmd.ToString())) {
while (reader.Read()) {
- Resource[] variableBindings = new Resource[varOrder.Length];
-
+ QueryResultRowVariable[] row = new QueryResultRowVariable[varOrder.Length];
+ results.Add(row);
+
int col = 0;
for (int i = 0; i < varOrder.Length; i++) {
- int id = reader.GetInt32(col++);
- string uri = AsString(reader[col++]);
+ Variable v = varOrder[i];
- string litvalue = null, litlanguage = null, litdatatype = null;
-
- if ((bool)varSelectedLiteral[varOrder[i]]) {
- litvalue = AsString(reader[col++]);
- litlanguage = AsString(reader[col++]);
- litdatatype = AsString(reader[col++]);
+ row[i].id = reader.GetInt32(col++);
+ if ((bool)varSelectedEntity[v]) {
+ row[i].uri = AsString(reader[col++]);
}
-
- if (litvalue != null) {
- Literal lit = new Literal(litvalue, litlanguage, litdatatype);
- variableBindings[i] = lit;
-
- ArrayList litFilters = (ArrayList)varLitFilters[varOrder[i]];
- if (litFilters != null && !LiteralFilter.MatchesFilters(lit, (LiteralFilter[])litFilters.ToArray(typeof(LiteralFilter)), this))
- continue;
-
- } else {
- variableBindings[i] = MakeEntity(id, uri, entityCache);
+ if ((bool)varSelectedLiteral[v]) {
+ row[i].litvalue = AsString(reader[col++]);
+ row[i].litlanguage = AsString(reader[col++]);
+ row[i].litdatatype = AsString(reader[col++]);
+ }
+ }
+ }
+ }
+
+ // For any distinguished variable that we did not select URIs or literal values for,
+ // select that information now.
+
+ for (int i = 0; i < varOrder.Length; i++) {
+ Variable v = varOrder[i];
+
+ if ((bool)varSelectedEntity[v] && (!(bool)varCouldBeLiteral[v] || (bool)varSelectedLiteral[v])) continue;
+
+ // Get the list of resource IDs found for this variable.
+ ArrayList rids = new ArrayList();
+ foreach (QueryResultRowVariable[] row in results) {
+ if (row[i].id <= 1) continue; // can't fetch for Statement.DefaultMeta
+ if (resourceCache.ContainsKey(row[i].id)) continue; // we've already fetched it
+ rids.Add(row[i].id); // probably no need to remove duplicates
+ }
+
+ if (rids.Count > 0) {
+ // Fetch what we can for entities.
+ if (!(bool)varSelectedEntity[v]) {
+ StringBuilder cmd2 = new StringBuilder();
+ cmd2.Append("SELECT id, value FROM ");
+ cmd2.Append(table);
+ cmd2.Append("_entities WHERE id IN (");
+ bool first = true;
+ foreach (int id in rids) {
+ if (!first) cmd2.Append(','); first = false;
+ cmd2.Append(id);
+ }
+ cmd2.Append(")");
+ if (Debug) { Console.Error.WriteLine(cmd2.ToString()); }
+ using (IDataReader reader = RunReader(cmd2.ToString())) {
+ while (reader.Read()) {
+ int id = reader.GetInt32(0);
+ string uri = AsString(reader[1]);
+ resourceCache[id] = MakeEntity(id, uri, null);
+ }
+ }
+ }
+
+ // Fetch what we can for literals.
+ if ((bool)varCouldBeLiteral[v] && !(bool)varSelectedLiteral[v]) {
+ StringBuilder cmd2 = new StringBuilder();
+ cmd2.Append("SELECT id, value, language, datatype FROM ");
+ cmd2.Append(table);
+ cmd2.Append("_literals WHERE id IN (");
+ bool first = true;
+ foreach (int id in rids) {
+ if (!first) cmd2.Append(','); first = false;
+ cmd2.Append(id);
+ }
+ cmd2.Append(")");
+ if (Debug) { Console.Error.WriteLine(cmd2.ToString()); }
+ using (IDataReader reader = RunReader(cmd2.ToString())) {
+ while (reader.Read()) {
+ int id = reader.GetInt32(0);
+ string value = AsString(reader[1]);
+ string language = AsString(reader[2]);
+ string datatype = AsString(reader[3]);
+ Literal lit = new Literal(value, language, datatype);
+ SetResourceKey(lit, new ResourceKey(id));
+ resourceCache[id] = lit;
+ }
}
}
- if (!sink.Add(new SemWeb.Query.VariableBindings(varOrder, variableBindings))) return;
+ // Any ids not found so far are bnodes.
+ foreach (int id in rids) {
+ if (!resourceCache.ContainsKey(id)) {
+ BNode b = new BNode();
+ SetResourceKey(b, new ResourceKey(id));
+ resourceCache[id] = b;
+ }
+ }
}
}
- } finally {
- if (useView)
- RunCommand("DROP VIEW " + viewname);
-
- sink.Finished();
+
+ } // lock
+
+ // Now loop through the binding results.
+
+ foreach (QueryResultRowVariable[] row in results) {
+ bool match = true;
+ Resource[] variableBindings = new Resource[varOrder.Length];
+
+ for (int i = 0; i < varOrder.Length; i++) {
+ int id = row[i].id;
+ if (resourceCache.ContainsKey(id)) {
+ variableBindings[i] = (Resource)resourceCache[id];
+ } else {
+ if (row[i].litvalue == null) {
+ variableBindings[i] = MakeEntity(id, row[i].uri, null);
+ } else {
+ Literal lit = new Literal(row[i].litvalue, row[i].litlanguage, row[i].litdatatype);
+
+ ArrayList litFilters = (ArrayList)varLitFilters[varOrder[i]];
+ if (litFilters != null && !LiteralFilter.MatchesFilters(lit, (LiteralFilter[])litFilters.ToArray(typeof(LiteralFilter)), this)) {
+ match = false;
+ break;
+ }
+
+ SetResourceKey(lit, new ResourceKey(id));
+ variableBindings[i] = lit;
+ }
+
+ // reuse this entity later
+ resourceCache[id] = variableBindings[i];
+ }
+ }
+
+ if (!match) continue;
+ if (!sink.Add(new SemWeb.Query.VariableBindings(varOrder, variableBindings))) return;
}
+
+ sink.Finished();
+ }
- } // lock
+ private struct QueryResultRowVariable {
+ public int id;
+ public string uri;
+ public string litvalue, litlanguage, litdatatype;
}
Entity GetSelectedEntity(int id, string uri, Resource given, bool idSelected, bool uriSelected, Hashtable entMap) {
@@ -1773,10 +1940,13 @@
Resource GetSelectedResource(int id, int type, string uri, string lv, string ll, string ld, Resource given, bool idSelected, bool uriSelected, Hashtable entMap) {
if (!idSelected) return (Resource)given;
if (!uriSelected) return (Resource)entMap[id];
- if (type == 0)
+ if (type == 0) {
return MakeEntity(id, uri, entMap);
- else
- return new Literal(lv, ll, ld);
+ } else {
+ Literal lit = new Literal(lv, ll, ld);
+ SetResourceKey(lit, new ResourceKey(id));
+ return lit;
+ }
}
private string CreateLikeTest(string column, string match, int method) {
@@ -1844,6 +2014,7 @@
case '\\':
case '\"':
case '*':
+ case '\'':
b.Append('\\');
b.Append(c);
break;
@@ -2047,3 +2218,5 @@
}
}
+
+#endif
Modified: trunk/beagle/Util/SemWeb/SparqlClient.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/SparqlClient.cs (original)
+++ trunk/beagle/Util/SemWeb/SparqlClient.cs Mon Jun 2 11:28:03 2008
@@ -5,7 +5,6 @@
#endif
using System.IO;
using System.Text;
-using System.Web;
using System.Xml;
using SemWeb;
@@ -21,7 +20,7 @@
void RunSparqlQuery(string sparqlQuery, QueryResultSink selectResults);
}
-#if false
+ #if false
public class SparqlHttpSource : QueryableSource, SparqlSource {
static bool Debug = System.Environment.GetEnvironmentVariable("SEMWEB_DEBUG_HTTP") != null;
@@ -585,7 +584,7 @@
}
}
}
-#endif
+ #endif
}
namespace SemWeb.Query {
@@ -681,5 +680,5 @@
output.Flush();
}
}
-
+
}
Modified: trunk/beagle/Util/SemWeb/SpecialRelations.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/SpecialRelations.cs (original)
+++ trunk/beagle/Util/SemWeb/SpecialRelations.cs Mon Jun 2 11:28:03 2008
@@ -15,6 +15,7 @@
}
namespace Relations {
+ #if !SILVERLIGHT
internal abstract class MathUnaryRelation : RdfRelation {
protected abstract Decimal EvaluateForward(Decimal left);
protected abstract Decimal EvaluateReverse(Decimal right);
@@ -249,6 +250,7 @@
return !(left == right);
}
}
+ #endif
}
}
Modified: trunk/beagle/Util/SemWeb/Store.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/Store.cs (original)
+++ trunk/beagle/Util/SemWeb/Store.cs Mon Jun 2 11:28:03 2008
@@ -128,7 +128,8 @@
case "sqlite":
case "mysql":
case "postgresql":
- if (spec == "") throw new ArgumentException("Use: sqlite|mysql|postgresql:table:connection-string");
+ case "sqlserver":
+ if (spec == "") throw new ArgumentException("Use: sqlite|mysql|postgresql|sqlserver:table:connection-string");
c = spec.IndexOf(':');
if (c == -1) throw new ArgumentException("Invalid format for SQL spec parameter (table:constring).");
@@ -143,6 +144,8 @@
classtype = "SemWeb.Stores.MySQLStore, SemWeb.MySQLStore";
} else if (type == "postgresql") {
classtype = "SemWeb.Stores.PostgreSQLStore, SemWeb.PostgreSQLStore";
+ } else if( type == "sqlserver" ) {
+ classtype = "SemWeb.Stores.SQLServerStore, SemWeb.SQLServerStore";
}
ttype = Type.GetType(classtype);
if (ttype == null)
@@ -150,8 +153,12 @@
return Activator.CreateInstance(ttype, new object[] { spec, table });
/*case "bdb":
return new SemWeb.Stores.BDBStore(spec);*/
- /*case "sparql-http":
- return new SemWeb.Remote.SparqlHttpSource(spec);*/
+ case "sparql-http":
+ #if false
+ return new SemWeb.Remote.SparqlHttpSource(spec);
+ #else
+ throw new NotSupportedException("The SparqlHttpSource class is not available in the Silverlight build of SemWeb.");
+ #endif
case "class":
ttype = Type.GetType(spec);
if (ttype == null)
@@ -492,7 +499,7 @@
public void Query(Statement[] graph, SemWeb.Query.QueryOptions options, SemWeb.Query.QueryResultSink sink) {
// If reasoning is applied, delegate this call to the last reasoner
- // and pass it a clone of this store but with itself removed.
+ // and pass it a clone of this store but with that reasoner removed.
ReasoningHelper rh = GetReasoningHelper(null);
if (rh != null) {
rh.reasoner.Query(graph, options, rh.nextStore, sink);
@@ -528,7 +535,58 @@
if (!mq[i].QuerySupported)
return null;
}
-
+
+ // Establish which statements can be answered definitively by which data sources.
+ bool[,] definitive = new bool[query.Length, allsources.Count];
+ for (int j = 0; j < query.Length; j++) {
+ // Find a definitive source for this statement
+ for (int i = 0; i < mq.Length; i++) {
+ if (mq[i].IsDefinitive != null && mq[i].IsDefinitive[j]) {
+ definitive[j,i] = true;
+ sink.AddComments("Data source '" + allsources[i] + "' definitively answers: " + query[j]);
+ }
+ }
+
+ // See if only one source can answer this statement.
+ System.Collections.ArrayList answerables = new System.Collections.ArrayList();
+ for (int i = 0; i < mq.Length; i++) {
+ if (mq[i].NoData != null && mq[i].NoData[j]) continue;
+ answerables.Add(i);
+ }
+ if (answerables.Count == 0) {
+ sink.AddComments("No data source could answer a part of the query: " + query[j]);
+ return null;
+ }
+
+ if (answerables.Count == 1) {
+ //sink.AddComments("Only '" + allsources[(int)answerables[0]] + "' could answer: " + query[j]);
+ definitive[j,(int)answerables[0]] = true;
+ }
+ }
+
+ // Create a table that indicates preferred grouping: two statements that can be
+ // definitively answered by the same data source prefer to be grouped together.
+ bool[,] group = new bool[query.Length, query.Length];
+ for (int i = 0; i < query.Length; i++) {
+ for (int j = 0; j < query.Length; j++) {
+ if (i == j) continue;
+
+ for (int k = 0; k < mq.Length; k++) {
+ if (definitive[i,k] && definitive[j,k]) {
+ group[i,j] = true;
+ group[j,i] = true;
+ }
+ }
+ }
+ }
+
+ // Reorder the statements. Then run MetaQuery again because the order of statements changed.
+ query = SemWeb.Query.GraphMatch.ReorderQuery(query, SemWeb.Query.GraphMatch.toArray(options.VariableKnownValues), this, group);
+ for (int i = 0; i < allsources.Count; i++)
+ mq[i] = ((QueryableSource)allsources[i]).MetaQuery(query, options);
+
+ // Chunk the statements.
+
System.Collections.ArrayList chunks = new System.Collections.ArrayList();
int curSource = -1;
@@ -540,7 +598,6 @@
// statement in the graph, include this statement in the
// current chunk.
if (mq[curSource].IsDefinitive != null && mq[curSource].IsDefinitive[j]) {
- sink.AddComments(allsources[curSource] + " answers definitively: " + query[j]);
curStatements.Add(query[j]);
continue;
}
@@ -576,7 +633,6 @@
if (mq[i].IsDefinitive != null && mq[i].IsDefinitive[j]) {
curSource = i;
curStatements.Add(query[j]);
- sink.AddComments(allsources[i] + " answers definitively: " + query[j]);
break;
}
}
@@ -602,7 +658,6 @@
continue;
}
if (answerables.Count == 0) {
- sink.AddComments("No data source could answer: " + query[j]);
return null;
}
@@ -737,7 +792,7 @@
// ModifiableSource
public void Clear() {
- if (allsources.Count > 0) throw new InvalidOperationException("The Clear() method is not supported when multiple data sources are added to a Store.");
+ if (allsources.Count > 1) throw new InvalidOperationException("The Clear() method is not supported when multiple data sources are added to a Store.");
if (!(allsources[0] is ModifiableSource)) throw new InvalidOperationException("The data source is not modifiable.");
((ModifiableSource)allsources[0]).Clear();
}
@@ -1013,7 +1068,7 @@
}
public void Query(Statement[] graph, SemWeb.Query.QueryOptions options, SemWeb.Query.QueryResultSink sink) {
- output.WriteLine("QUERY:");
+ output.WriteLine("QUERY: " + source);
foreach (Statement s in graph)
output.WriteLine("\t" + s);
if (options.VariableKnownValues != null) {
Modified: trunk/beagle/Util/SemWeb/UriMap.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/UriMap.cs (original)
+++ trunk/beagle/Util/SemWeb/UriMap.cs Mon Jun 2 11:28:03 2008
@@ -145,7 +145,11 @@
}
if (Children == null)
+ #if !SILVERLIGHT
Children = new HybridDictionary();
+ #else
+ Children = new Hashtable();
+ #endif
Node ret = (Node)Children[name];
if (ret != null || !create) {
Modified: trunk/beagle/Util/SemWeb/Util.cs
==============================================================================
--- trunk/beagle/Util/SemWeb/Util.cs (original)
+++ trunk/beagle/Util/SemWeb/Util.cs Mon Jun 2 11:28:03 2008
@@ -218,8 +218,7 @@
public virtual void RemoveAt(int index) {
if (index < 0 || index >= _size)
- throw new ArgumentOutOfRangeException("index", index,
- "Less than 0 or more than list count.");
+ throw new ArgumentOutOfRangeException();
Shift(index, -1);
_size--;
}
Added: trunk/beagle/Util/SemWeb/upstream-change.diff
==============================================================================
--- (empty file)
+++ trunk/beagle/Util/SemWeb/upstream-change.diff Mon Jun 2 11:28:03 2008
@@ -0,0 +1,50 @@
+Mostly to remove unneeded dependency on System.Remote.
+
+--- /usr/share/devel/cvsdev/semweb/src/Store.cs 2008-06-02 06:53:41.765078790 -0400
++++ Store.cs 2008-06-02 06:58:47.705070026 -0400
+@@ -152,7 +152,7 @@
+ /*case "bdb":
+ return new SemWeb.Stores.BDBStore(spec);*/
+ case "sparql-http":
+- #if !SILVERLIGHT
++ #if false
+ return new SemWeb.Remote.SparqlHttpSource(spec);
+ #else
+ throw new NotSupportedException("The SparqlHttpSource class is not available in the Silverlight build of SemWeb.");
+--- /usr/share/devel/cvsdev/semweb/src/RdfReader.cs 2008-06-02 06:53:41.921075546 -0400
++++ RdfReader.cs 2008-06-02 06:59:20.221472537 -0400
+@@ -122,7 +122,7 @@
+ }
+ }
+
+- #if !SILVERLIGHT
++ #if false
+ public static RdfReader LoadFromUri(Uri webresource) {
+ // TODO: Add Accept header for HTTP resources.
+
+--- /usr/share/devel/cvsdev/semweb/src/SparqlClient.cs 2008-06-02 06:53:41.789077382 -0400
++++ SparqlClient.cs 2008-06-02 07:07:54.145078453 -0400
+@@ -20,7 +20,7 @@
+ void RunSparqlQuery(string sparqlQuery, QueryResultSink selectResults);
+ }
+
+- #if !SILVERLIGHT
++ #if false
+ public class SparqlHttpSource : QueryableSource, SparqlSource {
+ static bool Debug = System.Environment.GetEnvironmentVariable("SEMWEB_DEBUG_HTTP") != null;
+
+@@ -584,6 +584,7 @@
+ }
+ }
+ }
++ #endif
+ }
+
+ namespace SemWeb.Query {
+@@ -679,6 +680,5 @@
+ output.Flush();
+ }
+ }
+- #endif
+
+ }
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]