Example #1
0
        static void SearchPath(
            object node,
            RouteRequestBuilder currentMatchedPath,
            string[] segments,
            List <RouteRequestBuilder> possibleRoutePaths,
            int depthToStart,
            int myDepth = -1,
            NodeLocation currentLocation = null,
            bool ignoreGlobalRoutes      = true)
        {
            if (node is GlobalRouteItem && ignoreGlobalRoutes)
            {
                return;
            }

            ++myDepth;
            currentLocation = currentLocation ?? new NodeLocation();
            currentLocation.SetNode(node);

            IEnumerable items = null;

            if (depthToStart > myDepth)
            {
                items = GetItems(node);
                if (items == null)
                {
                    return;
                }

                foreach (var nextNode in items)
                {
                    SearchPath(nextNode, null, segments, possibleRoutePaths, depthToStart, myDepth, currentLocation, ignoreGlobalRoutes);
                }
                return;
            }

            string shellSegment = GetRoute(node);
            string userSegment  = null;

            if (currentMatchedPath == null)
            {
                userSegment = segments[0];
            }
            else
            {
                userSegment = currentMatchedPath.NextSegment;
            }

            if (userSegment == null)
            {
                return;
            }

            RouteRequestBuilder builder = null;

            if (shellSegment == userSegment || Routing.IsImplicit(shellSegment))
            {
                if (currentMatchedPath == null)
                {
                    builder = new RouteRequestBuilder(shellSegment, userSegment, node, segments);
                }
                else
                {
                    builder = new RouteRequestBuilder(currentMatchedPath);
                    builder.AddMatch(shellSegment, userSegment, node);
                }

                if (!Routing.IsImplicit(shellSegment) || shellSegment == userSegment)
                {
                    possibleRoutePaths.Add(builder);
                }
            }

            items = GetItems(node);
            if (items == null)
            {
                return;
            }

            foreach (var nextNode in items)
            {
                SearchPath(nextNode, builder, segments, possibleRoutePaths, depthToStart, myDepth, currentLocation, ignoreGlobalRoutes);
            }
        }
