示例#1
0
        /// <summary>
        /// Parser method which parses a Binding Object which occurs in the array of Bindings
        /// </summary>
        private void ParseBinding(SparqlJsonParserContext context, bool headSeen)
        {
            //Can we read some properties
            if (context.Input.Read())
            {
                SparqlResult result = new SparqlResult();
                while (context.Input.TokenType != JsonToken.EndObject)
                {
                    if (context.Input.TokenType == JsonToken.PropertyName)
                    {
                        //Each Property Name should be for a variable
                        this.ParseBoundVariable(context, context.Input.Value.ToString(), result, headSeen);
                    }
                    else
                    {
                        throw Error(context, "Unexpected Token '" + context.Input.TokenType + "' with value '" + context.Input.Value + "' encountered, expected a Property Name giving the Binding for a Variable for this Result");
                    }

                    //Get Next Token
                    if (!context.Input.Read())
                    {
                        throw new RdfParseException("Unexpected End of Input while trying to parse a Binding Object");
                    }
                }

                //Check that all Variables are bound for a given result binding nulls where appropriate
                foreach (String v in context.Variables)
                {
                    if (!result.HasValue(v))
                    {
                        result.SetValue(v, null);
                    }
                }

                //Add to Results
                result.SetVariableOrdering(context.Variables);
                if (!context.Handler.HandleResult(result))
                {
                    ParserHelper.Stop();
                }
            }
            else
            {
                throw new RdfParseException("Unexpected End of Input while trying to parse a Binding Object");
            }
        }
示例#2
0
        private void TryParseResultRow(TokenisingResultParserContext context)
        {
            IToken next = context.Tokens.Peek();
            if (next.TokenType == Token.EOF)
            {
                context.Tokens.Dequeue();
                return;
            }

            bool allowEOL = true, expectComma = false;
            int v = 0;
            SparqlResult result = new SparqlResult();
            while (true)
            {
                next = context.Tokens.Dequeue();
                switch (next.TokenType)
                {

                    case Token.BLANKNODEWITHID:
                        if (expectComma) throw ParserHelper.Error("Unexpected Blank Node, expected a comma between RDF Terms", next);
                        if (v >= context.Variables.Count) throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                        INode blank = context.Handler.CreateBlankNode(next.Value.Substring(2));
                        result.SetValue(context.Variables[v], blank);
                        v++;
                        allowEOL = true;
                        expectComma = true;
                        break;

                    case Token.LITERAL:
                    case Token.PLAINLITERAL:
                        if (expectComma) throw ParserHelper.Error("Unexpected Blank Node, expected a comma between RDF Terms", next);
                        if (v >= context.Variables.Count) throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);

                        //Try and guess what kind of term this is
                        String lexicalForm = next.Value;
                        INode value;
                        if (lexicalForm.StartsWith("http://") || lexicalForm.StartsWith("https://") || lexicalForm.StartsWith("mailto:") || lexicalForm.StartsWith("ftp://"))
                        {
                            try
                            {
                                //Guessing a URI if starts with common URI prefix
                                value = context.Handler.CreateUriNode(UriFactory.Create(lexicalForm));
                            }
                            catch
                            {
                                //If invalid URI fall back to treating as literal
                                value = context.Handler.CreateLiteralNode(lexicalForm);
                            }
                        }
                        else
                        {
                            value = context.Handler.CreateLiteralNode(lexicalForm);
                        }

                        result.SetValue(context.Variables[v], value);
                        v++;
                        allowEOL = true;
                        expectComma = true;
                        break;

                    case Token.EOL:
                        if (allowEOL)
                        {
                            break;
                        }
                        else
                        {
                            if (v == context.Variables.Count - 1)
                            {
                                //If this is the last expected term then this must be an empty term
                                v++;
                                break;
                            }
                            throw ParserHelper.Error("Unexpected End of Line, expected a RDF Term Token", next);
                        }

                    case Token.COMMA:
                        if (!expectComma)
                        {
                            //This is an empty field
                            if (v >= context.Variables.Count) throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                            v++;
                        }
                        expectComma = false;
                        allowEOL = false;
                        break;

                    case Token.EOF:
                        if (!allowEOL) throw ParserHelper.Error("Unexpected EOF, expected another RDF Term for the Result Row", next);
                        break;

                    default:
                        throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered", next);
                 }

                //Stop when we've hit the End of the Line/File
                if (next.TokenType == Token.EOL || next.TokenType == Token.EOF) break;
            }

            if (!context.Handler.HandleResult(result)) ParserHelper.Stop();
        }
        /// <summary>
        /// Internal method which actually parses the Result Set by traversing the RDF Graph appropriately
        /// </summary>
        /// <param name="context">Parser Context</param>
        private void Parse(SparqlRdfParserContext context)
        {
            try
            {
                context.Handler.StartResults();

                //Create relevant Nodes
                context.Graph.NamespaceMap.AddNamespace("rdf", UriFactory.Create(NamespaceMapper.RDF));
                context.Graph.NamespaceMap.AddNamespace("rs", UriFactory.Create(SparqlSpecsHelper.SparqlRdfResultsNamespace));
                IUriNode rdfType        = context.Graph.CreateUriNode("rdf:type");
                IUriNode resultSetClass = context.Graph.CreateUriNode("rs:ResultSet");
                IUriNode resultVariable = context.Graph.CreateUriNode("rs:resultVariable");
                IUriNode solution       = context.Graph.CreateUriNode("rs:solution");
                IUriNode binding        = context.Graph.CreateUriNode("rs:binding");
                IUriNode value          = context.Graph.CreateUriNode("rs:value");
                IUriNode variable       = context.Graph.CreateUriNode("rs:variable");
                IUriNode boolean        = context.Graph.CreateUriNode("rs:boolean");

                //Try to get a ResultSet object
                Triple rset = context.Graph.Triples.WithPredicateObject(rdfType, resultSetClass).FirstOrDefault();
                if (rset != null)
                {
                    INode rsetID = rset.Subject;

                    //Find the Variables the Result Set contains or the Boolean Value
                    List <Triple> temp = context.Graph.Triples.WithSubjectPredicate(rsetID, boolean).ToList();
                    if (temp.Count > 0)
                    {
                        if (temp.Count > 1)
                        {
                            throw new RdfParseException("Result Set has more than one boolean result defined for it");
                        }

                        Triple booleanResult = temp.First();
                        INode  result        = booleanResult.Object;
                        if (result.NodeType == NodeType.Literal)
                        {
                            ILiteralNode lit = (ILiteralNode)result;
                            if (lit.DataType != null)
                            {
                                if (lit.DataType.AbsoluteUri.Equals(XmlSpecsHelper.XmlSchemaDataTypeBoolean))
                                {
                                    bool b;
                                    if (Boolean.TryParse(lit.Value, out b))
                                    {
                                        context.Handler.HandleBooleanResult(b);
                                        return;
                                    }
                                    else
                                    {
                                        throw new RdfParseException("Result Set has a boolean result which is a Literal typed as boolean but which does not contain a valid boolean value");
                                    }
                                }
                                else
                                {
                                    throw new RdfParseException("Result Set has a boolean result which is a Literal which is not boolean typed");
                                }
                            }
                            else
                            {
                                throw new RdfParseException("Result Set has a boolean result which is a Literal which is not typed as a boolean");
                            }
                        }
                        else
                        {
                            throw new RdfParseException("Result Set has a boolean result which is not a Literal Node");
                        }
                    }
                    else
                    {
                        //We're expected one/more variables
                        temp = context.Graph.Triples.WithSubjectPredicate(rsetID, resultVariable).ToList();
                        if (temp.Count > 0)
                        {
                            foreach (Triple t in temp)
                            {
                                if (t.Object.NodeType == NodeType.Literal)
                                {
                                    if (!context.Handler.HandleVariable(((ILiteralNode)t.Object).Value))
                                    {
                                        ParserHelper.Stop();
                                    }
                                    context.Variables.Add(((ILiteralNode)t.Object).Value);
                                }
                                else
                                {
                                    throw new RdfParseException("Result Set has a result variable definition which is not a Literal Node");
                                }
                            }
                        }
                        else
                        {
                            throw new RdfParseException("Result Set does not define any result variables or a boolean result");
                        }

                        //Then we're expecting some Solutions
                        temp = context.Graph.Triples.WithSubjectPredicate(rsetID, solution).ToList();
                        foreach (Triple slnTriple in temp)
                        {
                            //Each Solution has some Bindings
                            INode        slnID = slnTriple.Object;
                            bool         ok    = false;
                            SparqlResult r     = new SparqlResult();

                            foreach (Triple bindingTriple in context.Graph.Triples.WithSubjectPredicate(slnID, binding))
                            {
                                //Each Binding has a Variable and a Value
                                ok = true;
                                INode  bindingID = bindingTriple.Object;
                                String var       = String.Empty;
                                INode  val       = null;

                                //Retrieve the Variable and the Bound Value
                                foreach (Triple valueTriple in context.Graph.Triples.WithSubject(bindingID))
                                {
                                    if (valueTriple.Predicate.Equals(variable))
                                    {
                                        if (!var.Equals(String.Empty))
                                        {
                                            throw new RdfParseException("Result Set contains a Binding which refers to more than one Variable");
                                        }
                                        if (valueTriple.Object.NodeType != NodeType.Literal)
                                        {
                                            throw new RdfParseException("Result Set contains a Binding which refers to a Variable but not by a Literal Node as required");
                                        }
                                        var = ((ILiteralNode)valueTriple.Object).Value;
                                    }
                                    else if (valueTriple.Predicate.Equals(value))
                                    {
                                        if (val != null)
                                        {
                                            throw new RdfParseException("Result Set contains a Binding which has more than one Value");
                                        }
                                        val = valueTriple.Object;
                                    }
                                }
                                if (var.Equals(String.Empty) || val == null)
                                {
                                    throw new RdfParseException("Result Set contains a Binding which doesn't contain both a Variable and a Value");
                                }

                                //Check that the Variable was defined in the Header
                                if (!context.Variables.Contains(var))
                                {
                                    throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <binding> element attempts to bind a value to the variable '" + var + "' which is not defined in the <head> by a <variable> element!");
                                }

                                r.SetValue(var, val);
                            }
                            if (!ok)
                            {
                                throw new RdfParseException("Result Set contains a Solution which has no Bindings");
                            }

                            //Check that all Variables are bound for a given result binding nulls where appropriate
                            foreach (String v in context.Variables)
                            {
                                if (!r.HasValue(v))
                                {
                                    r.SetValue(v, null);
                                }
                            }

                            if (!context.Handler.HandleResult(r))
                            {
                                ParserHelper.Stop();
                            }
                        }
                    }
                }
                else
                {
                    throw new RdfParseException("No Result Set object is defined in the Graph");
                }

                context.Handler.EndResults(true);
            }
            catch (RdfParsingTerminatedException)
            {
                context.Handler.EndResults(true);
            }
            catch
            {
                context.Handler.EndResults(false);
                throw;
            }
        }
