예제 #1
0
        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());
        }
예제 #2
0
        /// <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()));
        }