예제 #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ODataPath" /> class.
        /// </summary>
        /// <param name="segments">The path segments for the path.</param>
        public ODataPath(IEnumerable <Semantic.ODataPathSegment> segments)
        {
            if (segments == null)
            {
                throw Error.ArgumentNull("segments");
            }

            var oDataPathSegments = segments as IList <Semantic.ODataPathSegment> ?? segments.ToList();

            _edmType = oDataPathSegments.Any() ? oDataPathSegments.Last().EdmType : null;

            _segments = new ReadOnlyCollection <Semantic.ODataPathSegment>(oDataPathSegments);

            ODataPathSegmentHandler handler = new ODataPathSegmentHandler();

            foreach (var segment in oDataPathSegments)
            {
                UnresolvedPathSegment pathSegment = segment as UnresolvedPathSegment;
                if (pathSegment != null)
                {
                    handler.Handle(pathSegment);
                }
                else
                {
                    segment.HandleWith(handler);
                }
            }

            _navigationSource = handler.NavigationSource;
            PathTemplate      = handler.PathTemplate;
            _pathLiteral      = handler.PathLiteral;
        }
예제 #2
0
        /// <summary>
        /// Handle a UnresolvedPathSegment
        /// </summary>
        /// <param name="segment">the segment to handle</param>
        public virtual void Handle(UnresolvedPathSegment segment)
        {
            // ODL doesn't provide the handle function for unresolved path segment
            _navigationSource = null;

            _pathTemplate.Add(ODataSegmentKinds.Unresolved); // unresolved
            _pathUriLiteral.Add(segment.SegmentValue);
        }
        public static string ToUriLiteral(this UnresolvedPathSegment segment)
        {
            if (segment == null)
            {
                throw Error.ArgumentNull("segment");
            }

            return(segment.SegmentValue);
        }
예제 #4
0
        /// <summary>
        /// Translates an ODL path to Web API path.
        /// </summary>
        /// <param name="path">The ODL path to be translated.</param>
        /// <param name="model">The model used to translate.</param>
        /// <param name="unresolvedPathSegment">Unresolved path segment.</param>
        /// <param name="id">The key segment from $id.</param>
        /// <param name="enableUriTemplateParsing">Specifies the ODL path is template or not.</param>
        /// <param name="parameterAliasNodes">The parameter alias nodes info.</param>
        /// <returns>The translated Web API path.</returns>
        public static ODataPath TranslateODLPathToWebAPIPath(
            Semantic.ODataPath path,
            IEdmModel model,
            UnresolvedPathSegment unresolvedPathSegment,
            Semantic.KeySegment id,
            bool enableUriTemplateParsing,
            IDictionary <string, Semantic.SingleValueNode> parameterAliasNodes)
        {
            if (path == null)
            {
                throw Error.ArgumentNull("path");
            }
            if (model == null)
            {
                throw Error.ArgumentNull("model");
            }
            if (parameterAliasNodes == null)
            {
                throw Error.ArgumentNull("parameterAliasNodes");
            }

            IList <ODataPathSegment> segments = path.WalkWith(
                new ODataPathSegmentTranslator(model, enableUriTemplateParsing, parameterAliasNodes))
                                                .SelectMany(s => s).ToList();

            if (unresolvedPathSegment != null)
            {
                segments.Add(unresolvedPathSegment);
            }

            if (!enableUriTemplateParsing)
            {
                AppendIdForRef(segments, id);
            }

            ReverseRefPathSegmentAndKeyValuePathSegment(segments);
            ODataPath odataPath = new ODataPath(segments);

            odataPath.ODLPath = path;

            return(odataPath);
        }
예제 #5
0
        private static ODataPathTemplate Templatify(ODataPath path, string pathTemplate)
        {
            if (path == null)
            {
                throw new ODataException(Error.Format(SRResources.InvalidODataPathTemplate, pathTemplate));
            }

            ODataPathSegmentTemplateTranslator translator = new ODataPathSegmentTemplateTranslator();
            var newPath = path.Segments.Select(e =>
            {
                UnresolvedPathSegment unresolvedPathSegment = e as UnresolvedPathSegment;
                if (unresolvedPathSegment != null)
                {
                    throw new ODataException(
                        Error.Format(SRResources.UnresolvedPathSegmentInTemplate, unresolvedPathSegment, pathTemplate));
                }

                return(e.TranslateWith(translator));
            });

            return(new ODataPathTemplate(newPath));
        }
