예제 #1
0
        /// <summary>
        /// Evaluates a Zero or More Path
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public override BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            List <List <INode> > paths = new List <List <INode> >();
            BaseMultiset         initialInput = context.InputMultiset;
            int step = 0, prevCount = 0, skipCount = 0;

            String subjVar = PathStart.VariableName;
            String objVar = PathEnd.VariableName;
            bool   bothTerms = (subjVar == null && objVar == null);
            bool   reverse = false;

            if (subjVar == null || (context.InputMultiset.ContainsVariable(subjVar)))
            {
                // Work Forwards from the Starting Term or Bound Variable
                // OR if there is no Ending Term or Bound Variable work forwards regardless
                if (subjVar == null)
                {
                    paths.Add(((NodeMatchPattern)PathStart).Node.AsEnumerable().ToList());
                }
                else if (context.InputMultiset.ContainsVariable(subjVar))
                {
                    paths.AddRange((from s in context.InputMultiset.Sets
                                    where s[subjVar] != null
                                    select s[subjVar]).Distinct().Select(n => n.AsEnumerable().ToList()));
                }
            }
            else if (objVar == null || (context.InputMultiset.ContainsVariable(objVar)))
            {
                // Work Backwards from Ending Term or Bound Variable
                if (objVar == null)
                {
                    paths.Add(((NodeMatchPattern)PathEnd).Node.AsEnumerable().ToList());
                }
                else
                {
                    paths.AddRange((from s in context.InputMultiset.Sets
                                    where s[objVar] != null
                                    select s[objVar]).Distinct().Select(n => n.AsEnumerable().ToList()));
                }
                reverse = true;
            }

            if (paths.Count == 0)
            {
                GetPathStarts(context, paths, reverse);
            }

            // Traverse the Paths
            do
            {
                prevCount = paths.Count;
                foreach (List <INode> path in paths.Skip(skipCount).ToList())
                {
                    foreach (INode nextStep in EvaluateStep(context, path, reverse))
                    {
                        List <INode> newPath = new List <INode>(path);
                        newPath.Add(nextStep);
                        paths.Add(newPath);
                    }
                }

                // Update Counts
                // skipCount is used to indicate the paths which we will ignore for the purposes of
                // trying to further extend since we've already done them once
                step++;
                if (paths.Count == 0)
                {
                    break;
                }
                skipCount = prevCount;

                // Can short circuit evaluation here if both are terms and any path is acceptable
                if (bothTerms)
                {
                    bool exit = false;
                    foreach (List <INode> path in paths)
                    {
                        if (reverse)
                        {
                            if (PathEnd.Accepts(context, path[0]) && PathStart.Accepts(context, path[path.Count - 1]))
                            {
                                exit = true;
                                break;
                            }
                        }
                        else
                        {
                            if (PathStart.Accepts(context, path[0]) && PathEnd.Accepts(context, path[path.Count - 1]))
                            {
                                exit = true;
                                break;
                            }
                        }
                    }
                    if (exit)
                    {
                        break;
                    }
                }
            } while (paths.Count > prevCount || (step == 1 && paths.Count == prevCount));

            if (paths.Count == 0)
            {
                // If all path starts lead nowhere then we get the Null Multiset as a result
                context.OutputMultiset = new NullMultiset();
            }
            else
            {
                context.OutputMultiset = new Multiset();

                // Evaluate the Paths to check that are acceptable
                HashSet <ISet> returnedPaths = new HashSet <ISet>();
                foreach (List <INode> path in paths)
                {
                    if (reverse)
                    {
                        if (PathEnd.Accepts(context, path[0]) && PathStart.Accepts(context, path[path.Count - 1]))
                        {
                            Set s = new Set();
                            if (!bothTerms)
                            {
                                if (subjVar != null)
                                {
                                    s.Add(subjVar, path[path.Count - 1]);
                                }
                                if (objVar != null)
                                {
                                    s.Add(objVar, path[0]);
                                }
                            }
                            // Make sure to check for uniqueness
                            if (returnedPaths.Contains(s))
                            {
                                continue;
                            }
                            context.OutputMultiset.Add(s);
                            returnedPaths.Add(s);

                            // If both are terms can short circuit evaluation here
                            // It is sufficient just to determine that there is one path possible
                            if (bothTerms)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        if (PathStart.Accepts(context, path[0]) && PathEnd.Accepts(context, path[path.Count - 1]))
                        {
                            Set s = new Set();
                            if (!bothTerms)
                            {
                                if (subjVar != null)
                                {
                                    s.Add(subjVar, path[0]);
                                }
                                if (objVar != null)
                                {
                                    s.Add(objVar, path[path.Count - 1]);
                                }
                            }
                            // Make sure to check for uniqueness
                            if (returnedPaths.Contains(s))
                            {
                                continue;
                            }
                            context.OutputMultiset.Add(s);
                            returnedPaths.Add(s);

                            // If both are terms can short circuit evaluation here
                            // It is sufficient just to determine that there is one path possible
                            if (bothTerms)
                            {
                                break;
                            }
                        }
                    }
                }

                // Now add the zero length paths into
                IEnumerable <INode> nodes;
                if (subjVar != null)
                {
                    if (objVar != null)
                    {
                        nodes = (from s in context.OutputMultiset.Sets
                                 where s[subjVar] != null
                                 select s[subjVar]).Concat(from s in context.OutputMultiset.Sets
                                                           where s[objVar] != null
                                                           select s[objVar]).Distinct();
                    }
                    else
                    {
                        nodes = (from s in context.OutputMultiset.Sets
                                 where s[subjVar] != null
                                 select s[subjVar]).Distinct();
                    }
                }
                else if (objVar != null)
                {
                    nodes = (from s in context.OutputMultiset.Sets
                             where s[objVar] != null
                             select s[objVar]).Distinct();
                }
                else
                {
                    nodes = Enumerable.Empty <INode>();
                }

                if (bothTerms)
                {
                    // If both were terms transform to an Identity/Null Multiset as appropriate
                    if (context.OutputMultiset.IsEmpty)
                    {
                        context.OutputMultiset = new NullMultiset();
                    }
                    else
                    {
                        context.OutputMultiset = new IdentityMultiset();
                    }
                }

                // Then union in the zero length paths
                context.InputMultiset = initialInput;
                ZeroLengthPath zeroPath    = new ZeroLengthPath(PathStart, PathEnd, Path);
                BaseMultiset   currResults = context.OutputMultiset;
                context.OutputMultiset = new Multiset();
                BaseMultiset results = context.Evaluate(zeroPath);//zeroPath.Evaluate(context);
                context.OutputMultiset = currResults;
                foreach (ISet s in results.Sets)
                {
                    if (!context.OutputMultiset.Sets.Contains(s))
                    {
                        context.OutputMultiset.Add(s.Copy());
                    }
                }
            }

            context.InputMultiset = initialInput;
            return(context.OutputMultiset);
        }
