// We need to append the key value path segment from $id. private static void AppendIdForRef(IList <ODataPathSegment> segments, Semantic.KeySegment id) { if (id == null || !(segments.Last() is RefPathSegment)) { return; } segments.Add(new KeyValuePathSegment(ConvertKeysToString(id.Keys, enableUriTemplateParsing: false))); }
/// <summary> /// Check if this segment is equal to another segment. /// </summary> /// <param name="other">the other segment to check.</param> /// <returns>true if the other segment is equal.</returns> /// <exception cref="System.ArgumentNullException">Throws if the input other is null.</exception> internal override bool Equals(ODataPathSegment other) { ExceptionUtils.CheckArgumentNotNull(other, "other"); KeySegment otherKeySegment = other as KeySegment; return(otherKeySegment != null && otherKeySegment.Keys.SequenceEqual(this.Keys) && otherKeySegment.EdmType == this.edmType && otherKeySegment.NavigationSource == this.navigationSource); }
/// <summary> /// Append the key segment in the end of ODataPath, the method does not modify current ODataPath instance, /// it returns a new ODataPath without ending type segment. /// If last segment is type cast, the key would be appended before type cast segment. /// </summary> /// <param name="path">Path to perform the computation on.</param> /// <param name="keys">The set of key property names and the values to be used in searching for the given item.</param> /// <param name="edmType">The type of the item this key returns.</param> /// <param name="navigationSource">The navigation source that this key is used to search.</param> /// <returns>The ODataPath with key segment appended</returns> public static ODataPath AppendKeySegment(this ODataPath path, IEnumerable <KeyValuePair <string, object> > keys, IEdmEntityType edmType, IEdmNavigationSource navigationSource) { var handler = new SplitEndingSegmentOfTypeHandler <TypeSegment>(); path.WalkWith(handler); KeySegment keySegment = new KeySegment(keys, edmType, navigationSource); ODataPath newPath = handler.FirstPart; newPath.Add(keySegment); foreach (var segment in handler.LastPart) { newPath.Add(segment); } return(newPath); }
/// <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); }
/// <summary> /// Translate a KeySegment /// </summary> /// <param name="segment">the segment to Translate</param> /// <returns>Translated WebApi path segment.</returns> public override IEnumerable <ODataPathSegment> Translate(Semantic.KeySegment segment) { yield return(new KeyValuePathSegment(ConvertKeysToString(segment.Keys, _enableUriTemplateParsing))); }
private static ODataPath Parse( IEdmModel model, string serviceRoot, string odataPath, ODataUriResolverSetttings resolverSettings, bool enableUriTemplateParsing) { ODataUriParser uriParser; Uri serviceRootUri = null; Uri fullUri = null; 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"))); } } } ODataPath webAPIPath = ODataPathSegmentTranslator.TranslateODLPathToWebAPIPath( path, model, unresolvedPathSegment, id, enableUriTemplateParsing, uriParser.ParameterAliasNodes); CheckNavigableProperty(webAPIPath, model); return(webAPIPath); }
/// <summary> /// Determine the NavigationSource of a KeySegment /// </summary> /// <param name="segment">The KeySegment to look in.</param> /// <returns>The IEdmNavigationSource of this KeySegment</returns> /// <exception cref="System.ArgumentNullException">Throws if the input segment is null.</exception> public override IEdmNavigationSource Translate(KeySegment segment) { ExceptionUtils.CheckArgumentNotNull(segment, "segment"); return(segment.NavigationSource); }