private HashSet <Tuple> SelectFromRemainingClauses(RequestProcess process, Tuple partial, int startIndex) { HashSet <Tuple> tuples; HashSet <Tuple> result; Clause clause = this.Clauses[startIndex].Clone(); // Fill in the clause with values from the tuple under consideration. string value; if (clause.subj.StartsWith("?") && partial.TryGetValue(clause.subj, out value)) { clause.subj = value; } if (clause.pred.StartsWith("?") && partial.TryGetValue(clause.pred, out value)) { clause.pred = value; } if (clause.obj.StartsWith("?") && partial.TryGetValue(clause.obj, out value)) { clause.obj = value; } // Find triples that match. var triples = process.Bot.Triples.Match(clause); if (!clause.Affirm) { // If the notq assertion succeeds, we just add the tuple under consideration without filling in any variables. if (triples.Count != 0) { return(new HashSet <Tuple>()); } tuples = new HashSet <Tuple>(); tuples.Add(partial); } else { // Add possible tuples from each matching triple. tuples = new HashSet <Tuple>(); foreach (var tripleIndex in triples) { var tuple = new Tuple(partial); if (clause.subj.StartsWith("?")) { tuple.Add(clause.subj, process.Bot.Triples[tripleIndex].Subject); } if (clause.pred.StartsWith("?")) { tuple.Add(clause.pred, process.Bot.Triples[tripleIndex].Predicate); } if (clause.obj.StartsWith("?")) { tuple.Add(clause.obj, process.Bot.Triples[tripleIndex].Object); } tuples.Add(tuple); } } var nextClause = startIndex + 1; if (nextClause == this.Clauses.Length) { return(tuples); } // Recurse into the remaining clauses for each possible tuple. result = new HashSet <Tuple>(); // TODO: This recursive strategy involving sets has a minor quirk. // For a query (q: a isA b, notq: b isA x), for subjects a that have more than one predicate isA, // the results depend on the order in which the triples are defined. foreach (var tuple in tuples) { result.UnionWith(this.SelectFromRemainingClauses(process, tuple, nextClause)); } return(result); }
public Uniq(TemplateElementCollection subj, TemplateElementCollection pred, TemplateElementCollection obj) { this.Clause = new Clause(subj, pred, obj, true); }