示例#4
0
        private void TryParseResultRow(TokenisingResultParserContext context)
        {
            IToken next = context.Tokens.Peek();
            if (next.TokenType == Token.EOF)
            {
                context.Tokens.Dequeue();
                return;
            }

            bool allowEOL = true, expectTab = false;
            int v = 0;
            SparqlResult result = new SparqlResult();
            while (true)
            {
                next = context.Tokens.Dequeue();
                switch (next.TokenType)
                {
                    case Token.URI:
                        if (expectTab) throw ParserHelper.Error("Unexpected URI, expected a Tab between RDF Terms", next);
                        if (v >= context.Variables.Count) throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                        INode uri = ParserHelper.TryResolveUri(context, next);
                        result.SetValue(context.Variables[v], uri);
                        v++;
                        allowEOL = true;
                        expectTab = true;
                        break;

                    case Token.BLANKNODEWITHID:
                        if (expectTab) throw ParserHelper.Error("Unexpected Blank Node, expected a Tab between RDF Terms", next);
                        if (v >= context.Variables.Count) throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                        INode blank = context.Handler.CreateBlankNode(next.Value.Substring(2));
                        result.SetValue(context.Variables[v], blank);
                        v++;
                        allowEOL = true;
                        expectTab = true;
                        break;

                    case Token.LITERAL:
                    case Token.LONGLITERAL:
                    case Token.PLAINLITERAL:
                        if (expectTab) throw ParserHelper.Error("Unexpected Blank Node, expected a Tab between RDF Terms", next);
                        if (v >= context.Variables.Count) throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                        INode lit = this.TryParseLiteral(context, next);
                        result.SetValue(context.Variables[v], lit);
                        v++;
                        allowEOL = true;
                        expectTab = true;
                        break;

                    case Token.EOL:
                        if (allowEOL)
                        {
                            break;
                        }
                        else
                        {
                            if (v == context.Variables.Count - 1)
                            {
                                //If this is the last expected term then this must be an empty term
                                v++;
                                break;
                            }
                            throw ParserHelper.Error("Unexpected End of Line, expected a RDF Term Token", next);
                        }

                    case Token.TAB:
                        if (!expectTab)
                        {
                            //This is an empty field
                            if (v >= context.Variables.Count) throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                            v++;
                        }
                        expectTab = false;
                        allowEOL = false;
                        break;

                    case Token.EOF:
                        if (!allowEOL) throw ParserHelper.Error("Unexpected EOF, expected another RDF Term for the Result Row", next);
                        break;

                    default:
                        throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered", next);
                 }

                //Stop when we've hit the End of the Line/File
                if (next.TokenType == Token.EOL || next.TokenType == Token.EOF) break;
            }

            if (!context.Handler.HandleResult(result)) ParserHelper.Stop();
        }
        /// <summary>
        /// Parser method which parses a Bound Variable Object which occurs within a Binding Object
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="var">Variable Name</param>
        /// <param name="r">Result Object that is being constructed from the Binding Object</param>
        private void ParseBoundVariable(SparqlJsonParserContext context, String var, SparqlResult r)
        {
            String token, nodeValue, nodeType, nodeLang, nodeDatatype;
            nodeValue = nodeType = nodeLang = nodeDatatype = null;

            //Can we read the start of an Object
            if (context.Input.Read())
            {
                if (context.Input.TokenType == JsonToken.StartObject)
                {
                    context.Input.Read();

                    while (context.Input.TokenType != JsonToken.EndObject)
                    {
                        token = context.Input.Value.ToString().ToLower();

                        //Check that we get a Property Value as a String
                        context.Input.Read();
                        if (context.Input.TokenType != JsonToken.String)
                        {
                            throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, expected a Property Value describing one of the properties of an Variable Binding");
                        }

                        //Extract the Information from the Object
                        if (token.Equals("value"))
                        {
                            nodeValue = context.Input.Value.ToString();
                        }
                        else if (token.Equals("type"))
                        {
                            nodeType = context.Input.Value.ToString().ToLower();
                        }
                        else if (token.Equals("lang") || token.Equals("xml:lang"))
                        {
                            if (nodeLang == null && nodeDatatype == null)
                            {
                                nodeLang = context.Input.Value.ToString();
                            }
                            else
                            {
                                throw Error(context, "Unexpected Language Property specified for an Object Node where a Language or Datatype has already been specified");
                            }
                        }
                        else if (token.Equals("datatype"))
                        {
                            if (nodeDatatype == null && nodeLang == null)
                            {
                                nodeDatatype = context.Input.Value.ToString();
                            }
                            else
                            {
                                throw Error(context, "Unexpected Datatype Property specified for an Object Node where a Language or Datatype has already been specified");
                            }
                        }
                        else
                        {
                            throw Error(context, "Unexpected Property '" + token + "' specified for an Object Node, only 'value', 'type', 'lang' and 'datatype' are valid properties");
                        }

                        //Get Next Token
                        if (!context.Input.Read())
                        {
                            throw new RdfParseException("Unexpected End of Input while trying to parse a Bound Variable Object");
                        }
                    }

                    //Validate the Information
                    if (nodeType == null)
                    {
                        throw new RdfParseException("Cannot parse a Node from the JSON where no 'type' property was specified in the JSON Object representing the Node");
                    }
                    if (nodeValue == null)
                    {
                        throw new RdfParseException("Cannot parse a Node from the JSON where no 'value' property was specified in the JSON Object representing the Node");
                    }

                    //Turn this information into a Node
                    INode n;
                    if (nodeType.Equals("uri"))
                    {
                        n = context.Handler.CreateUriNode(new Uri(nodeValue));
                    }
                    else if (nodeType.Equals("bnode"))
                    {
                        if (nodeValue.StartsWith("_:"))
                        {
                            n = context.Handler.CreateBlankNode(nodeValue.Substring(2));
                        }
                        else if (nodeValue.Contains("://"))
                        {
                            n = context.Handler.CreateBlankNode(nodeValue.Substring(nodeValue.IndexOf("://") + 3));
                        }
                        else if (nodeValue.Contains(":"))
                        {
                            n = context.Handler.CreateBlankNode(nodeValue.Substring(nodeValue.LastIndexOf(':') + 1));
                        }
                        else
                        {
                            n = context.Handler.CreateBlankNode(nodeValue);
                        }
                    }
                    else if (nodeType.Equals("literal") || nodeType.Equals("typed-literal"))
                    {
                        if (nodeLang != null)
                        {
                            n = context.Handler.CreateLiteralNode(nodeValue, nodeLang);
                        }
                        else if (nodeDatatype != null)
                        {
                            n = context.Handler.CreateLiteralNode(nodeValue, new Uri(nodeDatatype));
                        }
                        else
                        {
                            n = context.Handler.CreateLiteralNode(nodeValue);
                        }
                    }
                    else
                    {
                        throw new RdfParseException("Cannot parse a Node from the JSON where the 'type' property has a value of '" + nodeType + "' which is not one of the permitted values 'uri', 'bnode', 'literal' or 'typed-literal' in the JSON Object representing the Node");
                    }

                    //Check that the Variable was defined in the Header
                    if (!context.Variables.Contains(var))
                    {
                        throw new RdfParseException("Unable to Parse a SPARQL Result Set since a Binding Object attempts to bind a value to the variable '" + var + "' which is not defined in the Header Object in the value for the 'vars' property!");
                    }

                    //Add to the result
                    r.SetValue(var, n);
                }
                else
                {
                    throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, expected the start of a Bound Variable Object");
                }
            }
            else
            {
                throw Error(context, "Unexpected End of Input while trying to parse a Bound Variable Object");
            }
        }
        /// <summary>
        /// Parser method which parses a Binding Object which occurs in the array of Bindings
        /// </summary>
        private void ParseBinding(SparqlJsonParserContext context)
        {
            //Can we read some properties
            if (context.Input.Read())
            {
                SparqlResult result = new SparqlResult();
                while (context.Input.TokenType != JsonToken.EndObject)
                {
                    if (context.Input.TokenType == JsonToken.PropertyName)
                    {
                        //Each Property Name should be for a variable
                        this.ParseBoundVariable(context, context.Input.Value.ToString(), result);
                    }
                    else
                    {
                        throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, expected a Property Name giving the Binding for a Variable for this Result");
                    }

                    //Get Next Token
                    if (!context.Input.Read())
                    {
                        throw new RdfParseException("Unexpected End of Input while trying to parse a Binding Object");
                    }
                }

                //Check that all Variables are bound for a given result binding nulls where appropriate
                foreach (String v in context.Variables)
                {
                    if (!result.HasValue(v))
                    {
                        result.SetValue(v, null);
                    }
                }

                //Add to Results
                if (!context.Handler.HandleResult(result)) throw ParserHelper.Stop();
            }
            else
            {
                throw new RdfParseException("Unexpected End of Input while trying to parse a Binding Object");
            }
        }
