private string CalculateTemplate() { int index = 0; StringBuilder sb = new StringBuilder(); foreach (var segment in Segments) { KeySegmentTemplate keySg = segment as KeySegmentTemplate; if (keySg != null) { sb.Append("("); sb.Append(segment.Literal); sb.Append(")"); } else { if (index != 0) { sb.Append("/"); } sb.Append(segment.Literal); index++; } } return(sb.ToString()); }
/// <inheritdoc /> public override bool TryTranslate(ODataTemplateTranslateContext context) { if (context == null) { throw Error.ArgumentNull(nameof(context)); } RouteValueDictionary routeValues = context.RouteValues; // the request should have the navigation property if (!routeValues.TryGetValue(ParameterName, out object rawValue)) { return(false); } string navigationProperty = rawValue as string; if (navigationProperty == null) { return(false); } // Find the navigation property IEdmNavigationProperty edmNavProperty = DeclaringType.ResolveProperty(navigationProperty) as IEdmNavigationProperty; if (edmNavProperty == null) { return(false); } IEdmNavigationSource targetNavigationSource = NavigationSource.FindNavigationTarget(edmNavProperty); // ODL implementation is complex, here i just use the NavigationPropertyLinkSegment context.Segments.Add(new NavigationPropertyLinkSegment(edmNavProperty, targetNavigationSource)); if (RelatedKey != null) { IEdmEntityType entityType = edmNavProperty.ToEntityType(); // only handle the single key IEdmStructuralProperty keyProperty = entityType.Key().SingleOrDefault(); Contract.Assert(entityType.Key().Count() == 1); Contract.Assert(keyProperty != null); IDictionary <string, string> keyValuePairs = new Dictionary <string, string> { { keyProperty.Name, $"{{{RelatedKey}}}" } }; KeySegmentTemplate keySegment = new KeySegmentTemplate(keyValuePairs, entityType, targetNavigationSource); return(keySegment.TryTranslate(context)); } return(true); }
private static string GetDisplayName(this KeySegmentTemplate segment) { Contract.Assert(segment != null); if (segment.KeyMappings.Count == 1) { return($"{{{segment.KeyMappings.First().Value}}}"); } return(string.Join(",", segment.KeyMappings.Select(a => $"{a.Key}={{{a.Value}}}"))); }
/// <summary> /// Generates all templates for the given <see cref="ODataPathTemplate"/>. /// All templates mean: /// 1) for key segment, we have key in parenthesis and key as segment. /// 2) for bound function segment, we have qualified function call and unqualified function call. /// </summary> /// <param name="path">The given path template.</param> /// <param name="options">The route options.</param> /// <returns>All path templates.</returns> public static IEnumerable <string> GetTemplates(this ODataPathTemplate path, ODataRouteOptions options = null) { if (path == null) { throw Error.ArgumentNull(nameof(path)); } options = options ?? ODataRouteOptions.Default; IList <StringBuilder> templates = new List <StringBuilder> { new StringBuilder() }; int count = path.Segments.Count; for (int index = 0; index < count; index++) { ODataSegmentTemplate segment = path.Segments[index]; if (segment.Kind == ODataSegmentKind.Key) { // for key segment, if it's single key, let's add key as segment template also // otherwise, we only add the key in parenthesis template. KeySegmentTemplate keySg = segment as KeySegmentTemplate; templates = AppendKeyTemplate(templates, keySg, options); continue; } if (index != 0) { templates = CombinateTemplate(templates, "/"); } // create => ~.../navigation/{key}/$ref if (segment.Kind == ODataSegmentKind.NavigationLink) { NavigationLinkSegmentTemplate navigationLinkSegment = (NavigationLinkSegmentTemplate)segment; if (index == count - 1) { // we don't have the other segment templates = CombinateTemplates(templates, $"{navigationLinkSegment.Segment.NavigationProperty.Name}/$ref"); } else { ODataSegmentTemplate nextSegment = path.Segments[index + 1]; if (nextSegment.Kind == ODataSegmentKind.Key) { // append "navigation property" templates = CombinateTemplates(templates, navigationLinkSegment.Segment.NavigationProperty.Name); // append "key" KeySegmentTemplate keySg = nextSegment as KeySegmentTemplate; templates = AppendKeyTemplate(templates, keySg, options); // append $ref templates = CombinateTemplates(templates, "/$ref"); index++; // skip the key segment after $ref. } else { templates = CombinateTemplates(templates, $"{navigationLinkSegment.Segment.NavigationProperty.Name}/$ref"); } } continue; } if (segment.Kind == ODataSegmentKind.Action) { ActionSegmentTemplate action = (ActionSegmentTemplate)segment; templates = AppendActionTemplate(templates, action, options); } else if (segment.Kind == ODataSegmentKind.Function) { FunctionSegmentTemplate function = (FunctionSegmentTemplate)segment; templates = AppendFunctionTemplate(templates, function, options); } else { templates = CombinateTemplate(templates, segment.Literal); } } return(templates.Select(t => t.ToString())); }
private static IList <StringBuilder> AppendKeyTemplate(IList <StringBuilder> templates, KeySegmentTemplate segment, ODataRouteOptions options) { Contract.Assert(segment != null); Contract.Assert(options != null); if (options.EnableKeyInParenthesis && options.EnableKeyAsSegment) { return(CombinateTemplates(templates, $"({segment.Literal})", $"/{segment.Literal}")); } else if (options.EnableKeyInParenthesis) { return(CombinateTemplate(templates, $"({segment.Literal})")); } else if (options.EnableKeyAsSegment) { return(CombinateTemplate(templates, $"/{segment.Literal}")); } else { throw new ODataException(SRResources.RouteOptionDisabledKeySegment); } }
/// <summary> /// Generates all templates for the given <see cref="ODataPathTemplate"/> /// </summary> /// <param name="path">The given path template.</param> /// <returns>All path templates.</returns> public static IEnumerable <string> GetTemplates(this ODataPathTemplate path) { if (path == null) { throw Error.ArgumentNull(nameof(path)); } IList <StringBuilder> templates = new List <StringBuilder> { new StringBuilder() }; int count = path.Segments.Count; for (int index = 0; index < count; index++) { ODataSegmentTemplate segment = path.Segments[index]; if (segment.Kind == ODataSegmentKind.Key) { KeySegmentTemplate keySg = segment as KeySegmentTemplate; if (keySg.Count == 1) { templates = CombinateTemplates(templates, "(" + segment.Literal + ")", "/" + segment.Literal); } else { templates = CombinateTemplate(templates, "(" + segment.Literal + ")"); } continue; } if (index != 0) { templates = CombinateTemplate(templates, "/"); } // create => ~.../navigation/{key}/$ref if (segment.Kind == ODataSegmentKind.NavigationLink) { NavigationPropertyLinkSegmentTemplate navigationLinkSegment = (NavigationPropertyLinkSegmentTemplate)segment; if (index == count - 1) { // we don't have the other segment templates = CombinateTemplates(templates, $"{navigationLinkSegment.Segment.NavigationProperty.Name}/$ref"); } else { ODataSegmentTemplate nextSegment = path.Segments[index + 1]; if (nextSegment.Kind == ODataSegmentKind.Key) { // append "navigation property" templates = CombinateTemplates(templates, navigationLinkSegment.Segment.NavigationProperty.Name); // append "key" KeySegmentTemplate keySg = nextSegment as KeySegmentTemplate; if (keySg.Count == 1) { templates = CombinateTemplates(templates, "(" + nextSegment.Literal + ")", "/" + nextSegment.Literal); } else { templates = CombinateTemplate(templates, "(" + nextSegment.Literal + ")"); } // append $ref templates = CombinateTemplates(templates, "/$ref"); index++; // skip the key segment after $ref. } else { templates = CombinateTemplates(templates, $"{navigationLinkSegment.Segment.NavigationProperty.Name}/$ref"); } } continue; } if (segment.Kind == ODataSegmentKind.Action) { ActionSegmentTemplate action = (ActionSegmentTemplate)segment; templates = CombinateTemplates(templates, action.Action.FullName(), action.Action.Name); } else if (segment.Kind == ODataSegmentKind.Function) { FunctionSegmentTemplate function = (FunctionSegmentTemplate)segment; templates = CombinateTemplates(templates, function.Literal, function.UnqualifiedIdentifier); } else { templates = CombinateTemplate(templates, segment.Literal); } } return(templates.Select(t => t.ToString())); }
/// <summary> /// Gets the whole supported template belongs to a <see cref="ODataPathTemplate"/>. /// We supports: /// 1. Key as segment if it's single key (We doesn't consider the alternate key so far) /// 2. Unqualified function/action call /// 3. Optional parameters combination. /// </summary> /// <param name="path">The input path template.</param> /// <returns>The whole path template string.</returns> public static IEnumerable <string> GetAllTemplates(this ODataPathTemplate path) { if (path == null) { throw new ArgumentNullException(nameof(path)); } IList <StringBuilder> templates = new List <StringBuilder> { new StringBuilder() }; int index = 0; foreach (ODataSegmentTemplate segment in path.Segments) { if (segment.Kind == ODataSegmentKind.Key) { KeySegmentTemplate keySg = segment as KeySegmentTemplate; if (keySg.Count == 1) { templates = CombinateTemplates(templates, "(" + segment.Literal + ")", "/" + segment.Literal); } else { templates = CombinateTemplate(templates, "(" + segment.Literal + ")"); } index++; continue; } if (index != 0) { templates = CombinateTemplate(templates, "/"); } index++; if (segment.Kind == ODataSegmentKind.Action) { ActionSegmentTemplate action = (ActionSegmentTemplate)segment; templates = CombinateTemplates(templates, action.Action.FullName(), action.Action.Name); } else if (segment.Kind == ODataSegmentKind.Function) { FunctionSegmentTemplate function = (FunctionSegmentTemplate)segment; IList <string> functionTemplates = function.Function.GenerateFunctionTemplates(); templates = CombinateTemplates(templates, functionTemplates); } else if (segment.Kind == ODataSegmentKind.FunctionImport) { FunctionImportSegmentTemplate functionImport = (FunctionImportSegmentTemplate)segment; IList <string> functionTemplates = functionImport.FunctionImport.Function.GenerateFunctionTemplates(); templates = CombinateTemplates(templates, functionTemplates); } else { templates = CombinateTemplate(templates, segment.Literal); } } return(templates.Select(t => t.ToString())); }