예제 #2
0
        /// <summary>
        /// Applies the Filter over the results of evaluating the inner pattern
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public sealed override BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            INode term = this._term.Value(null, 0);

            //First take appropriate pre-filtering actions
            if (context.InputMultiset is IdentityMultiset)
            {
                //If the Input is Identity switch the input to be a Multiset containing a single Set
                //where the variable is bound to the term
                context.InputMultiset = new Multiset();
                Set s = new Set();
                s.Add(this.RestrictionVariable, term);
                context.InputMultiset.Add(s);
            }
            else if (context.InputMultiset is NullMultiset)
            {
                //If Input is Null then output is Null
                context.OutputMultiset = context.InputMultiset;
                return(context.OutputMultiset);
            }
            else
            {
                if (context.InputMultiset.ContainsVariable(this.RestrictionVariable))
                {
                    //If the Input Multiset contains the variable then pre-filter
                    foreach (int id in context.InputMultiset.SetIDs.ToList())
                    {
                        ISet x = context.InputMultiset[id];
                        try
                        {
                            if (x.ContainsVariable(this.RestrictionVariable))
                            {
                                //If does exist check it has appropriate value and if not remove it
                                if (!term.Equals(x[this.RestrictionVariable]))
                                {
                                    context.InputMultiset.Remove(id);
                                }
                            }
                            else
                            {
                                //If doesn't exist for this set then bind it to the term
                                x.Add(this.RestrictionVariable, term);
                            }
                        }
                        catch (RdfQueryException)
                        {
                            context.InputMultiset.Remove(id);
                        }
                    }
                }
                else
                {
                    //If it doesn't contain the variable then bind for each existing set
                    foreach (ISet x in context.InputMultiset.Sets)
                    {
                        x.Add(this.RestrictionVariable, term);
                    }
                }
            }

            //Then evaluate the inner algebra
            BaseMultiset results = context.Evaluate(this.InnerAlgebra);

            if (results is NullMultiset || results is IdentityMultiset)
            {
                return(results);
            }

            //Filter the results to ensure that the variable is indeed bound to the term
            foreach (int id in results.SetIDs.ToList())
            {
                ISet x = results[id];
                try
                {
                    if (!term.Equals(x[this.RestrictionVariable]))
                    {
                        results.Remove(id);
                    }
                }
                catch (RdfQueryException)
                {
                    results.Remove(id);
                }
            }

            if (results.Count > 0)
            {
                context.OutputMultiset = results;
            }
            else
            {
                context.OutputMultiset = new NullMultiset();
            }
            return(context.OutputMultiset);
        }