示例#7
0
        private void TryParseResultRow(TokenisingResultParserContext context)
        {
            IToken next = context.Tokens.Peek();

            if (next.TokenType == Token.EOF)
            {
                context.Tokens.Dequeue();
                return;
            }

            bool         allowEOL = true, expectTab = false;
            int          v      = 0;
            SparqlResult result = new SparqlResult();

            while (true)
            {
                next = context.Tokens.Dequeue();
                switch (next.TokenType)
                {
                case Token.URI:
                    if (expectTab)
                    {
                        throw ParserHelper.Error("Unexpected URI, expected a Tab between RDF Terms", next);
                    }
                    if (v >= context.Variables.Count)
                    {
                        throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                    }
                    INode uri = ParserHelper.TryResolveUri(context, next);
                    result.SetValue(context.Variables[v], uri);
                    v++;
                    allowEOL  = true;
                    expectTab = true;
                    break;

                case Token.BLANKNODEWITHID:
                    if (expectTab)
                    {
                        throw ParserHelper.Error("Unexpected Blank Node, expected a Tab between RDF Terms", next);
                    }
                    if (v >= context.Variables.Count)
                    {
                        throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                    }
                    INode blank = context.Handler.CreateBlankNode(next.Value.Substring(2));
                    result.SetValue(context.Variables[v], blank);
                    v++;
                    allowEOL  = true;
                    expectTab = true;
                    break;

                case Token.LITERAL:
                case Token.LONGLITERAL:
                case Token.PLAINLITERAL:
                    if (expectTab)
                    {
                        throw ParserHelper.Error("Unexpected Blank Node, expected a Tab between RDF Terms", next);
                    }
                    if (v >= context.Variables.Count)
                    {
                        throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                    }
                    INode lit = TryParseLiteral(context, next);
                    result.SetValue(context.Variables[v], lit);
                    v++;
                    allowEOL  = true;
                    expectTab = true;
                    break;

                case Token.EOL:
                    if (allowEOL)
                    {
                        break;
                    }
                    else
                    {
                        if (v == context.Variables.Count - 1)
                        {
                            // If this is the last expected term then this must be an empty term
                            v++;
                            break;
                        }
                        throw ParserHelper.Error("Unexpected End of Line, expected a RDF Term Token", next);
                    }

                case Token.TAB:
                    if (!expectTab)
                    {
                        // This is an empty field
                        if (v >= context.Variables.Count)
                        {
                            throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                        }
                        v++;
                    }
                    expectTab = false;
                    allowEOL  = false;
                    break;

                case Token.EOF:
                    if (!allowEOL)
                    {
                        throw ParserHelper.Error("Unexpected EOF, expected another RDF Term for the Result Row", next);
                    }
                    break;

                default:
                    throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered", next);
                }

                // Stop when we've hit the End of the Line/File
                if (next.TokenType == Token.EOL || next.TokenType == Token.EOF)
                {
                    break;
                }
            }

            if (v < context.Variables.Count)
            {
                throw ParserHelper.Error("Too few RDF Terms, got " + v + " but expected " + context.Variables.Count, next);
            }

            result.SetVariableOrdering(context.Variables);
            if (!context.Handler.HandleResult(result))
            {
                ParserHelper.Stop();
            }
        }
        private void TryParseResultRow(TokenisingResultParserContext context)
        {
            IToken next = context.Tokens.Peek();

            if (next.TokenType == Token.EOF)
            {
                context.Tokens.Dequeue();
                return;
            }

            bool         allowEOL = true, expectComma = false;
            int          v      = 0;
            SparqlResult result = new SparqlResult();

            while (true)
            {
                next = context.Tokens.Dequeue();
                switch (next.TokenType)
                {
                case Token.BLANKNODEWITHID:
                    if (expectComma)
                    {
                        throw ParserHelper.Error("Unexpected Blank Node, expected a comma between RDF Terms", next);
                    }
                    if (v >= context.Variables.Count)
                    {
                        throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                    }
                    INode blank = context.Handler.CreateBlankNode(next.Value.Substring(2));
                    result.SetValue(context.Variables[v], blank);
                    v++;
                    allowEOL    = true;
                    expectComma = true;
                    break;

                case Token.LITERAL:
                case Token.PLAINLITERAL:
                    if (expectComma)
                    {
                        throw ParserHelper.Error("Unexpected Blank Node, expected a comma between RDF Terms", next);
                    }
                    if (v >= context.Variables.Count)
                    {
                        throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                    }

                    // Try and guess what kind of term this is
                    String lexicalForm = next.Value;
                    INode  value;
                    if (lexicalForm.StartsWith("http://") || lexicalForm.StartsWith("https://") || lexicalForm.StartsWith("mailto:") || lexicalForm.StartsWith("ftp://"))
                    {
                        try
                        {
                            // Guessing a URI if starts with common URI prefix
                            value = ParserHelper.TryResolveUri(context, next);
                        }
                        catch
                        {
                            // If invalid URI fall back to treating as literal
                            value = context.Handler.CreateLiteralNode(lexicalForm);
                        }
                    }
                    else
                    {
                        value = context.Handler.CreateLiteralNode(lexicalForm);
                    }

                    result.SetValue(context.Variables[v], value);
                    v++;
                    allowEOL    = true;
                    expectComma = true;
                    break;

                case Token.EOL:
                    if (allowEOL)
                    {
                        break;
                    }
                    else
                    {
                        if (v == context.Variables.Count - 1)
                        {
                            // If this is the last expected term then this must be an empty term
                            v++;
                            break;
                        }
                        throw ParserHelper.Error("Unexpected End of Line, expected a RDF Term Token", next);
                    }

                case Token.COMMA:
                    if (!expectComma)
                    {
                        // This is an empty field
                        if (v >= context.Variables.Count)
                        {
                            throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                        }
                        v++;
                    }
                    expectComma = false;
                    allowEOL    = false;
                    break;

                case Token.EOF:
                    if (!allowEOL)
                    {
                        throw ParserHelper.Error("Unexpected EOF, expected another RDF Term for the Result Row", next);
                    }
                    break;

                default:
                    throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered", next);
                }

                // Stop when we've hit the End of the Line/File
                if (next.TokenType == Token.EOL || next.TokenType == Token.EOF)
                {
                    break;
                }
            }

            result.SetVariableOrdering(context.Variables);
            if (!context.Handler.HandleResult(result))
            {
                ParserHelper.Stop();
            }
        }
        /// <summary>
        /// Parses the XML Result Set format into a set of SPARQLResult objects
        /// </summary>
        /// <param name="context">Parser Context</param>
        private void Parse(SparqlXmlParserContext context)
        {
            try
            {
                context.Handler.StartResults();

                // Get the Document Element and check it's a Sparql element
                if (!context.Input.Read())
                {
                    throw new RdfParseException("Unable to Parse a SPARQL Result Set as it was not possible to read a document element from the input");
                }
                while (context.Input.NodeType != XmlNodeType.Element)
                {
                    if (!context.Input.Read())
                    {
                        throw new RdfParseException("Unable to Parse a SPARQL Result Set as it was not possible to read a document element from the input");
                    }
                }
                if (!context.Input.Name.Equals("sparql"))
                {
                    throw new RdfParseException("Unable to Parse a SPARQL Result Set from the provided XML since the Document Element is not a <sparql> element!");
                }

                // Go through it's attributes and check the Namespace is specified
                bool nsfound = false;
                if (context.Input.HasAttributes)
                {
                    for (int i = 0; i < context.Input.AttributeCount; i++)
                    {
                        context.Input.MoveToNextAttribute();
                        if (context.Input.Name.Equals("xmlns"))
                        {
                            if (!context.Input.Value.Equals(SparqlSpecsHelper.SparqlNamespace))
                            {
                                throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <sparql> element has an incorrect Namespace!");
                            }
                            else
                            {
                                nsfound = true;
                            }
                        }
                    }
                }
                if (!nsfound)
                {
                    throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <sparql> element fails to specify the SPARQL Namespace!");
                }

                // Get the Variables from the Header
                if (!context.Input.Read())
                {
                    throw new RdfParseException("Unable to Parse a SPARQL Result Set as could not read a <head> element from the input");
                }
                if (!context.Input.Name.Equals("head"))
                {
                    throw new RdfParseException("Unable to Parse a SPARQL Result Set since the first Child Node of the <sparql> element is not the required <head> element!");
                }

                // Only parser <variable> and <link> elements if not an empty <head /> element
                if (!context.Input.IsEmptyElement)
                {
                    while (context.Input.Read())
                    {
                        // Stop reading when we hit the </head>
                        if (context.Input.NodeType == XmlNodeType.EndElement && context.Input.Name.Equals("head"))
                        {
                            break;
                        }

                        // Looking for <variable> elements
                        if (context.Input.Name.Equals("variable"))
                        {
                            // Should only have 1 attribute
                            if (context.Input.AttributeCount != 1)
                            {
                                throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <variable> element has too few/many attributes, only a 'name' attribute should be present!");
                            }
                            else
                            {
                                // Add the Variable to the list
                                context.Input.MoveToNextAttribute();
                                if (!context.Handler.HandleVariable(context.Input.Value))
                                {
                                    ParserHelper.Stop();
                                }
                                context.Variables.Add(context.Input.Value);
                            }
                        }
                        else if (context.Input.Name.Equals("link"))
                        {
                            // Not bothered about <link> elements
                        }
                        else
                        {
                            // Some unexpected element
                            throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <head> contains an unexpected element <" + context.Input.Name + ">!");
                        }
                    }
                }

                if (!context.Input.Name.Equals("head"))
                {
                    throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of the input before the closing </head> element was found");
                }

                // Look at the <results> or <boolean> element
                if (!context.Input.Read())
                {
                    throw new RdfParseException("Unable to Parse a SPARQL Result Set as could not read a <results> element from the input");
                }
                if (context.Input.Name.Equals("results"))
                {
                    // Only parser <result> elements if it's not an empty <results /> element
                    if (!context.Input.IsEmptyElement)
                    {
                        while (context.Input.Read())
                        {
                            // Stop reading when we hit the </results>
                            if (context.Input.NodeType == XmlNodeType.EndElement && context.Input.Name.Equals("results"))
                            {
                                break;
                            }

                            // Must be a <result> element
                            if (!context.Input.Name.Equals("result"))
                            {
                                throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <results> element contains an unexpected element <" + context.Input.Name + ">!");
                            }

                            // Empty Elements generate an Empty Result
                            if (context.Input.IsEmptyElement)
                            {
                                if (!context.Handler.HandleResult(new SparqlResult()))
                                {
                                    ParserHelper.Stop();
                                }
                                continue;
                            }

                            // Get the values of each Binding
                            String       var;
                            INode        value;
                            SparqlResult result = new SparqlResult();
                            while (context.Input.Read())
                            {
                                // Stop reading when we hit the </binding>
                                if (context.Input.NodeType == XmlNodeType.EndElement && context.Input.Name.Equals("result"))
                                {
                                    break;
                                }

                                // Must be a <binding> element
                                if (!context.Input.Name.Equals("binding"))
                                {
                                    throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <result> element contains an unexpected element <" + context.Input.Name + ">!");
                                }

                                // Must have only 1 attribute
                                if (context.Input.AttributeCount != 1)
                                {
                                    throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <binding> element has too few/many attributes, only a 'name' attribute should be present!");
                                }

                                // Get the Variable this is a binding for and its Value
                                context.Input.MoveToNextAttribute();
                                var = context.Input.Value;
                                if (!context.Input.Read())
                                {
                                    throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of input when the contents of a <binding> element was expected");
                                }
                                value = ParseValue(context);

                                // Check that the Variable was defined in the Header
                                if (!context.Variables.Contains(var))
                                {
                                    throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <binding> element attempts to bind a value to the variable '" + var + "' which is not defined in the <head> by a <variable> element!");
                                }

                                // Set the Variable to the Value
                                result.SetValue(var, value);
                            }

                            // Check that all Variables are bound for a given result binding nulls where appropriate
                            foreach (String v in context.Variables)
                            {
                                if (!result.HasValue(v))
                                {
                                    result.SetValue(v, null);
                                }
                            }

                            if (!context.Input.Name.Equals("result"))
                            {
                                throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of the input before a closing </result> element was found");
                            }

                            // Add to results set
                            result.SetVariableOrdering(context.Variables);
                            if (!context.Handler.HandleResult(result))
                            {
                                ParserHelper.Stop();
                            }
                        }
                    }

                    if (!context.Input.Name.Equals("results"))
                    {
                        throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of the input before the closing </results> element was found");
                    }
                }
                else if (context.Input.Name.Equals("boolean"))
                {
                    // Can't be any <variable> elements
                    if (context.Variables.Count > 0)
                    {
                        throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <boolean> element is specified but the <head> contained one/more <variable> elements which is not permitted!");
                    }

                    try
                    {
                        // Get the value of the <boolean> element as a Boolean
                        Boolean b = Boolean.Parse(context.Input.ReadInnerXml());
                        context.Handler.HandleBooleanResult(b);
                    }
                    catch (Exception)
                    {
                        throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <boolean> element contained a value that could not be understood as a Boolean value!");
                    }
                }
                else
                {
                    throw new RdfParseException("Unable to Parse a SPARQL Result Set since the second Child Node of the <sparql> element is not the required <results> or <boolean> element!");
                }

                context.Handler.EndResults(true);
            }
            catch (RdfParsingTerminatedException)
            {
                context.Handler.EndResults(true);
            }
            catch
            {
                // Some other Error
                context.Handler.EndResults(false);
                throw;
            }
        }
