/// <summary> /// Generates all templates for an input function. /// </summary> /// <param name="segment">The input function.</param> /// <returns>All templates.</returns> public static IList <FunctionSegmentTemplate> GenerateFunctionSegments(this FunctionSegmentTemplate segment) { if (segment == null) { throw new ArgumentNullException(nameof(segment)); } // split parameters (var fixes, var optionals) = SplitParameters(segment.Function); // gets all combinations of the optional parameters. Stack <IEdmOptionalParameter> current = new Stack <IEdmOptionalParameter>(); IList <IEdmOptionalParameter[]> full = new List <IEdmOptionalParameter[]>(); int length = optionals.Count; if (optionals.Count > 0) { Traveral(optionals.ToArray(), 0, length, current, full); } IList <FunctionSegmentTemplate> newList = new List <FunctionSegmentTemplate>(); foreach (var optional in full) { ISet <string> requiredParameters = new HashSet <string>(fixes.Select(e => e.Name)); foreach (var optionalParameter in optional) { requiredParameters.Add(optionalParameter.Name); } newList.Add(new FunctionSegmentTemplate(segment.Function, segment.NavigationSource, requiredParameters)); } return(newList); }
private static string GetDisplayName(this FunctionSegmentTemplate segment, bool qualified) { Contract.Assert(segment != null); string parameters = "(" + string.Join(",", segment.ParameterMappings.Select(a => $"{a.Key}={{{a.Value}}}")) + ")"; if (qualified) { return(segment.Function.FullName() + parameters); } else { return(segment.Function.Name + parameters); } }
/// <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> AppendFunctionTemplate(IList <StringBuilder> templates, FunctionSegmentTemplate segment, ODataRouteOptions options) { Contract.Assert(segment != null); Contract.Assert(options != null); if (options.EnableQualifiedOperationCall && options.EnableUnqualifiedOperationCall) { return(CombinateTemplates(templates, segment.Literal, segment.UnqualifiedIdentifier)); } else if (options.EnableQualifiedOperationCall) { return(CombinateTemplate(templates, segment.Literal)); } else if (options.EnableUnqualifiedOperationCall) { return(CombinateTemplate(templates, segment.UnqualifiedIdentifier)); } else { throw new ODataException(Error.Format(SRResources.RouteOptionDisabledOperationSegment, "function")); } }
private static IList <TemplateInfo> AppendFunctionTemplate(IList <TemplateInfo> templates, FunctionSegmentTemplate segment, ODataRouteOptions options) { Contract.Assert(segment != null); Contract.Assert(options != null); string qualified = segment.GetDisplayName(true); string unqulified = segment.GetDisplayName(false); if (options.EnableQualifiedOperationCall && options.EnableUnqualifiedOperationCall) { return(CombinateTemplates(templates, (segment.Literal, qualified), (segment.UnqualifiedIdentifier, unqulified))); } else if (options.EnableQualifiedOperationCall) { return(CombinateTemplate(templates, (segment.Literal, qualified))); } else if (options.EnableUnqualifiedOperationCall) { return(CombinateTemplate(templates, (segment.UnqualifiedIdentifier, unqulified))); } else { throw new ODataException(Error.Format(SRResources.RouteOptionDisabledOperationSegment, "function")); } }
/// <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())); }