예제 #3
0
        /// <summary>
        /// Evaluates the Graph Clause by setting up the dataset, applying the pattern and then generating additional bindings if necessary
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            // Q: Can we optimise GRAPH when the input is the Null Multiset to just return the Null Multiset?

            bool datasetOk = false;

            try
            {
                List <String> activeGraphs = new List <string>();

                // Get the URIs of Graphs that should be evaluated over
                if (this._graphSpecifier.TokenType != Token.VARIABLE)
                {
                    switch (this._graphSpecifier.TokenType)
                    {
                    case Token.URI:
                    case Token.QNAME:
                        Uri activeGraphUri = UriFactory.Create(Tools.ResolveUriOrQName(this._graphSpecifier, context.Query.NamespaceMap, context.Query.BaseUri));
                        if (context.Data.HasGraph(activeGraphUri))
                        {
                            // If the Graph is explicitly specified and there are FROM/FROM NAMED present then the Graph
                            // URI must be in the graphs specified by a FROM/FROM NAMED or the result is null
                            if (context.Query == null ||
                                ((!context.Query.DefaultGraphs.Any() && !context.Query.NamedGraphs.Any()) ||
                                 context.Query.NamedGraphs.Any(u => EqualityHelper.AreUrisEqual(activeGraphUri, u)))
                                )
                            {
                                // Either there was no Query
                                // OR there were no Default/Named Graphs (hence any Graph URI is permitted)
                                // OR the specified URI was a Named Graph URI
                                // In any case we can go ahead and set the active Graph
                                activeGraphs.Add(activeGraphUri.AbsoluteUri);
                            }
                            else
                            {
                                // The specified URI was not present in the Named Graphs so return null
                                context.OutputMultiset = new NullMultiset();
                                return(context.OutputMultiset);
                            }
                        }
                        else
                        {
                            // If specifies a specific Graph and not in the Dataset result is a null multiset
                            context.OutputMultiset = new NullMultiset();
                            return(context.OutputMultiset);
                        }
                        break;

                    default:
                        throw new RdfQueryException("Cannot use a '" + this._graphSpecifier.GetType().ToString() + "' Token to specify the Graph for a GRAPH clause");
                    }
                }
                else
                {
                    String gvar = this._graphSpecifier.Value.Substring(1);

                    // Watch out for the case in which the Graph Variable is not bound for all Sets in which case
                    // we still need to operate over all Graphs
                    if (context.InputMultiset.ContainsVariable(gvar) && context.InputMultiset.Sets.All(s => s[gvar] != null))
                    {
                        // If there are already values bound to the Graph variable for all Input Solutions then we limit the Query to those Graphs
                        List <Uri> graphUris = new List <Uri>();
                        foreach (ISet s in context.InputMultiset.Sets)
                        {
                            INode temp = s[gvar];
                            if (temp == null)
                            {
                                continue;
                            }
                            if (temp.NodeType != NodeType.Uri)
                            {
                                continue;
                            }
                            activeGraphs.Add(temp.ToString());
                            graphUris.Add(((IUriNode)temp).Uri);
                        }
                    }
                    else
                    {
                        // Nothing yet bound to the Graph Variable so the Query is over all the named Graphs
                        if (context.Query != null && context.Query.NamedGraphs.Any())
                        {
                            // Query specifies one/more named Graphs
                            activeGraphs.AddRange(context.Query.NamedGraphs.Select(u => u.AbsoluteUri));
                        }
                        else if (context.Query != null && context.Query.DefaultGraphs.Any() && !context.Query.NamedGraphs.Any())
                        {
                            // Gives null since the query dataset does not include any named graphs
                            context.OutputMultiset = new NullMultiset();
                            return(context.OutputMultiset);
                        }
                        else
                        {
                            // Query is over entire dataset/default Graph since no named Graphs are explicitly specified
                            activeGraphs.AddRange(context.Data.GraphUris.Select(u => u.ToSafeString()));
                        }
                    }
                }

                // Remove all duplicates from Active Graphs to avoid duplicate results
                activeGraphs = activeGraphs.Distinct().ToList();

                // Evaluate the inner pattern
                BaseMultiset initialInput = context.InputMultiset;
                BaseMultiset finalResult  = new Multiset();

                // Evalute for each Graph URI and union the results
                foreach (String uri in activeGraphs)
                {
                    // Always use the same Input for each Graph URI and set that Graph to be the Active Graph
                    // Be sure to translate String.Empty back to the null URI to select the default graph
                    // correctly
                    context.InputMultiset = initialInput;
                    Uri currGraphUri = (uri.Equals(String.Empty)) ? null : UriFactory.Create(uri);

                    // Set Active Graph
                    if (currGraphUri == null)
                    {
                        // GRAPH operates over named graphs only so default graph gets skipped
                        continue;
                    }
                    // The result of the HasGraph() call is ignored we just make it so datasets with any kind of
                    // load on demand behaviour work properly
                    context.Data.HasGraph(currGraphUri);
                    // All we actually care about is setting the active graph
                    context.Data.SetActiveGraph(currGraphUri);
                    datasetOk = true;

                    // Evaluate for the current Active Graph
                    BaseMultiset result = context.Evaluate(this._pattern);

                    // Merge the Results into our overall Results
                    if (result is NullMultiset)
                    {
                        // Don't do anything, adds nothing to the results
                    }
                    else if (result is IdentityMultiset)
                    {
                        // Adds a single row to the results
                        if (this._graphSpecifier.TokenType == Token.VARIABLE)
                        {
                            // Include graph variable if not yet bound
                            INode currGraph = new UriNode(null, currGraphUri);
                            Set   s         = new Set();
                            s.Add(this._graphSpecifier.Value.Substring(1), currGraph);
                            finalResult.Add(s);
                        }
                        else
                        {
                            finalResult.Add(new Set());
                        }
                    }
                    else
                    {
                        // If the Graph Specifier is a Variable then we must either bind the
                        // variable or eliminate solutions which have an incorrect value for it
                        if (this._graphSpecifier.TokenType == Token.VARIABLE)
                        {
                            String gvar      = this._graphSpecifier.Value.Substring(1);
                            INode  currGraph = new UriNode(null, currGraphUri);
                            foreach (int id in result.SetIDs.ToList())
                            {
                                ISet s = result[id];
                                if (s[gvar] == null)
                                {
                                    // If Graph Variable is not yet bound for solution bind it
                                    s.Add(gvar, currGraph);
                                }
                                else if (!s[gvar].Equals(currGraph))
                                {
                                    // If Graph Variable is bound for solution and doesn't match
                                    // current Graph then we have to remove the solution
                                    result.Remove(id);
                                }
                            }
                        }
                        // Union solutions into the Results
                        finalResult.Union(result);
                    }

                    // Reset the Active Graph after each pass
                    context.Data.ResetActiveGraph();
                    datasetOk = false;
                }

                // Return the final result
                if (finalResult.IsEmpty)
                {
                    finalResult = new NullMultiset();
                }
                context.OutputMultiset = finalResult;
            }
            finally
            {
                if (datasetOk)
                {
                    context.Data.ResetActiveGraph();
                }
            }

            return(context.OutputMultiset);
        }