示例#10
0
        /// <summary>
        /// Parser method which parses a Bound Variable Object which occurs within a Binding Object
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="var">Variable Name</param>
        /// <param name="r">Result Object that is being constructed from the Binding Object</param>
        /// <param name="headSeen"></param>
        private void ParseBoundVariable(SparqlJsonParserContext context, string var, SparqlResult r, bool headSeen)
        {
            String nodeType, nodeLang, nodeDatatype;
            string nodeValue = nodeType = nodeLang = nodeDatatype = null;

            //Can we read the start of an Object
            if (context.Input.Read())
            {
                if (context.Input.TokenType == JsonToken.StartObject)
                {
                    context.Input.Read();

                    while (context.Input.TokenType != JsonToken.EndObject)
                    {
                        String token = context.Input.Value.ToString().ToLower();

                        //Check that we get a Property Value as a String
                        context.Input.Read();
                        if (!IsValidValue(context))
                        {
                            throw Error(context, "Unexpected Token '" + context.Input.TokenType + "' with value '" + context.Input.Value + "' encountered, expected a Property Value describing one of the properties of an Variable Binding");
                        }

                        //Extract the Information from the Object
                        if (token.Equals("value"))
                        {
                            nodeValue = context.Input.Value.ToString();
                        }
                        else if (token.Equals("type"))
                        {
                            nodeType = context.Input.Value.ToString().ToLower();
                        }
                        else if (token.Equals("lang") || token.Equals("xml:lang"))
                        {
                            if (nodeLang == null && nodeDatatype == null)
                            {
                                nodeLang = context.Input.Value.ToString();
                            }
                            else
                            {
                                throw Error(context, "Unexpected Language Property specified for an Object Node where a Language or Datatype has already been specified");
                            }
                        }
                        else if (token.Equals("datatype"))
                        {
                            if (nodeDatatype == null && nodeLang == null)
                            {
                                nodeDatatype = context.Input.Value.ToString();
                            }
                            else
                            {
                                throw Error(context, "Unexpected Datatype Property specified for an Object Node where a Language or Datatype has already been specified");
                            }
                        }
                        else
                        {
                            throw Error(context, "Unexpected Property '" + token + "' specified for an Object Node, only 'value', 'type', 'lang' and 'datatype' are valid properties");
                        }

                        //Get Next Token
                        if (!context.Input.Read())
                        {
                            throw new RdfParseException("Unexpected End of Input while trying to parse a Bound Variable Object");
                        }
                    }

                    //Validate the Information
                    if (nodeType == null)
                    {
                        throw new RdfParseException("Cannot parse a Node from the JSON where no 'type' property was specified in the JSON Object representing the Node");
                    }
                    if (nodeValue == null)
                    {
                        throw new RdfParseException("Cannot parse a Node from the JSON where no 'value' property was specified in the JSON Object representing the Node");
                    }

                    //Turn this information into a Node
                    INode n;
                    if (nodeType.Equals("uri"))
                    {
                        n = ParserHelper.TryResolveUri(context, nodeValue);
                    }
                    else if (nodeType.Equals("bnode"))
                    {
                        if (nodeValue.StartsWith("_:"))
                        {
                            n = context.Handler.CreateBlankNode(nodeValue.Substring(2));
                        }
                        else if (nodeValue.Contains("://"))
                        {
                            n = context.Handler.CreateBlankNode(nodeValue.Substring(nodeValue.IndexOf("://", StringComparison.Ordinal) + 3));
                        }
                        else if (nodeValue.Contains(":"))
                        {
                            n = context.Handler.CreateBlankNode(nodeValue.Substring(nodeValue.LastIndexOf(':') + 1));
                        }
                        else
                        {
                            n = context.Handler.CreateBlankNode(nodeValue);
                        }
                    }
                    else if (nodeType.Equals("literal") || nodeType.Equals("typed-literal"))
                    {
                        if (nodeLang != null)
                        {
                            n = context.Handler.CreateLiteralNode(nodeValue, nodeLang);
                        }
                        else if (nodeDatatype != null)
                        {
                            Uri dtUri = ((IUriNode)ParserHelper.TryResolveUri(context, nodeDatatype)).Uri;
                            n = context.Handler.CreateLiteralNode(nodeValue, dtUri);
                        }
                        else
                        {
                            n = context.Handler.CreateLiteralNode(nodeValue);
                        }
                    }
                    else
                    {
                        throw new RdfParseException("Cannot parse a Node from the JSON where the 'type' property has a value of '" + nodeType + "' which is not one of the permitted values 'uri', 'bnode', 'literal' or 'typed-literal' in the JSON Object representing the Node");
                    }

                    //Check that the Variable was defined in the Header
                    if (!context.Variables.Contains(var))
                    {
                        if (headSeen)
                        {
                            throw new RdfParseException("Unable to Parse a SPARQL Result Set since a Binding Object attempts to bind a value to the variable '" + var + "' which is not defined in the Header Object in the value for the 'vars' property!");
                        }
                        context.Variables.Add(var);
                    }

                    //Add to the result
                    r.SetValue(var, n);
                }
                else
                {
                    throw Error(context, "Unexpected Token '" + context.Input.TokenType + "' with value '" + context.Input.Value + "' encountered, expected the start of a Bound Variable Object");
                }
            }
            else
            {
                throw Error(context, "Unexpected End of Input while trying to parse a Bound Variable Object");
            }
        }