Example #2
0
        static IEnumerable GetItems(object node)
        {
            IEnumerable results = null;

            switch (node)
            {
            case IShellController shell:
                results = shell.GetItems();
                break;

            case IShellItemController item:
                results = item.GetItems();
                break;

            case IShellSectionController section:
                results = section.GetItems();
                break;

            case ShellContent content:
                results = new object[0];
                break;

            case GlobalRouteItem routeITem:
                results = routeITem.Items;
                break;
            }

            if (results == null)
            {
                throw new ArgumentException($"{node}", nameof(node));
            }

            foreach (var result in results)
            {
                yield return(result);
            }

            if (node is GlobalRouteItem)
            {
                yield break;
            }

            var    keys  = Routing.GetRouteKeys();
            string route = GetRoute(node);

            for (var i = 0; i < keys.Length; i++)
            {
                var key = FormatUri(keys[i]);
                if (key.StartsWith(_pathSeparator, StringComparison.Ordinal) && !(node is Shell))
                {
                    continue;
                }

                var segments = key.Split(_pathSeparator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

                if (segments[0] == route)
                {
                    yield return(new GlobalRouteItem(key, key));
                }
            }
        }
Example #3
0
        internal static List <RouteRequestBuilder> GenerateRoutePaths(Shell shell, Uri request, Uri originalRequest, bool enableRelativeShellRoutes)
        {
            var routeKeys = Routing.GetRouteKeys();

            for (int i = 0; i < routeKeys.Length; i++)
            {
                if (routeKeys[i] == originalRequest.OriginalString)
                {
                    var builder = new RouteRequestBuilder(routeKeys[i], routeKeys[i], null, new string[] { routeKeys[i] });
                    return(new List <RouteRequestBuilder> {
                        builder
                    });
                }
                routeKeys[i] = FormatUri(routeKeys[i]);
            }

            request         = FormatUri(request, shell);
            originalRequest = FormatUri(originalRequest, shell);

            List <RouteRequestBuilder> possibleRoutePaths = new List <RouteRequestBuilder>();

            if (!request.IsAbsoluteUri)
            {
                request = ConvertToStandardFormat(shell, request);
            }

            string localPath = request.LocalPath;

            bool relativeMatch = false;

            if (!originalRequest.IsAbsoluteUri &&
                !originalRequest.OriginalString.StartsWith("//", StringComparison.Ordinal))
            {
                relativeMatch = true;
            }

            var segments = localPath.Split(_pathSeparator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

            if (!relativeMatch)
            {
                for (int i = 0; i < routeKeys.Length; i++)
                {
                    var route = routeKeys[i];
                    var uri   = ConvertToStandardFormat(shell, CreateUri(route));
                    if (uri.Equals(request))
                    {
                        throw new Exception($"Global routes currently cannot be the only page on the stack, so absolute routing to global routes is not supported. For now, just navigate to: {originalRequest.OriginalString.Replace("//", "")}");
                        //var builder = new RouteRequestBuilder(route, route, null, segments);
                        //return new List<RouteRequestBuilder> { builder };
                    }
                }
            }

            var depthStart = 0;

            if (segments[0] == shell?.Route)
            {
                segments   = segments.Skip(1).ToArray();
                depthStart = 1;
            }
            else
            {
                depthStart = 0;
            }

            if (relativeMatch && shell?.CurrentItem != null)
            {
                // retrieve current location
                var currentLocation = NodeLocation.Create(shell);

                while (currentLocation.Shell != null)
                {
                    var pureRoutesMatch       = new List <RouteRequestBuilder>();
                    var pureGlobalRoutesMatch = new List <RouteRequestBuilder>();

                    //currently relative routes to shell routes isn't supported as we aren't creating navigation stacks
                    if (enableRelativeShellRoutes)
                    {
                        SearchPath(currentLocation.LowestChild, null, segments, pureRoutesMatch, 0);
                        ExpandOutGlobalRoutes(pureRoutesMatch, routeKeys);
                        pureRoutesMatch = GetBestMatches(pureRoutesMatch);
                        if (pureRoutesMatch.Count > 0)
                        {
                            return(pureRoutesMatch);
                        }
                    }


                    SearchPath(currentLocation.LowestChild, null, segments, pureGlobalRoutesMatch, 0, ignoreGlobalRoutes: false);
                    ExpandOutGlobalRoutes(pureGlobalRoutesMatch, routeKeys);
                    pureGlobalRoutesMatch = GetBestMatches(pureGlobalRoutesMatch);
                    if (pureGlobalRoutesMatch.Count > 0)
                    {
                        // currently relative routes to shell routes isn't supported as we aren't creating navigation stacks
                        // So right now we will just throw an exception so that once this is implemented
                        // GotoAsync doesn't start acting inconsistently and all of a suddent starts creating routes
                        if (!enableRelativeShellRoutes && pureGlobalRoutesMatch[0].SegmentsMatched.Count > 0)
                        {
                            throw new Exception($"Relative routing to shell elements is currently not supported. Try prefixing your uri with ///: ///{originalRequest}");
                        }

                        return(pureGlobalRoutesMatch);
                    }

                    currentLocation.Pop();
                }

                string searchPath = String.Join(_pathSeparator, segments);

                if (routeKeys.Contains(searchPath))
                {
                    return(new List <RouteRequestBuilder> {
                        new RouteRequestBuilder(searchPath, searchPath, null, segments)
                    });
                }

                RouteRequestBuilder builder = null;
                foreach (var segment in segments)
                {
                    if (routeKeys.Contains(segment))
                    {
                        if (builder == null)
                        {
                            builder = new RouteRequestBuilder(segment, segment, null, segments);
                        }
                        else
                        {
                            builder.AddGlobalRoute(segment, segment);
                        }
                    }
                }

                if (builder != null && builder.IsFullMatch)
                {
                    return new List <RouteRequestBuilder> {
                               builder
                    }
                }
                ;
            }
            else
            {
                possibleRoutePaths.Clear();
                SearchPath(shell, null, segments, possibleRoutePaths, depthStart);

                var bestMatches = GetBestMatches(possibleRoutePaths);
                if (bestMatches.Count > 0)
                {
                    return(bestMatches);
                }

                bestMatches.Clear();
                ExpandOutGlobalRoutes(possibleRoutePaths, routeKeys);
            }

            possibleRoutePaths = GetBestMatches(possibleRoutePaths);
            return(possibleRoutePaths);
        }