예제 #4
0
        /// <summary>
        /// Evaluates the Service Clause by generating instance(s) of <see cref="SparqlRemoteEndpoint">SparqlRemoteEndpoint</see> as required and issuing the query to the remote endpoint(s).
        /// </summary>
        /// <param name="context">Evaluation Context.</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            bool bypassSilent = false;

            try
            {
                SparqlRemoteEndpoint endpoint;
                Uri    endpointUri;
                String baseUri = (context.Query.BaseUri == null) ? String.Empty : context.Query.BaseUri.AbsoluteUri;
                SparqlParameterizedString sparqlQuery = new SparqlParameterizedString("SELECT * WHERE ");

                String pattern = _pattern.ToString();
                pattern = pattern.Substring(pattern.IndexOf('{'));
                sparqlQuery.CommandText += pattern;

                // Pass through LIMIT and OFFSET to the remote service
                if (context.Query.Limit >= 0)
                {
                    // Calculate a LIMIT which is the LIMIT plus the OFFSET
                    // We'll apply OFFSET locally so don't pass that through explicitly
                    int limit = context.Query.Limit;
                    if (context.Query.Offset > 0)
                    {
                        limit += context.Query.Offset;
                    }
                    sparqlQuery.CommandText += " LIMIT " + limit;
                }

                // Select which service to use
                if (_endpointSpecifier.TokenType == Token.URI)
                {
                    endpointUri = UriFactory.Create(Tools.ResolveUri(_endpointSpecifier.Value, baseUri));
                    endpoint    = new SparqlRemoteEndpoint(endpointUri);
                }
                else if (_endpointSpecifier.TokenType == Token.VARIABLE)
                {
                    // Get all the URIs that are bound to this Variable in the Input
                    String var = _endpointSpecifier.Value.Substring(1);
                    if (!context.InputMultiset.ContainsVariable(var))
                    {
                        throw new RdfQueryException("Cannot evaluate a SERVICE clause which uses a Variable as the Service specifier when the Variable is unbound");
                    }
                    List <IUriNode> services = new List <IUriNode>();
                    foreach (ISet s in context.InputMultiset.Sets)
                    {
                        if (s.ContainsVariable(var))
                        {
                            if (s[var].NodeType == NodeType.Uri)
                            {
                                services.Add((IUriNode)s[var]);
                            }
                        }
                    }
                    services = services.Distinct().ToList();

                    // Now generate a Federated Remote Endpoint
                    List <SparqlRemoteEndpoint> serviceEndpoints = new List <SparqlRemoteEndpoint>();
                    services.ForEach(u => serviceEndpoints.Add(new SparqlRemoteEndpoint(u.Uri)));
                    endpoint = new FederatedSparqlRemoteEndpoint(serviceEndpoints);
                }
                else
                {
                    // Note that we must bypass the SILENT operator in this case as this is not an evaluation failure
                    // but a query syntax error
                    bypassSilent = true;
                    throw new RdfQueryException("SERVICE Specifier must be a URI/Variable Token but a " + _endpointSpecifier.GetType().ToString() + " Token was provided");
                }

                // Where possible do substitution and execution to get accurate and correct SERVICE results
                context.OutputMultiset = new Multiset();
                List <String> existingVars = (from v in _pattern.Variables
                                              where context.InputMultiset.ContainsVariable(v)
                                              select v).ToList();

                if (existingVars.Any() || context.Query.Bindings != null)
                {
                    // Pre-bound variables/BINDINGS clause so do substitution and execution

                    // Build the set of possible bindings
                    HashSet <ISet> bindings = new HashSet <ISet>();
                    if (context.Query.Bindings != null && !_pattern.Variables.IsDisjoint(context.Query.Bindings.Variables))
                    {
                        // Possible Bindings comes from BINDINGS clause
                        // In this case each possibility is a distinct binding tuple defined in the BINDINGS clause
                        foreach (BindingTuple tuple in context.Query.Bindings.Tuples)
                        {
                            bindings.Add(new Set(tuple));
                        }
                    }
                    else
                    {
                        // Possible Bindings get built from current input (if there was a BINDINGS clause the variables it defines are not in this SERVICE clause)
                        // In this case each possibility only contains Variables bound so far
                        foreach (ISet s in context.InputMultiset.Sets)
                        {
                            Set t = new Set();
                            foreach (String var in existingVars)
                            {
                                t.Add(var, s[var]);
                            }
                            bindings.Add(t);
                        }
                    }

                    // Execute the Query for every possible Binding and build up our Output Multiset from all the results
                    foreach (ISet s in bindings)
                    {
                        // Q: Should we continue processing here if and when we hit an error?

                        foreach (String var in s.Variables)
                        {
                            sparqlQuery.SetVariable(var, s[var]);
                        }
                        SparqlResultSet results = endpoint.QueryWithResultSet(sparqlQuery.ToString());
                        context.CheckTimeout();

                        foreach (SparqlResult r in results)
                        {
                            Set t = new Set(r);
                            foreach (String var in s.Variables)
                            {
                                t.Add(var, s[var]);
                            }
                            context.OutputMultiset.Add(t);
                        }
                    }

                    return(context.OutputMultiset);
                }
                else
                {
                    // No pre-bound variables/BINDINGS clause so just execute the query

                    // Try and get a Result Set from the Service
                    SparqlResultSet results = endpoint.QueryWithResultSet(sparqlQuery.ToString());

                    // Transform this Result Set back into a Multiset
                    foreach (SparqlResult r in results.Results)
                    {
                        context.OutputMultiset.Add(new Set(r));
                    }

                    return(context.OutputMultiset);
                }
            }
            catch (Exception ex)
            {
                if (_silent && !bypassSilent)
                {
                    // If Evaluation Errors are SILENT is specified then a Multiset containing a single set with all values unbound is returned
                    // Unless some of the SPARQL queries did return results in which we just return the results we did obtain
                    if (context.OutputMultiset.IsEmpty)
                    {
                        Set s = new Set();
                        foreach (String var in _pattern.Variables.Distinct())
                        {
                            s.Add(var, null);
                        }
                        context.OutputMultiset.Add(s);
                    }
                    return(context.OutputMultiset);
                }
                else
                {
                    throw new RdfQueryException("Query execution failed because evaluating a SERVICE clause failed - this may be due to an error with the remote service", ex);
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Evaluates the Negated Property Set.
        /// </summary>
        /// <param name="context">SPARQL Evaluation Context.</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            IEnumerable <Triple> ts;
            String subjVar = _start.VariableName;
            String objVar  = _end.VariableName;

            if (subjVar != null && context.InputMultiset.ContainsVariable(subjVar))
            {
                if (objVar != null && context.InputMultiset.ContainsVariable(objVar))
                {
                    ts = (from s in context.InputMultiset.Sets
                          where s[subjVar] != null && s[objVar] != null
                          from t in context.Data.GetTriplesWithSubjectObject(s[subjVar], s[objVar])
                          select t);
                }
                else
                {
                    ts = (from s in context.InputMultiset.Sets
                          where s[subjVar] != null
                          from t in context.Data.GetTriplesWithSubject(s[subjVar])
                          select t);
                }
            }
            else if (objVar != null && context.InputMultiset.ContainsVariable(objVar))
            {
                ts = (from s in context.InputMultiset.Sets
                      where s[objVar] != null
                      from t in context.Data.GetTriplesWithObject(s[objVar])
                      select t);
            }
            else
            {
                ts = context.Data.Triples;
            }

            context.OutputMultiset = new Multiset();

            // Q: Should this not go at the start of evaluation?
            if (_inverse)
            {
                String temp = objVar;
                objVar  = subjVar;
                subjVar = temp;
            }
            foreach (Triple t in ts)
            {
                if (!_properties.Contains(t.Predicate))
                {
                    Set s = new Set();
                    if (subjVar != null)
                    {
                        s.Add(subjVar, t.Subject);
                    }
                    if (objVar != null)
                    {
                        s.Add(objVar, t.Object);
                    }
                    context.OutputMultiset.Add(s);
                }
            }

            if (subjVar == null && objVar == null)
            {
                if (context.OutputMultiset.Count == 0)
                {
                    context.OutputMultiset = new NullMultiset();
                }
                else
                {
                    context.OutputMultiset = new IdentityMultiset();
                }
            }

            return(context.OutputMultiset);
        }
예제 #6
0
        /// <summary>
        /// Evaluates a Zero Length Path.
        /// </summary>
        /// <param name="context">Evaluation Context.</param>
        /// <returns></returns>
        public override BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            if (AreBothTerms())
            {
                if (AreSameTerms())
                {
                    return(new IdentityMultiset());
                }
                else
                {
                    return(new NullMultiset());
                }
            }

            String subjVar = PathStart.VariableName;
            String objVar  = PathEnd.VariableName;

            context.OutputMultiset = new Multiset();

            // Determine the Triples to which this applies
            if (subjVar != null)
            {
                // Subject is a Variable
                if (context.InputMultiset.ContainsVariable(subjVar))
                {
                    // Subject is Bound
                    if (objVar != null)
                    {
                        // Object is a Variable
                        if (context.InputMultiset.ContainsVariable(objVar))
                        {
                            // Both Subject and Object are Bound
                            foreach (ISet s in context.InputMultiset.Sets.Where(x => x[subjVar] != null && x[objVar] != null && PathStart.Accepts(context, x[subjVar]) && PathEnd.Accepts(context, x[objVar])))
                            {
                                ISet x = new Set();
                                x.Add(subjVar, x[subjVar]);
                                context.OutputMultiset.Add(x);
                                x = new Set();
                                x.Add(objVar, x[objVar]);
                                context.OutputMultiset.Add(x);
                            }
                        }
                        else
                        {
                            // Subject is bound but Object is Unbound
                            foreach (ISet s in context.InputMultiset.Sets.Where(x => x[subjVar] != null && PathStart.Accepts(context, x[subjVar])))
                            {
                                ISet x = s.Copy();
                                x.Add(objVar, x[subjVar]);
                                context.OutputMultiset.Add(x);
                            }
                        }
                    }
                    else
                    {
                        // Object is a Term
                        // Preseve sets where the Object Term is equal to the currently bound Subject
                        INode objTerm = ((NodeMatchPattern)PathEnd).Node;
                        foreach (ISet s in context.InputMultiset.Sets)
                        {
                            INode temp = s[subjVar];
                            if (temp != null && temp.Equals(objTerm))
                            {
                                context.OutputMultiset.Add(s.Copy());
                            }
                        }
                    }
                }
                else
                {
                    // Subject is Unbound
                    if (objVar != null)
                    {
                        // Object is a Variable
                        if (context.InputMultiset.ContainsVariable(objVar))
                        {
                            // Object is Bound but Subject is unbound
                            foreach (ISet s in context.InputMultiset.Sets.Where(x => x[objVar] != null && PathEnd.Accepts(context, x[objVar])))
                            {
                                ISet x = s.Copy();
                                x.Add(subjVar, x[objVar]);
                                context.OutputMultiset.Add(x);
                            }
                        }
                        else
                        {
                            // Subject and Object are Unbound
                            HashSet <INode> nodes = new HashSet <INode>();
                            foreach (Triple t in context.Data.Triples)
                            {
                                nodes.Add(t.Subject);
                                nodes.Add(t.Object);
                            }
                            foreach (INode n in nodes)
                            {
                                Set s = new Set();
                                s.Add(subjVar, n);
                                s.Add(objVar, n);
                                context.OutputMultiset.Add(s);
                            }
                        }
                    }
                    else
                    {
                        // Object is a Term
                        // Create a single set with the Variable bound to the Object Term
                        Set s = new Set();
                        s.Add(subjVar, ((NodeMatchPattern)PathEnd).Node);
                        context.OutputMultiset.Add(s);
                    }
                }
            }
            else if (objVar != null)
            {
                // Subject is a Term but Object is a Variable
                if (context.InputMultiset.ContainsVariable(objVar))
                {
                    // Object is Bound
                    // Preseve sets where the Subject Term is equal to the currently bound Object
                    INode subjTerm = ((NodeMatchPattern)PathStart).Node;
                    foreach (ISet s in context.InputMultiset.Sets)
                    {
                        INode temp = s[objVar];
                        if (temp != null && temp.Equals(subjTerm))
                        {
                            context.OutputMultiset.Add(s.Copy());
                        }
                    }
                }
                else
                {
                    // Object is Unbound
                    // Create a single set with the Variable bound to the Suject Term
                    Set s = new Set();
                    s.Add(objVar, ((NodeMatchPattern)PathStart).Node);
                    context.OutputMultiset.Add(s);
                }
            }
            else
            {
                // Should already have dealt with this earlier (the AreBothTerms() and AreSameTerms() branch)
                throw new RdfQueryException("Reached unexpected point of ZeroLengthPath evaluation");
            }

            return(context.OutputMultiset);
        }