示例#11
0
        /// <summary>
        /// Parses the XML Result Set format into a set of SPARQLResult objects
        /// </summary>
        /// <param name="context">Parser Context</param>
        private void Parse(SparqlXmlParserContext context)
        {
            try
            {
                context.Handler.StartResults();

                //Get the Document Element and check it's a Sparql element
                if (!context.Input.Read()) throw new RdfParseException("Unable to Parse a SPARQL Result Set as it was not possible to read a document element from the input");
                while (context.Input.NodeType != XmlNodeType.Element)
                {
                    if (!context.Input.Read()) throw new RdfParseException("Unable to Parse a SPARQL Result Set as it was not possible to read a document element from the input");
                }
                if (!context.Input.Name.Equals("sparql"))
                {
                    throw new RdfParseException("Unable to Parse a SPARQL Result Set from the provided XML since the Document Element is not a <sparql> element!");
                }

                //Go through it's attributes and check the Namespace is specified
                bool nsfound = false;
                if (context.Input.HasAttributes)
                {
                    for (int i = 0; i < context.Input.AttributeCount; i++)
                    {
                        context.Input.MoveToNextAttribute();
                        if (context.Input.Name.Equals("xmlns"))
                        {
                            if (!context.Input.Value.Equals(SparqlSpecsHelper.SparqlNamespace))
                            {
                                throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <sparql> element has an incorrect Namespace!");
                            }
                            else
                            {
                                nsfound = true;
                            }
                        }
                    }
                }
                if (!nsfound)
                {
                    throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <sparql> element fails to specify the SPARQL Namespace!");
                }

                //Get the Variables from the Header
                if (!context.Input.Read()) throw new RdfParseException("Unable to Parse a SPARQL Result Set as could not read a <head> element from the input");
                if (!context.Input.Name.Equals("head"))
                {
                    throw new RdfParseException("Unable to Parse a SPARQL Result Set since the first Child Node of the <sparql> element is not the required <head> element!");
                }

                //Only parser <variable> and <link> elements if not an empty <head /> element
                if (!context.Input.IsEmptyElement)
                {
                    while (context.Input.Read())
                    {
                        //Stop reading when we hit the </head>
                        if (context.Input.NodeType == XmlNodeType.EndElement && context.Input.Name.Equals("head")) break;

                        //Looking for <variable> elements
                        if (context.Input.Name.Equals("variable"))
                        {
                            //Should only have 1 attribute
                            if (context.Input.AttributeCount != 1)
                            {
                                throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <variable> element has too few/many attributes, only a 'name' attribute should be present!");
                            }
                            else
                            {
                                //Add the Variable to the list
                                context.Input.MoveToNextAttribute();
                                if (!context.Handler.HandleVariable(context.Input.Value)) ParserHelper.Stop();
                                context.Variables.Add(context.Input.Value);
                            }
                        }
                        else if (context.Input.Name.Equals("link"))
                        {
                            //Not bothered about <link> elements
                        }
                        else
                        {
                            //Some unexpected element
                            throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <head> contains an unexpected element <" + context.Input.Name + ">!");
                        }
                    }
                }

                if (!context.Input.Name.Equals("head"))
                {
                    throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of the input before the closing </head> element was found");
                }

                //Look at the <results> or <boolean> element
                if (!context.Input.Read()) throw new RdfParseException("Unable to Parse a SPARQL Result Set as could not read a <results> element from the input");
                if (context.Input.Name.Equals("results"))
                {
                    //Only parser <result> elements if it's not an empty <results /> element
                    if (!context.Input.IsEmptyElement)
                    {
                        while (context.Input.Read())
                        {
                            //Stop reading when we hit the </results>
                            if (context.Input.NodeType == XmlNodeType.EndElement && context.Input.Name.Equals("results")) break;

                            //Must be a <result> element
                            if (!context.Input.Name.Equals("result"))
                            {
                                throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <results> element contains an unexpected element <" + context.Input.Name + ">!");
                            }

                            //Empty Elements generate an Empty Result
                            if (context.Input.IsEmptyElement)
                            {
                                if (!context.Handler.HandleResult(new SparqlResult())) ParserHelper.Stop();
                                continue;
                            }

                            //Get the values of each Binding
                            String var;
                            INode value;
                            SparqlResult result = new SparqlResult();
                            while (context.Input.Read())
                            {
                                //Stop reading when we hit the </binding>
                                if (context.Input.NodeType == XmlNodeType.EndElement && context.Input.Name.Equals("result")) break;

                                //Must be a <binding> element
                                if (!context.Input.Name.Equals("binding"))
                                {
                                    throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <result> element contains an unexpected element <" + context.Input.Name + ">!");
                                }

                                //Must have only 1 attribute
                                if (context.Input.AttributeCount != 1)
                                {
                                    throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <binding> element has too few/many attributes, only a 'name' attribute should be present!");
                                }

                                //Get the Variable this is a binding for and its Value
                                context.Input.MoveToNextAttribute();
                                var = context.Input.Value;
                                if (!context.Input.Read()) throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of input when the contents of a <binding> element was expected");
                                value = this.ParseValue(context);

                                //Check that the Variable was defined in the Header
                                if (!context.Variables.Contains(var))
                                {
                                    throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <binding> element attempts to bind a value to the variable '" + var + "' which is not defined in the <head> by a <variable> element!");
                                }

                                //Set the Variable to the Value
                                result.SetValue(var, value);
                            }

                            //Check that all Variables are bound for a given result binding nulls where appropriate
                            foreach (String v in context.Variables)
                            {
                                if (!result.HasValue(v))
                                {
                                    result.SetValue(v, null);
                                }
                            }

                            if (!context.Input.Name.Equals("result"))
                            {
                                throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of the input before a closing </result> element was found");
                            }

                            //Add to results set
                            if (!context.Handler.HandleResult(result)) ParserHelper.Stop();
                        }
                    }

                    if (!context.Input.Name.Equals("results"))
                    {
                        throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of the input before the closing </results> element was found");
                    }
                }
                else if (context.Input.Name.Equals("boolean"))
                {
                    //Can't be any <variable> elements
                    if (context.Variables.Count > 0)
                    {
                        throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <boolean> element is specified but the <head> contained one/more <variable> elements which is not permitted!");
                    }

                    try
                    {
                        //Get the value of the <boolean> element as a Boolean
                        Boolean b = Boolean.Parse(context.Input.ReadInnerXml());
                        context.Handler.HandleBooleanResult(b);
                    }
                    catch (Exception)
                    {
                        throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <boolean> element contained a value that could not be understood as a Boolean value!");
                    }
                }
                else
                {
                    throw new RdfParseException("Unable to Parse a SPARQL Result Set since the second Child Node of the <sparql> element is not the required <results> or <boolean> element!");
                }

                context.Handler.EndResults(true);
            }
            catch (RdfParsingTerminatedException)
            {
                context.Handler.EndResults(true);
            }
            catch
            {
                //Some other Error
                context.Handler.EndResults(false);
                throw;
            }
        }
