/// <summary>
        /// Processes requests made to the Graph Store HTTP Protocol endpoint and invokes the appropriate methods on the Protocol Processor that is in use
        /// </summary>
        /// <param name="context">HTTP Context</param>
        /// <remarks>
        /// <para>
        /// Implementations may override this if necessary - if the implementation is only providing additional logic such as authentication, ACLs etc. then it is recommended that the override applies its logic and then calls the base method since this base method will handle much of the error handling and sending of appropriate HTTP Response Codes.
        /// </para>
        /// </remarks>
        public virtual void ProcessRequest(HttpContext context)
        {
            this._config = this.LoadConfig(context, out this._basePath);

            //Add our Standard Headers
            HandlerHelper.AddStandardHeaders(context, this._config);

            if (context.Request.HttpMethod.Equals("OPTIONS"))
            {
                //OPTIONS requests always result in the Service Description document
                IGraph svcDescrip = SparqlServiceDescriber.GetServiceDescription(context, this._config, new Uri(new Uri(context.Request.Url.AbsoluteUri), this._basePath));
                HandlerHelper.SendToClient(context, svcDescrip, this._config);
                return;
            }

            //Check whether we need to use authentication
            if (!HandlerHelper.IsAuthenticated(context, this._config.UserGroups, context.Request.HttpMethod)) return;

            try
            {
                //Invoke the appropriate method on our protocol processor
                switch (context.Request.HttpMethod)
                {
                    case "GET":
                        this._config.Processor.ProcessGet(context);
                        break;
                    case "PUT":
                        this._config.Processor.ProcessPut(context);
                        break;
                    case "POST":
                        Uri serviceUri = new Uri(new Uri(context.Request.Url.AbsoluteUri), this._basePath);
                        if (context.Request.Url.AbsoluteUri.Equals(serviceUri.ToString()))
                        {
                            //If there is a ?graph parameter or ?default parameter then this is a normal Post
                            //Otherwise it is a PostCreate
                            if (context.Request.QueryString["graph"] != null)
                            {
                                this._config.Processor.ProcessPost(context);
                            }
                            else if (context.Request.QueryString.AllKeys.Contains("default") || Regex.IsMatch(context.Request.QueryString.ToString(), BaseProtocolProcessor.DefaultParameterPattern))
                            {
                                this._config.Processor.ProcessPost(context);
                            }
                            else
                            {
                                this._config.Processor.ProcessPostCreate(context);
                            }
                        }
                        else
                        {
                            this._config.Processor.ProcessPost(context);
                        }
                        break;
                    case "DELETE":
                        this._config.Processor.ProcessDelete(context);
                        break;
                    case "HEAD":
                        this._config.Processor.ProcessHead(context);
                        break;
                    case "PATCH":
                        this._config.Processor.ProcessPatch(context);
                        break;
                    default:
                        //For any other HTTP Verb we send a 405 Method Not Allowed
                        context.Response.StatusCode = (int)HttpStatusCode.MethodNotAllowed;
                        break;
                }

                //Update the Cache as the request may have changed the endpoint
                this.UpdateConfig(context);
            }
            catch (SparqlHttpProtocolUriResolutionException)
            {
                //If URI Resolution fails we send a 400 Bad Request
                context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
            }
            catch (SparqlHttpProtocolUriInvalidException)
            {
                //If URI is invalid we send a 400 Bad Request
                context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
            }
            catch (NotSupportedException)
            {
                //If Not Supported we send a 405 Method Not Allowed
                context.Response.StatusCode = (int)HttpStatusCode.MethodNotAllowed;
            }
            catch (NotImplementedException)
            {
                //If Not Implemented we send a 501 Not Implemented
                context.Response.StatusCode = (int)HttpStatusCode.NotImplemented;
            }
            catch (RdfWriterSelectionException)
            {
                //If we can't select a valid Writer when returning content we send a 406 Not Acceptable
                context.Response.StatusCode = (int)HttpStatusCode.NotAcceptable;
            }
            catch (RdfParserSelectionException)
            {
                //If we can't select a valid Parser when receiving content we send a 415 Unsupported Media Type
                context.Response.StatusCode = (int)HttpStatusCode.UnsupportedMediaType;
            }
            catch (RdfParseException)
            {
                //If we can't parse the received content successfully we send a 400 Bad Request
                context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
            }
            catch (Exception)
            {
                //For any other error we'll send a 500 Internal Server Error
                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            }
        }
        /// <summary>
        /// Generates a SPARQL Service Description Graph for the given Protocol Handler Configuration or uses the configuration supplied Description Graph
        /// </summary>
        /// <param name="context">HTTP Context</param>
        /// <param name="config">Protocol Handler Configuration</param>
        /// <param name="descripUri">Base URI of the Description</param>
        /// <returns></returns>
        public static IGraph GetServiceDescription(HttpContext context, BaseProtocolHandlerConfiguration config, Uri descripUri)
        {
            //Use user specified Service Description if present
            if (config.ServiceDescription != null) return config.ServiceDescription;

            IGraph g = SparqlServiceDescriber.GetNewGraph();

            //Add the Top Level Node representing the Service
            IUriNode descrip = g.CreateUriNode(descripUri);
            IUriNode rdfType = g.CreateUriNode(new Uri(RdfSpecsHelper.RdfType));
            IUriNode service = g.CreateUriNode("sd:" + ClassService);
            g.Assert(descrip, rdfType, service);

            //Add its sd:url
            IUriNode url = g.CreateUriNode("sd:" + PropertyUrl);
            g.Assert(descrip, url, descrip);

            //Add the Input Formats
            IUriNode inputFormat = g.CreateUriNode("sd:" + PropertyInputFormat);
            foreach (MimeTypeDefinition definition in MimeTypesHelper.Definitions)
            {
                if (definition.CanParseRdf)
                {
                    if (definition.FormatUri != null)
                    {
                        g.Assert(descrip, inputFormat, g.CreateUriNode(new Uri(definition.FormatUri)));
                    }
                }
            }

            //Add the Result Formats
            IUriNode resultFormat = g.CreateUriNode("sd:" + PropertyResultFormat);
            foreach (MimeTypeDefinition definition in MimeTypesHelper.Definitions)
            {
                if (definition.CanWriteRdf)
                {
                    if (definition.FormatUri != null)
                    {
                        g.Assert(descrip, resultFormat, g.CreateUriNode(new Uri(definition.FormatUri)));
                    }
                }
            }

            config.AddFeatureDescription(g, descrip);

            return g;
        }