예제 #7
0
        /// <summary>
        /// Evaluates a Zero Length Path
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public override BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            if (this.AreBothTerms())
            {
                if (this.AreSameTerms())
                {
                    return(new IdentityMultiset());
                }
                else
                {
                    return(new NullMultiset());
                }
            }

            String subjVar = this.PathStart.VariableName;
            String objVar  = this.PathEnd.VariableName;

            context.OutputMultiset = new Multiset();

            //Determine the Triples to which this applies
            IEnumerable <Triple> ts = null;

            if (subjVar != null)
            {
                //Subject is a Variable
                if (context.InputMultiset.ContainsVariable(subjVar))
                {
                    //Subject is Bound
                    if (objVar != null)
                    {
                        //Object is a Variable
                        if (context.InputMultiset.ContainsVariable(objVar))
                        {
                            //Object is Bound
                            ts = (from s in context.InputMultiset.Sets
                                  where s[subjVar] != null && s[objVar] != null
                                  from t in context.Data.GetTriplesWithSubjectObject(s[subjVar], s[objVar])
                                  select t);
                        }
                        else
                        {
                            //Object is Unbound
                            ts = (from s in context.InputMultiset.Sets
                                  where s[subjVar] != null
                                  from t in context.Data.GetTriplesWithSubject(s[subjVar])
                                  select t);
                        }
                    }
                    else
                    {
                        //Object is a Term
                        //Preseve sets where the Object Term is equal to the currently bound Subject
                        INode objTerm = ((NodeMatchPattern)this.PathEnd).Node;
                        foreach (ISet s in context.InputMultiset.Sets)
                        {
                            INode temp = s[subjVar];
                            if (temp != null && temp.Equals(objTerm))
                            {
                                context.OutputMultiset.Add(s.Copy());
                            }
                        }
                    }
                }
                else
                {
                    //Subject is Unbound
                    if (objVar != null)
                    {
                        //Object is a Variable
                        if (context.InputMultiset.ContainsVariable(objVar))
                        {
                            //Object is Bound
                            ts = (from s in context.InputMultiset.Sets
                                  where s[objVar] != null
                                  from t in context.Data.GetTriplesWithObject(s[objVar])
                                  select t);
                        }
                        else
                        {
                            //Object is Unbound
                            HashSet <INode> nodes = new HashSet <INode>();
                            foreach (Triple t in context.Data.Triples)
                            {
                                nodes.Add(t.Subject);
                                nodes.Add(t.Object);
                            }
                            foreach (INode n in nodes)
                            {
                                Set s = new Set();
                                s.Add(subjVar, n);
                                s.Add(objVar, n);
                                context.OutputMultiset.Add(s);
                            }
                        }
                    }
                    else
                    {
                        //Object is a Term
                        //Create a single set with the Variable bound to the Object Term
                        Set s = new Set();
                        s.Add(subjVar, ((NodeMatchPattern)this.PathEnd).Node);
                        context.OutputMultiset.Add(s);
                    }
                }
            }
            else if (objVar != null)
            {
                //Subject is a Term but Object is a Variable
                if (context.InputMultiset.ContainsVariable(objVar))
                {
                    //Object is Bound
                    //Preseve sets where the Subject Term is equal to the currently bound Object
                    INode subjTerm = ((NodeMatchPattern)this.PathStart).Node;
                    foreach (ISet s in context.InputMultiset.Sets)
                    {
                        INode temp = s[objVar];
                        if (temp != null && temp.Equals(subjTerm))
                        {
                            context.OutputMultiset.Add(s.Copy());
                        }
                    }
                }
                else
                {
                    //Object is Unbound
                    //Create a single set with the Variable bound to the Suject Term
                    Set s = new Set();
                    s.Add(objVar, ((NodeMatchPattern)this.PathStart).Node);
                    context.OutputMultiset.Add(s);
                }
            }
            else
            {
                //Should already have dealt with this earlier (the AreBothTerms() and AreSameTerms() branch)
                throw new RdfQueryException("Reached unexpected point of ZeroLengthPath evaluation");
            }

            //Get the Matches only if we haven't already generated the output
            if (ts != null)
            {
                HashSet <KeyValuePair <INode, INode> > matches = new HashSet <KeyValuePair <INode, INode> >();
                foreach (Triple t in ts)
                {
                    if (this.PathStart.Accepts(context, t.Subject) && this.PathEnd.Accepts(context, t.Object))
                    {
                        matches.Add(new KeyValuePair <INode, INode>(t.Subject, t.Object));
                    }
                }

                //Generate the Output based on the mathces
                if (matches.Count == 0)
                {
                    context.OutputMultiset = new NullMultiset();
                }
                else
                {
                    if (this.PathStart.VariableName == null && this.PathEnd.VariableName == null)
                    {
                        context.OutputMultiset = new IdentityMultiset();
                    }
                    else
                    {
                        context.OutputMultiset = new Multiset();
                        foreach (KeyValuePair <INode, INode> m in matches)
                        {
                            Set s = new Set();
                            if (subjVar != null)
                            {
                                s.Add(subjVar, m.Key);
                            }
                            if (objVar != null)
                            {
                                s.Add(objVar, m.Value);
                            }
                            context.OutputMultiset.Add(s);
                        }
                    }
                }
            }
            return(context.OutputMultiset);
        }