示例#12
0
        /// <summary>
        /// Internal method which actually parses the Result Set by traversing the RDF Graph appropriately
        /// </summary>
        /// <param name="context">Parser Context</param>
        private void Parse(SparqlRdfParserContext context)
        {
            try
            {
                context.Handler.StartResults();

                //Create relevant Nodes
                context.Graph.NamespaceMap.AddNamespace("rdf", new Uri(NamespaceMapper.RDF));
                context.Graph.NamespaceMap.AddNamespace("rs", new Uri(SparqlSpecsHelper.SparqlRdfResultsNamespace));
                IUriNode rdfType = context.Graph.CreateUriNode("rdf:type");
                IUriNode resultSetClass = context.Graph.CreateUriNode("rs:ResultSet");
                IUriNode resultVariable = context.Graph.CreateUriNode("rs:resultVariable");
                IUriNode solution = context.Graph.CreateUriNode("rs:solution");
                IUriNode binding = context.Graph.CreateUriNode("rs:binding");
                IUriNode value = context.Graph.CreateUriNode("rs:value");
                IUriNode variable = context.Graph.CreateUriNode("rs:variable");
                IUriNode boolean = context.Graph.CreateUriNode("rs:boolean");

                //Try to get a ResultSet object
                Triple rset = context.Graph.Triples.WithPredicateObject(rdfType, resultSetClass).FirstOrDefault();
                if (rset != null)
                {
                    INode rsetID = rset.Subject;

                    //Find the Variables the Result Set contains or the Boolean Value
                    List<Triple> temp = context.Graph.Triples.WithSubjectPredicate(rsetID, boolean).ToList();
                    if (temp.Count > 0)
                    {
                        if (temp.Count > 1) throw new RdfParseException("Result Set has more than one boolean result defined for it");

                        Triple booleanResult = temp.First();
                        INode result = booleanResult.Object;
                        if (result.NodeType == NodeType.Literal)
                        {
                            ILiteralNode lit = (ILiteralNode)result;
                            if (lit.DataType != null)
                            {
                                if (lit.DataType.ToString().Equals(XmlSpecsHelper.XmlSchemaDataTypeBoolean))
                                {
                                    bool b;
                                    if (Boolean.TryParse(lit.Value, out b))
                                    {
                                        context.Handler.HandleBooleanResult(b);
                                        return;
                                    }
                                    else
                                    {
                                        throw new RdfParseException("Result Set has a boolean result which is a Literal typed as boolean but which does not contain a valid boolean value");
                                    }
                                }
                                else
                                {
                                    throw new RdfParseException("Result Set has a boolean result which is a Literal which is not boolean typed");
                                }
                            }
                            else
                            {
                                throw new RdfParseException("Result Set has a boolean result which is a Literal which is not typed as a boolean");
                            }
                        }
                        else
                        {
                            throw new RdfParseException("Result Set has a boolean result which is not a Literal Node");
                        }
                    }
                    else
                    {
                        //We're expected one/more variables
                        temp = context.Graph.Triples.WithSubjectPredicate(rsetID, resultVariable).ToList();
                        if (temp.Count > 0)
                        {
                            foreach (Triple t in temp)
                            {
                                if (t.Object.NodeType == NodeType.Literal)
                                {
                                    if (!context.Handler.HandleVariable(((ILiteralNode)t.Object).Value)) ParserHelper.Stop();
                                    context.Variables.Add(((ILiteralNode)t.Object).Value);
                                }
                                else
                                {
                                    throw new RdfParseException("Result Set has a result variable definition which is not a Literal Node");
                                }
                            }
                        }
                        else
                        {
                            throw new RdfParseException("Result Set does not define any result variables or a boolean result");
                        }

                        //Then we're expecting some Solutions
                        temp = context.Graph.Triples.WithSubjectPredicate(rsetID, solution).ToList();
                        foreach (Triple slnTriple in temp)
                        {
                            //Each Solution has some Bindings
                            INode slnID = slnTriple.Object;
                            bool ok = false;
                            SparqlResult r = new SparqlResult();

                            foreach (Triple bindingTriple in context.Graph.Triples.WithSubjectPredicate(slnID, binding))
                            {
                                //Each Binding has a Variable and a Value
                                ok = true;
                                INode bindingID = bindingTriple.Object;
                                String var = String.Empty;
                                INode val = null;

                                //Retrieve the Variable and the Bound Value
                                foreach (Triple valueTriple in context.Graph.Triples.WithSubject(bindingID))
                                {
                                    if (valueTriple.Predicate.Equals(variable))
                                    {
                                        if (!var.Equals(String.Empty)) throw new RdfParseException("Result Set contains a Binding which refers to more than one Variable");
                                        if (valueTriple.Object.NodeType != NodeType.Literal) throw new RdfParseException("Result Set contains a Binding which refers to a Variable but not by a Literal Node as required");
                                        var = ((ILiteralNode)valueTriple.Object).Value;
                                    }
                                    else if (valueTriple.Predicate.Equals(value))
                                    {
                                        if (val != null) throw new RdfParseException("Result Set contains a Binding which has more than one Value");
                                        val = valueTriple.Object;
                                    }
                                }
                                if (var.Equals(String.Empty) || val == null) throw new RdfParseException("Result Set contains a Binding which doesn't contain both a Variable and a Value");

                                //Check that the Variable was defined in the Header
                                if (!context.Variables.Contains(var))
                                {
                                    throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <binding> element attempts to bind a value to the variable '" + var + "' which is not defined in the <head> by a <variable> element!");
                                }

                                r.SetValue(var, val);
                            }
                            if (!ok) throw new RdfParseException("Result Set contains a Solution which has no Bindings");

                            //Check that all Variables are bound for a given result binding nulls where appropriate
                            foreach (String v in context.Variables)
                            {
                                if (!r.HasValue(v))
                                {
                                    r.SetValue(v, null);
                                }
                            }

                            if (!context.Handler.HandleResult(r)) ParserHelper.Stop();
                        }
                    }
                }
                else
                {
                    throw new RdfParseException("No Result Set object is defined in the Graph");
                }

                context.Handler.EndResults(true);
            }
            catch (RdfParsingTerminatedException)
            {
                context.Handler.EndResults(true);
            }
            catch
            {
                context.Handler.EndResults(false);
                throw;
            }
        }