예제 #6
0
        /// <summary>
        /// Parse the odata path.
        /// </summary>
        /// <param name="model">The model to use for path parsing.</param>
        /// <param name="serviceRoot">The service root of the OData path.</param>
        /// <param name="odataPath">The OData path to parse.</param>
        /// <param name="template">The flag indicates whether the path is template or not.</param>
        /// <param name="serviceProvider">The service proivder.</param>
        /// <param name="httpContext"></param>
        /// <param name="resolverSettings"></param>
        /// <returns>A parsed representation of the path, or <c>null</c> if the path does not match the model.</returns>
        public static ODataPath Parse(IEdmModel model, string serviceRoot, string odataPath, bool template, IServiceProvider serviceProvider, ODataUriResolverSettings resolverSettings)
        {
            ODL.ODataUriParser uriParser;
            Uri serviceRootUri = null;
            Uri fullUri        = null;
            // TODO: Replace this type.
            //NameValueCollection queryString = null;

            ODataOptions options = serviceProvider.GetRequiredService <IOptions <ODataOptions> >().Value;

            if (template)
            {
                uriParser = new ODL.ODataUriParser(model, new Uri(odataPath, UriKind.Relative), serviceProvider);
                uriParser.EnableUriTemplateParsing = true;
            }
            else
            {
                Contract.Assert(serviceRoot != null);

                serviceRootUri = new Uri(
                    serviceRoot.EndsWith("/", StringComparison.Ordinal) ?
                    serviceRoot :
                    serviceRoot + "/");

                fullUri = new Uri(serviceRootUri, odataPath);
                //queryString = fullUri.ParseQueryString();
                uriParser = new ODL.ODataUriParser(model, serviceRootUri, fullUri, serviceProvider);
            }

            uriParser.Resolver = resolverSettings.CreateResolver();

            if (options.UrlKeyDelimiter != null)
            {
                uriParser.UrlKeyDelimiter = options.UrlKeyDelimiter;
            }
            else
            {
                // ODL changes to use ODataUrlKeyDelimiter.Slash as default value.
                // Web API still uses the ODataUrlKeyDelimiter.Parentheses as default value.
                // Please remove it after fix: https://github.com/OData/odata.net/issues/642
                uriParser.UrlKeyDelimiter = ODataUrlKeyDelimiter.Parentheses;
            }

            ODL.ODataPath         path;
            UnresolvedPathSegment unresolvedPathSegment = null;

            ODL.KeySegment id = null;
            try
            {
                path = uriParser.ParsePath();
            }
            catch (ODL.ODataUnrecognizedPathException ex)
            {
                if (ex.ParsedSegments != null &&
                    ex.ParsedSegments.Any() &&
                    (ex.ParsedSegments.Last().EdmType is IEdmComplexType ||
                     ex.ParsedSegments.Last().EdmType is IEdmEntityType) &&
                    ex.CurrentSegment != ODataSegmentKinds.Count)
                {
                    if (!ex.UnparsedSegments.Any())
                    {
                        path = new ODL.ODataPath(ex.ParsedSegments);
                        unresolvedPathSegment = new UnresolvedPathSegment(ex.CurrentSegment);
                    }
                    else
                    {
                        // Throw ODataException if there is some segment following the unresolved segment.
                        throw new ODataException(Error.Format(
                                                     SRResources.InvalidPathSegment,
                                                     ex.UnparsedSegments.First(),
                                                     ex.CurrentSegment));
                    }
                }
                else
                {
                    throw;
                }
            }

            if (!template && path.LastSegment is ODL.NavigationPropertyLinkSegment)
            {
                IEdmCollectionType lastSegmentEdmType = path.LastSegment.EdmType as IEdmCollectionType;

                if (lastSegmentEdmType != null)
                {
                    ODL.EntityIdSegment entityIdSegment = null;
                    bool exceptionThrown = false;

                    try
                    {
                        entityIdSegment = uriParser.ParseEntityId();

                        if (entityIdSegment != null)
                        {
                            // Create another ODataUriParser to parse $id, which is absolute or relative.
                            ODL.ODataUriParser parser = new ODL.ODataUriParser(model, serviceRootUri, entityIdSegment.Id);
                            id = parser.ParsePath().LastSegment as ODL.KeySegment;
                        }
                    }
                    catch (ODataException)
                    {
                        // Exception was thrown while parsing the $id.
                        // We will throw another exception about the invalid $id.
                        exceptionThrown = true;
                    }

                    if (exceptionThrown ||
                        (entityIdSegment != null &&
                         (id == null ||
                          !(id.EdmType.IsOrInheritsFrom(lastSegmentEdmType.ElementType.Definition) ||
                            lastSegmentEdmType.ElementType.Definition.IsOrInheritsFrom(id.EdmType)))))
                    {
                        throw new ODataException(Error.Format(SRResources.InvalidDollarId, "$id" /*queryString.Get("$id")*/));
                    }
                }
            }

            // do validation for the odata path
            path.WalkWith(new DefaultODataPathValidator(model));

            // do segment translator (for example parameter alias, key & function parameter template, etc)
            var segments =
                ODataPathSegmentTranslator.Translate(model, path, uriParser.ParameterAliasNodes).ToList();

            if (unresolvedPathSegment != null)
            {
                segments.Add(unresolvedPathSegment);
            }

            if (!template)
            {
                AppendIdForRef(segments, id);
            }

            return(new ODataPath(segments)
            {
                ODLPath = path
            });
        }
 /// <summary>
 /// Handle a UnresolvedPathSegment
 /// </summary>
 /// <param name="segment">the segment to handle</param>
 public virtual void Handle(UnresolvedPathSegment segment)
 {
 }