예제 #8
0
        /// <summary>
        /// Evaluates a setp of the Path.
        /// </summary>
        /// <param name="context">Context.</param>
        /// <param name="path">Paths.</param>
        /// <param name="reverse">Whether to evaluate Paths in reverse.</param>
        /// <returns></returns>
        protected List <INode> EvaluateStep(SparqlEvaluationContext context, List <INode> path, bool reverse)
        {
            if (Path is Property)
            {
                HashSet <INode>      nodes     = new HashSet <INode>();
                INode                predicate = ((Property)Path).Predicate;
                IEnumerable <Triple> ts        = (reverse ? context.Data.GetTriplesWithPredicateObject(predicate, path[path.Count - 1]) : context.Data.GetTriplesWithSubjectPredicate(path[path.Count - 1], predicate));
                foreach (Triple t in ts)
                {
                    if (reverse)
                    {
                        if (!path.Contains(t.Subject))
                        {
                            nodes.Add(t.Subject);
                        }
                    }
                    else
                    {
                        if (!path.Contains(t.Object))
                        {
                            nodes.Add(t.Object);
                        }
                    }
                }
                return(nodes.ToList());
            }
            else
            {
                HashSet <INode> nodes = new HashSet <INode>();

                BaseMultiset    initialInput = context.InputMultiset;
                Multiset        currInput    = new Multiset();
                VariablePattern x            = new VariablePattern("?x");
                VariablePattern y            = new VariablePattern("?y");
                Set             temp         = new Set();
                if (reverse)
                {
                    temp.Add("y", path[path.Count - 1]);
                }
                else
                {
                    temp.Add("x", path[path.Count - 1]);
                }
                currInput.Add(temp);
                context.InputMultiset = currInput;

                Bgp          bgp     = new Bgp(new PropertyPathPattern(x, Path, y));
                BaseMultiset results = context.Evaluate(bgp); //bgp.Evaluate(context);
                context.InputMultiset = initialInput;

                if (!results.IsEmpty)
                {
                    foreach (ISet s in results.Sets)
                    {
                        if (reverse)
                        {
                            if (s["x"] != null)
                            {
                                if (!path.Contains(s["x"]))
                                {
                                    nodes.Add(s["x"]);
                                }
                            }
                        }
                        else
                        {
                            if (s["y"] != null)
                            {
                                if (!path.Contains(s["y"]))
                                {
                                    nodes.Add(s["y"]);
                                }
                            }
                        }
                    }
                }

                return(nodes.ToList());
            }
        }