示例#13
0
        /// <summary>
        /// Executes a SPARQL Query on the native Quad Store
        /// </summary>
        /// <param name="sparqlQuery">SPARQL Query to execute</param>
        /// <returns></returns>
        /// <remarks>
        /// <para>
        /// This method will first attempt to parse the query into a <see cref="SparqlQuery">SparqlQuery</see> object.  If this succeeds then the Query Type can be used to determine how to handle the response.
        /// </para>
        /// <para>
        /// If the parsing fails then the query will be executed anyway using Virtuoso's SPASQL (SPARQL + SQL) syntax.  Parsing can fail because Virtuoso supports various SPARQL extensions which the library does not support.  These include things like aggregate functions but also SPARQL Update statements.
        /// </para>
        /// <para>
        /// If you use an aggregate query which has an Integer, Decimal or Double type result then you will receive a <see cref="SparqlResultSet">SparqlResultSet</see> containing a single <see cref="SparqlResult">SparqlResult</see> which has contains a binding for a variable named <strong>Result</strong> which contains a <see cref="LiteralNode">LiteralNode</see> typed to the appropriate datatype.
        /// </para>
        /// </remarks>
        /// <exception cref="RdfQueryException">Thrown if an error occurs in making the query</exception>
        public Object Query(String sparqlQuery)
        {
            Object finalResult = null;
            DataTable results = new DataTable();
            results.Columns.CollectionChanged += new System.ComponentModel.CollectionChangeEventHandler(Columns_CollectionChanged);

            //See if the query can be parsed into a SparqlQuery object
            //It might not since the user might use Virtuoso's extensions to Sparql in their query
            try
            {
                //We'll set the Parser to SPARQL 1.1 mode even though Virtuoso's SPARQL implementation has
                //various perculiarties in their SPARQL 1.1 implementation and we'll try and 
                //handle the potential results in the catch branch if a valid SPARQL 1.0 query
                //cannot be parsed
                //Change made in response to a bug report by Aleksandr A. Zaripov [[email protected]]
                SparqlQueryParser parser = new SparqlQueryParser();
                parser.SyntaxMode = SparqlQuerySyntax.Sparql_1_1;
                SparqlQuery query = parser.ParseFromString(sparqlQuery);

                switch (query.QueryType)
                {
                    case SparqlQueryType.Select:
                    case SparqlQueryType.SelectAll:
                    case SparqlQueryType.SelectAllDistinct:
                    case SparqlQueryType.SelectAllReduced:
                    case SparqlQueryType.SelectDistinct:
                    case SparqlQueryType.SelectReduced:
                        //Type the Tables columns as System.Object
                        foreach (SparqlVariable var in query.Variables)
                        {
                            if (var.IsResultVariable)
                            {
                                results.Columns.Add(var.Name, typeof(System.Object));
                            }
                        }
                        break;
                }

                try 
                {
                    this.Open(false);

                    //Make the Query against Virtuoso
                    VirtuosoCommand cmd = this._db.CreateCommand();
                    cmd.CommandText = "SPARQL " + sparqlQuery;
                    VirtuosoDataAdapter adapter = new VirtuosoDataAdapter(cmd);
                    adapter.Fill(results);

                    //Decide how to process the results based on the return type
                    switch (query.QueryType)
                    {
                        case SparqlQueryType.Ask:
                            //Expect a DataTable containing a single row and column which contains a boolean

                            if (results.Rows.Count == 1 && results.Columns.Count == 1)
                            {
                                bool result;
                                int r;
                                if (Boolean.TryParse(results.Rows[0][0].ToString(), out result))
                                {
                                    finalResult = new SparqlResultSet(result);
                                }
                                else if (Int32.TryParse(results.Rows[0][0].ToString(), out r))
                                {
                                    if (r == 1)
                                    {
                                        finalResult = new SparqlResultSet(true);
                                    }
                                    else
                                    {
                                        finalResult = new SparqlResultSet(false);
                                    }
                                }
                                else
                                {
                                    throw new RdfQueryException("Expected a Boolean as the result of an ASK query but the non-boolean value '" + results.Rows[0][0].ToString() + "' was received");
                                }
                            }
                            else
                            {
                                //If we get anything else then we'll return that the result was False
                                finalResult = new SparqlResultSet(false);
                            }

                            break;
                        case SparqlQueryType.Construct:
                        case SparqlQueryType.Describe:
                        case SparqlQueryType.DescribeAll:
                            //Expect a DataTable containing a single row and column which contains a String
                            //That string will be a Turtle serialization of the Graph

                            if (results.Rows.Count == 1 && results.Columns.Count == 1)
                            {
                                try
                                {
                                    //Use StringParser to parse
                                    String data = results.Rows[0][0].ToString();
                                    TurtleParser ttlparser = new TurtleParser();
                                    Graph g = new Graph();
                                    StringParser.Parse(g, data, ttlparser);

                                    finalResult = g;
                                }
                                catch (RdfParseException parseEx)
                                {
                                    throw new RdfQueryException("Expected a valid Turtle serialization of the Graph resulting from a CONSTRUCT/DESCRIBE query but the result failed to parse", parseEx);
                                }
                            }
                            else
                            {
                                throw new RdfQueryException("Expected a single string value representing the serialization of the Graph resulting from a CONSTRUCT/DESCRIBE query but this was not received");
                            }

                            break;
                        case SparqlQueryType.Select:
                        case SparqlQueryType.SelectAll:
                        case SparqlQueryType.SelectAllDistinct:
                        case SparqlQueryType.SelectAllReduced:
                        case SparqlQueryType.SelectDistinct:
                        case SparqlQueryType.SelectReduced:
                            //Expect a DataTable containing columns for each Result Variable and a row for each solution
                            SparqlResultSet rset = new SparqlResultSet();
                            rset.SetResult(true);

                            //Get Result Variables
                            List<SparqlVariable> resultVars = query.Variables.Where(v => v.IsResultVariable).ToList();
                            foreach (SparqlVariable var in resultVars)
                            {
                                rset.AddVariable(var.Name);
                            }
                            Graph temp = new Graph();

                            //Convert each solution into a SPARQLResult
                            foreach (DataRow r in results.Rows)
                            {
                                SparqlResult result = new SparqlResult();
                                foreach (SparqlVariable var in resultVars)
                                {
                                    if (r[var.Name] != null)
                                    {
                                        result.SetValue(var.Name, this.LoadNode(temp, r[var.Name]));
                                    }
                                }
                                rset.AddResult(result);
                            }

                            finalResult = rset;

                            break;
                        default:
                            throw new RdfQueryException("Unable to process the Results of an Unknown query type");
                    }

                    this.Close(false);
                } 
                catch
                {
                    this.Close(true, true);
                    throw;
                }
            }
            catch (RdfParseException)
            {
                //Unable to parse a SPARQL 1.0 query
                //Have to attempt to detect the return type based on the DataTable that
                //the SPASQL (Sparql+SQL) query gives back

                //Make the Query against Virtuoso
                VirtuosoCommand cmd = this._db.CreateCommand();
                cmd.CommandText = "SPARQL " /*define output:format '_JAVA_' "*/ + sparqlQuery;
                VirtuosoDataAdapter adapter = new VirtuosoDataAdapter(cmd);
                adapter.Fill(results);

                //Try to detect the return type based on the DataTable configuration
                if (results.Rows.Count == 0 && results.Columns.Count > 0)
                {
                    //No Rows but some columns implies empty SELECT results
                    SparqlResultSet rset = new SparqlResultSet();
                    foreach (DataColumn col in results.Columns)
                    {
                        rset.AddVariable(col.ColumnName);
                    }

                    finalResult = rset;
                }
                else if (results.Rows.Count == 1 && results.Columns.Count == 1 && !Regex.IsMatch(sparqlQuery, "SELECT", RegexOptions.IgnoreCase))
                {
                    //Added a fix here suggested by Alexander Sidorov - not entirely happy with this fix as what happens if SELECT just happens to occur in a URI/Variable Name?

                    //Single Row and Column implies ASK/DESCRIBE/CONSTRUCT results
                    bool result;
                    int r;
                    decimal rdec;
                    double rdbl;
                    float rflt;

                    if (results.Rows[0][0].ToString().Equals(String.Empty))
                    {
                        //Empty Results
                        finalResult = new SparqlResultSet();
                    }
                    else if (Boolean.TryParse(results.Rows[0][0].ToString(), out result))
                    {
                        //Parseable Boolean so ASK Results
                        finalResult = new SparqlResultSet(result);
                    }
                    else if (Int32.TryParse(results.Rows[0][0].ToString(), out r))
                    {
                        //Parseable Integer so Aggregate SELECT Query Results
                        SparqlResultSet rset = new SparqlResultSet();
                        rset.AddVariable("Result");
                        SparqlResult res = new SparqlResult();
                        res.SetValue("Result", new LiteralNode(null, r.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger)));
                        rset.AddResult(res);

                        finalResult = rset;
                    }
                    else if (Single.TryParse(results.Rows[0][0].ToString(), out rflt))
                    {
                        //Parseable Single so Aggregate SELECT Query Results
                        SparqlResultSet rset = new SparqlResultSet();
                        rset.AddVariable("Result");
                        SparqlResult res = new SparqlResult();
                        res.SetValue("Result", new LiteralNode(null, rflt.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeFloat)));
                        rset.AddResult(res);

                        finalResult = rset;
                    }
                    else if (Double.TryParse(results.Rows[0][0].ToString(), out rdbl))
                    {
                        //Parseable Double so Aggregate SELECT Query Results
                        SparqlResultSet rset = new SparqlResultSet();
                        rset.AddVariable("Result");
                        SparqlResult res = new SparqlResult();
                        res.SetValue("Result", new LiteralNode(null, rdbl.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDouble)));
                        rset.AddResult(res);

                        finalResult = rset;
                    }
                    else if (Decimal.TryParse(results.Rows[0][0].ToString(), out rdec))
                    {
                        //Parseable Decimal so Aggregate SELECT Query Results
                        SparqlResultSet rset = new SparqlResultSet();
                        rset.AddVariable("Result");
                        SparqlResult res = new SparqlResult();
                        res.SetValue("Result", new LiteralNode(null, rdec.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDecimal)));
                        rset.AddResult(res);

                        finalResult = rset;
                    }
                    else
                    {
                        //String so try and parse as Turtle
                        try
                        {
                            //Use StringParser to parse
                            String data = results.Rows[0][0].ToString();
                            TurtleParser ttlparser = new TurtleParser();
                            Graph g = new Graph();
                            StringParser.Parse(g, data, ttlparser);

                            finalResult = g;
                        }
                        catch (RdfParseException)
                        {
                            //If it failed to parse then it might be the result of one of the aggregate
                            //functions that Virtuoso extends Sparql with
                            Graph temp = new Graph();
                            SparqlResultSet rset = new SparqlResultSet();
                            rset.AddVariable(results.Columns[0].ColumnName);
                            SparqlResult res = new SparqlResult();
                            res.SetValue(results.Columns[0].ColumnName, this.LoadNode(temp, results.Rows[0][0]));
                            //Nothing was returned here previously - fix submitted by Aleksandr A. Zaripov [[email protected]]
                            rset.AddResult(res);
                            finalResult = rset;
                        }
                    }
                }
                else
                {
                    //Any other number of rows/columns we have to assume that it's normal SELECT results
                    //Changed in response to bug report by Aleksandr A. Zaripov [[email protected]]

                    //SELECT Query Results
                    SparqlResultSet rset = new SparqlResultSet();
                    rset.SetResult(true);

                    //Get Result Variables
                    foreach (DataColumn col in results.Columns)
                    {
                        rset.AddVariable(col.ColumnName);
                    }
                    Graph temp = new Graph();

                    //Convert each solution into a SPARQLResult
                    foreach (DataRow r in results.Rows)
                    {
                        SparqlResult result = new SparqlResult();
                        foreach (String var in rset.Variables)
                        {
                            if (r[var] != null)
                            {
                                result.SetValue(var, this.LoadNode(temp, r[var]));
                            }
                        }
                        rset.AddResult(result);
                    }

                    finalResult = rset;
                }
            }

            return finalResult;
        }