/// <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; }
/// <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); }
/// <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); }
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)); }
/// <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) { }
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; }
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); }