예제 #9
0
        /// <summary>
        /// Evaluates the One or More Path
        /// </summary>
        /// <param name="context">SPARQL Evaluation Context</param>
        /// <returns></returns>
        public override BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            List <List <INode> > paths = new List <List <INode> >();
            BaseMultiset         initialInput = context.InputMultiset;
            int step = 0, prevCount = 0, skipCount = 0;

            String subjVar = this.PathStart.VariableName;
            String objVar = this.PathEnd.VariableName;
            bool   bothTerms = (subjVar == null && objVar == null);
            bool   reverse = false;

            if (subjVar == null || (subjVar != null && context.InputMultiset.ContainsVariable(subjVar)) || (objVar != null && !context.InputMultiset.ContainsVariable(objVar)))
            {
                //Work Forwards from the Starting Term or Bound Variable
                //OR if there is no Ending Term or Bound Variable work forwards regardless
                if (subjVar == null)
                {
                    paths.Add(((NodeMatchPattern)this.PathStart).Node.AsEnumerable().ToList());
                }
                else if (context.InputMultiset.ContainsVariable(subjVar))
                {
                    paths.AddRange((from s in context.InputMultiset.Sets
                                    where s[subjVar] != null
                                    select s[subjVar]).Distinct().Select(n => n.AsEnumerable().ToList()));
                }
            }
            else if (objVar == null || (objVar != null && context.InputMultiset.ContainsVariable(objVar)))
            {
                //Work Backwards from Ending Term or Bound Variable
                if (objVar == null)
                {
                    paths.Add(((NodeMatchPattern)this.PathEnd).Node.AsEnumerable().ToList());
                }
                else
                {
                    paths.AddRange((from s in context.InputMultiset.Sets
                                    where s[objVar] != null
                                    select s[objVar]).Distinct().Select(n => n.AsEnumerable().ToList()));
                }
                reverse = true;
            }

            if (paths.Count == 0)
            {
                this.GetPathStarts(context, paths, reverse);
            }

            //Traverse the Paths
            do
            {
                prevCount = paths.Count;
                foreach (List <INode> path in paths.Skip(skipCount).ToList())
                {
                    foreach (INode nextStep in this.EvaluateStep(context, path, reverse))
                    {
                        List <INode> newPath = new List <INode>(path);
                        newPath.Add(nextStep);
                        paths.Add(newPath);
                    }
                }

                if (step == 0)
                {
                    //Remove any 1 length paths as these denote path starts that couldn't be traversed
                    paths.RemoveAll(p => p.Count == 1);
                    prevCount = paths.Count;
                }

                //Update Counts
                //skipCount is used to indicate the paths which we will ignore for the purposes of
                //trying to further extend since we've already done them once
                step++;
                if (paths.Count == 0)
                {
                    break;
                }
                if (step > 1)
                {
                    skipCount = prevCount;
                }

                //Can short circuit evaluation here if both are terms and any path is acceptable
                if (bothTerms)
                {
                    bool exit = false;
                    foreach (List <INode> path in paths)
                    {
                        if (reverse)
                        {
                            if (this.PathEnd.Accepts(context, path[0]) && this.PathStart.Accepts(context, path[path.Count - 1]))
                            {
                                exit = true;
                                break;
                            }
                        }
                        else
                        {
                            if (this.PathStart.Accepts(context, path[0]) && this.PathEnd.Accepts(context, path[path.Count - 1]))
                            {
                                exit = true;
                                break;
                            }
                        }
                    }
                    if (exit)
                    {
                        break;
                    }
                }
            } while (paths.Count > prevCount || (step == 1 && paths.Count == prevCount));

            if (paths.Count == 0)
            {
                //If all path starts lead nowhere then we get the Null Multiset as a result
                context.OutputMultiset = new NullMultiset();
            }
            else
            {
                context.OutputMultiset = new Multiset();

                //Evaluate the Paths to check that are acceptable
                foreach (List <INode> path in paths)
                {
                    if (reverse)
                    {
                        if (this.PathEnd.Accepts(context, path[0]) && this.PathStart.Accepts(context, path[path.Count - 1]))
                        {
                            Set s = new Set();
                            if (!bothTerms)
                            {
                                if (subjVar != null)
                                {
                                    s.Add(subjVar, path[path.Count - 1]);
                                }
                                if (objVar != null)
                                {
                                    s.Add(objVar, path[0]);
                                }
                            }
                            context.OutputMultiset.Add(s);

                            //If both are terms can short circuit evaluation here
                            //It is sufficient just to determine that there is one path possible
                            if (bothTerms)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        if (this.PathStart.Accepts(context, path[0]) && this.PathEnd.Accepts(context, path[path.Count - 1]))
                        {
                            Set s = new Set();
                            if (!bothTerms)
                            {
                                if (subjVar != null)
                                {
                                    s.Add(subjVar, path[0]);
                                }
                                if (objVar != null)
                                {
                                    s.Add(objVar, path[path.Count - 1]);
                                }
                            }
                            context.OutputMultiset.Add(s);

                            //If both are terms can short circuit evaluation here
                            //It is sufficient just to determine that there is one path possible
                            if (bothTerms)
                            {
                                break;
                            }
                        }
                    }
                }

                if (bothTerms)
                {
                    //If both were terms transform to an Identity/Null Multiset as appropriate
                    if (context.OutputMultiset.IsEmpty)
                    {
                        context.OutputMultiset = new NullMultiset();
                    }
                    else
                    {
                        context.OutputMultiset = new IdentityMultiset();
                    }
                }
            }

            context.InputMultiset = initialInput;
            return(context.OutputMultiset);
        }