예제 #8
0
        private static ODataPath Parse(
            IEdmModel model,
            string serviceRoot,
            string odataPath,
            ODataUriResolverSetttings resolverSettings,
            bool enableUriTemplateParsing)
        {
            ODataUriParser uriParser;
            Uri serviceRootUri = null;
            Uri fullUri = null;
            // TODO: Replace this type.
            //NameValueCollection queryString = null;

            if (enableUriTemplateParsing)
            {
                uriParser = new ODataUriParser(model, new Uri(odataPath, UriKind.Relative));
                uriParser.EnableUriTemplateParsing = true;
            }
            else
            {
                Contract.Assert(serviceRoot != null);

                serviceRootUri = new Uri(
                    serviceRoot.EndsWith("/", StringComparison.Ordinal) ?
                        serviceRoot :
                        serviceRoot + "/");

                fullUri = new Uri(serviceRootUri, odataPath);
                //queryString = fullUri.ParseQueryString();
                uriParser = new ODataUriParser(model, serviceRootUri, fullUri);
            }

            uriParser.Resolver = resolverSettings.CreateResolver();

            Semantic.ODataPath path;
            UnresolvedPathSegment unresolvedPathSegment = null;
            Semantic.KeySegment id = null;
            try
            {
                path = uriParser.ParsePath();
            }
            catch (ODataUnrecognizedPathException ex)
            {
                if (ex.ParsedSegments != null &&
                    ex.ParsedSegments.Count() > 0 &&
                    (ex.ParsedSegments.Last().EdmType is IEdmComplexType ||
                     ex.ParsedSegments.Last().EdmType is IEdmEntityType) &&
                    ex.CurrentSegment != ODataSegmentKinds.Count)
                {
                    if (ex.UnparsedSegments.Count() == 0)
                    {
                        path = new Semantic.ODataPath(ex.ParsedSegments);
                        unresolvedPathSegment = new UnresolvedPathSegment(ex.CurrentSegment);
                    }
                    else
                    {
                        // Throw ODataException if there is some segment following the unresolved segment.
                        throw new ODataException(Error.Format(
                            SRResources.InvalidPathSegment,
                            ex.UnparsedSegments.First(),
                            ex.CurrentSegment));
                    }
                }
                else
                {
                    throw;
                }
            }

            if (!enableUriTemplateParsing && path.LastSegment is Semantic.NavigationPropertyLinkSegment)
            {
                IEdmCollectionType lastSegmentEdmType = path.LastSegment.EdmType as IEdmCollectionType;

                if (lastSegmentEdmType != null)
                {
                    Semantic.EntityIdSegment entityIdSegment = null;
                    bool exceptionThrown = false;

                    try
                    {
                        entityIdSegment = uriParser.ParseEntityId();

                        if (entityIdSegment != null)
                        {
                            // Create another ODataUriParser to parse $id, which is absolute or relative.
                            ODataUriParser parser = new ODataUriParser(model, serviceRootUri, entityIdSegment.Id);
                            id = parser.ParsePath().LastSegment as Semantic.KeySegment;
                        }
                    }
                    catch (ODataException)
                    {
                        // Exception was thrown while parsing the $id.
                        // We will throw another exception about the invalid $id.
                        exceptionThrown = true;
                    }

                    if (exceptionThrown ||
                        (entityIdSegment != null &&
                            (id == null ||
                                !(id.EdmType.IsOrInheritsFrom(lastSegmentEdmType.ElementType.Definition) ||
                                  lastSegmentEdmType.ElementType.Definition.IsOrInheritsFrom(id.EdmType)))))
                    {
                        throw new ODataException(Error.Format(SRResources.InvalidDollarId, /*queryString.Get("$id")*/"$id"));
                    }
                }
            }

            ODataPath webAPIPath = ODataPathSegmentTranslator.TranslateODLPathToWebAPIPath(
                path,
                model,
                unresolvedPathSegment,
                id,
                enableUriTemplateParsing,
                uriParser.ParameterAliasNodes);

            CheckNavigableProperty(webAPIPath, model);
            return webAPIPath;
        }