예제 #10
0
        /// <summary>
        /// Applies the Projection to the results of Evaluating the Inner Pattern
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            try
            {
                context.InputMultiset = context.Evaluate(this._pattern);//this._pattern.Evaluate(context);
            }
            catch (RdfQueryTimeoutException)
            {
                //If not partial results throw the error
                if (!context.Query.PartialResultsOnTimeout)
                {
                    throw;
                }
            }

            IEnumerable <SparqlVariable> vars;

            if (context.Query != null)
            {
                vars = context.Query.Variables;
            }
            else
            {
                vars = this._variables;
            }

            //For Null and Identity Multisets this is just a simple selection
            if (context.InputMultiset is NullMultiset)
            {
                context.InputMultiset  = new Multiset(vars.Select(v => v.Name));
                context.OutputMultiset = context.InputMultiset;
            }
            else if (context.InputMultiset is IdentityMultiset)
            {
                context.InputMultiset = new Multiset(vars.Select(v => v.Name));
                Set s = new Set();
                context.InputMultiset.Add(s);
                context.OutputMultiset = context.InputMultiset;
            }

            //If we have a Group Multiset then Projection is more complex
            GroupMultiset groupSet = null;

            if (context.InputMultiset is GroupMultiset)
            {
                groupSet = (GroupMultiset)context.InputMultiset;

                //Project all simple variables for the Groups here
                foreach (SparqlVariable v in vars.Where(v => v.IsResultVariable && !v.IsProjection && !v.IsAggregate))
                {
                    //Can only project a variable if it's used in the GROUP OR if it was assigned by a GROUP BY expression
                    if (context.Query != null)
                    {
                        if (!groupSet.ContainsVariable(v.Name) && !context.Query.GroupBy.Variables.Contains(v.Name))
                        {
                            throw new RdfQueryException("Cannot project the variable ?" + v.Name + " since this Query contains Grouping(s) but the given Variable is not in the GROUP BY - use the SAMPLE aggregate if you need to sample this Variable");
                        }
                    }

                    //Project the value for each variable
                    if (!groupSet.ContainsVariable(v.Name))
                    {
                        //Simple Variable Projection used in GROUP BY so grab first value as all should be same
                        //for the group
                        context.OutputMultiset.AddVariable(v.Name);
                        foreach (int id in groupSet.SetIDs)
                        {
                            INode value = groupSet.Contents[groupSet.GroupSetIDs(id).First()][v.Name];
                            context.OutputMultiset[id].Add(v.Name, value);
                        }
                    }
                }
            }
            else if (context.Query.IsAggregate)
            {
                context.OutputMultiset = new Multiset();
            }

            //Project the rest of the Variables
            Set aggSet = new Set();

            foreach (SparqlVariable v in vars.Where(v => v.IsResultVariable))
            {
                if (groupSet == null)
                {
                    context.InputMultiset.AddVariable(v.Name);
                }
                else
                {
                    context.OutputMultiset.AddVariable(v.Name);
                }

                if (v.IsAggregate)
                {
                    //Compute the Aggregate
                    if (groupSet != null)
                    {
                        context.InputMultiset = groupSet.Contents;
                        foreach (int id in groupSet.SetIDs)
                        {
                            INode aggValue = v.Aggregate.Apply(context, groupSet.GroupSetIDs(id));
                            context.OutputMultiset[id].Add(v.Name, aggValue);
                        }
                        context.InputMultiset = groupSet;
                    }
                    else
                    {
                        INode aggValue = v.Aggregate.Apply(context, context.InputMultiset.SetIDs);
                        aggSet.Add(v.Name, aggValue);
                    }
                }
                else if (v.IsProjection)
                {
                    if (context.Query != null && context.Query.IsAggregate && context.Query.GroupBy == null)
                    {
                        throw new RdfQueryException("Cannot project an expression since this Query contains Aggregates and no GROUP BY");
                    }
                    else
                    {
                        //Compute the Value of the Projection Expression for each Set
                        foreach (int id in context.InputMultiset.SetIDs)
                        {
                            ISet s = context.InputMultiset[id];
                            try
                            {
                                INode temp = v.Projection.Value(context, id);
                                s.Add(v.Name, temp);
                            }
                            catch (RdfQueryException)
                            {
                                s.Add(v.Name, null);
                            }
                        }
                    }
                }
                else
                {
                    if (context.Query != null && context.Query.IsAggregate && context.Query.GroupBy == null)
                    {
                        //If this is an Aggregate without a GROUP BY projected variables are invalid
                        throw new RdfQueryException("Cannot project the variable ?" + v.Name + " since this Query contains Aggregates and no GROUP BY");
                    }
                    else if (context.Query != null && context.Query.IsAggregate && !context.Query.GroupBy.ProjectableVariables.Contains(v.Name))
                    {
                        //If this is an Aggregate with a GROUP BY projected variables are only valid if they occur in the GROUP BY
                        throw new RdfQueryException("Cannot project the variable ?" + v.Name + " since this Query contains Aggregates but the given Variable is not in the GROUP BY - use the SAMPLE aggregate if you need to access this variable");
                    }

                    //Otherwise we don't need to do anything with the Variable
                }
            }

            if (context.Query != null && context.Query.IsAggregate && context.Query.GroupBy == null)
            {
                context.OutputMultiset.Add(aggSet);
            }
            else
            {
                context.OutputMultiset = context.InputMultiset;
            }

            return(context.OutputMultiset);
        }