예제 #9
0
        private static ODataPath Parse(
            IEdmModel model,
            string serviceRoot,
            string odataPath,
            ODataUriResolverSetttings resolverSettings,
            bool enableUriTemplateParsing)
        {
            ODataUriParser uriParser;
            Uri            serviceRootUri = null;
            Uri            fullUri        = null;

            // TODO: Replace this type.
            //NameValueCollection queryString = null;

            if (enableUriTemplateParsing)
            {
                uriParser = new ODataUriParser(model, new Uri(odataPath, UriKind.Relative));
                uriParser.EnableUriTemplateParsing = true;
            }
            else
            {
                Contract.Assert(serviceRoot != null);

                serviceRootUri = new Uri(
                    serviceRoot.EndsWith("/", StringComparison.Ordinal) ?
                    serviceRoot :
                    serviceRoot + "/");

                fullUri = new Uri(serviceRootUri, odataPath);
                //queryString = fullUri.ParseQueryString();
                uriParser = new ODataUriParser(model, serviceRootUri, fullUri);
            }

            uriParser.Resolver = resolverSettings.CreateResolver();

            Semantic.ODataPath    path;
            UnresolvedPathSegment unresolvedPathSegment = null;

            Semantic.KeySegment id = null;
            try
            {
                path = uriParser.ParsePath();
            }
            catch (ODataUnrecognizedPathException ex)
            {
                if (ex.ParsedSegments != null &&
                    ex.ParsedSegments.Count() > 0 &&
                    (ex.ParsedSegments.Last().EdmType is IEdmComplexType ||
                     ex.ParsedSegments.Last().EdmType is IEdmEntityType) &&
                    ex.CurrentSegment != ODataSegmentKinds.Count)
                {
                    if (ex.UnparsedSegments.Count() == 0)
                    {
                        path = new Semantic.ODataPath(ex.ParsedSegments);
                        unresolvedPathSegment = new UnresolvedPathSegment(ex.CurrentSegment);
                    }
                    else
                    {
                        // Throw ODataException if there is some segment following the unresolved segment.
                        throw new ODataException(Error.Format(
                                                     SRResources.InvalidPathSegment,
                                                     ex.UnparsedSegments.First(),
                                                     ex.CurrentSegment));
                    }
                }
                else
                {
                    throw;
                }
            }

            if (!enableUriTemplateParsing && path.LastSegment is Semantic.NavigationPropertyLinkSegment)
            {
                IEdmCollectionType lastSegmentEdmType = path.LastSegment.EdmType as IEdmCollectionType;

                if (lastSegmentEdmType != null)
                {
                    Semantic.EntityIdSegment entityIdSegment = null;
                    bool exceptionThrown = false;

                    try
                    {
                        entityIdSegment = uriParser.ParseEntityId();

                        if (entityIdSegment != null)
                        {
                            // Create another ODataUriParser to parse $id, which is absolute or relative.
                            ODataUriParser parser = new ODataUriParser(model, serviceRootUri, entityIdSegment.Id);
                            id = parser.ParsePath().LastSegment as Semantic.KeySegment;
                        }
                    }
                    catch (ODataException)
                    {
                        // Exception was thrown while parsing the $id.
                        // We will throw another exception about the invalid $id.
                        exceptionThrown = true;
                    }

                    if (exceptionThrown ||
                        (entityIdSegment != null &&
                         (id == null ||
                          !(id.EdmType.IsOrInheritsFrom(lastSegmentEdmType.ElementType.Definition) ||
                            lastSegmentEdmType.ElementType.Definition.IsOrInheritsFrom(id.EdmType)))))
                    {
                        throw new ODataException(Error.Format(SRResources.InvalidDollarId, /*queryString.Get("$id")*/ "$id"));
                    }
                }
            }

            ODataPath webAPIPath = ODataPathSegmentTranslator.TranslateODLPathToWebAPIPath(
                path,
                model,
                unresolvedPathSegment,
                id,
                enableUriTemplateParsing,
                uriParser.ParameterAliasNodes);

            CheckNavigableProperty(webAPIPath, model);
            return(webAPIPath);
        }