internal static void ExpandOutGlobalRoutes(List <RouteRequestBuilder> possibleRoutePaths, string[] routeKeys) { foreach (var possibleRoutePath in possibleRoutePaths) { while (FindAndAddSegmentMatch(possibleRoutePath, routeKeys)) { ; } while (!possibleRoutePath.IsFullMatch) { NodeLocation nodeLocation = new NodeLocation(); nodeLocation.SetNode(possibleRoutePath.LowestChild); List <RouteRequestBuilder> pureGlobalRoutesMatch = new List <RouteRequestBuilder>(); while (nodeLocation.Shell != null && pureGlobalRoutesMatch.Count == 0) { SearchPath(nodeLocation.LowestChild, null, possibleRoutePath.RemainingSegments, pureGlobalRoutesMatch, 0, ignoreGlobalRoutes: false); nodeLocation.Pop(); } // nothing found or too many things found if (pureGlobalRoutesMatch.Count != 1 || pureGlobalRoutesMatch[0].GlobalRouteMatches.Count == 0) { break; } for (var i = 0; i < pureGlobalRoutesMatch[0].GlobalRouteMatches.Count; i++) { var match = pureGlobalRoutesMatch[0]; possibleRoutePath.AddGlobalRoute(match.GlobalRouteMatches[i], match.SegmentsMatched[i]); } } } }
public NodeLocation WalkToNextNode() { int itemIndex = 0; int sectionIndex = 0; int contentIndex = 0; if (Item != null) { itemIndex = Shell.Items.IndexOf(Item); } if (Section != null) { sectionIndex = Item.Items.IndexOf(Section); } if (Content != null) { contentIndex = Section.Items.IndexOf(Content) + 1; } for (int i = itemIndex; i < Shell.Items.Count; i++) { for (int j = sectionIndex; j < Shell.Items[i].Items.Count; j++) { for (int k = contentIndex; k < Shell.Items[i].Items[j].Items.Count;) { var nodeLocation = new NodeLocation(); nodeLocation.SetNode(Shell.Items[i]); nodeLocation.SetNode(Shell.Items[i].Items[j]); nodeLocation.SetNode(Shell.Items[i].Items[j].Items[k]); return(nodeLocation); } contentIndex = 0; } sectionIndex = 0; } return(null); }
public static NodeLocation Create(Shell shell) { NodeLocation location = new NodeLocation(); location.SetNode( (object)shell.CurrentItem?.CurrentItem?.CurrentItem ?? (object)shell.CurrentItem?.CurrentItem ?? (object)shell.CurrentItem ?? (object)shell); return location; }
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); } }
internal static List <RouteRequestBuilder> GenerateRoutePaths(Shell shell, Uri request, Uri originalRequest) { request = FormatUri(request); originalRequest = FormatUri(originalRequest); var routeKeys = Routing.GetRouteKeys(); for (int i = 0; i < routeKeys.Length; i++) { routeKeys[i] = FormatUri(routeKeys[i]); } 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("/") && !originalRequest.OriginalString.StartsWith("\\")) { relativeMatch = true; } var segments = localPath.Split(_pathSeparator, StringSplitOptions.RemoveEmptyEntries); if (!relativeMatch) { for (int i = 0; i < routeKeys.Length; i++) { var route = routeKeys[i]; var uri = ConvertToStandardFormat(shell, new Uri(route, UriKind.RelativeOrAbsolute)); // Todo is this supported? if (uri.Equals(request)) { 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) { List <RouteRequestBuilder> pureRoutesMatch = new List <RouteRequestBuilder>(); List <RouteRequestBuilder> pureGlobalRoutesMatch = new List <RouteRequestBuilder>(); SearchPath(currentLocation.LowestChild, null, segments, pureRoutesMatch, 0); SearchPath(currentLocation.LowestChild, null, segments, pureGlobalRoutesMatch, 0, ignoreGlobalRoutes: false); pureRoutesMatch = GetBestMatches(pureRoutesMatch); pureGlobalRoutesMatch = GetBestMatches(pureGlobalRoutesMatch); if (pureRoutesMatch.Count > 0) { return(pureRoutesMatch); } if (pureGlobalRoutesMatch.Count > 0) { return(pureGlobalRoutesMatch); } currentLocation.Pop(); } string searchPath = String.Join("/", 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(); foreach (var possibleRoutePath in possibleRoutePaths) { while (routeKeys.Contains(possibleRoutePath.NextSegment) || routeKeys.Contains(possibleRoutePath.RemainingPath)) { if (routeKeys.Contains(possibleRoutePath.NextSegment)) { possibleRoutePath.AddGlobalRoute(possibleRoutePath.NextSegment, possibleRoutePath.NextSegment); } else { possibleRoutePath.AddGlobalRoute(possibleRoutePath.RemainingPath, possibleRoutePath.RemainingPath); } } while (!possibleRoutePath.IsFullMatch) { NodeLocation nodeLocation = new NodeLocation(); nodeLocation.SetNode(possibleRoutePath.LowestChild); List <RouteRequestBuilder> pureGlobalRoutesMatch = new List <RouteRequestBuilder>(); while (nodeLocation.Shell != null && pureGlobalRoutesMatch.Count == 0) { SearchPath(nodeLocation.LowestChild, null, possibleRoutePath.RemainingSegments, pureGlobalRoutesMatch, 0, ignoreGlobalRoutes: false); nodeLocation.Pop(); } // nothing found or too many things found if (pureGlobalRoutesMatch.Count != 1) { break; } for (var i = 0; i < pureGlobalRoutesMatch[0].GlobalRouteMatches.Count; i++) { var match = pureGlobalRoutesMatch[0]; possibleRoutePath.AddGlobalRoute(match.GlobalRouteMatches[i], match.SegmentsMatched[i]); } } } } possibleRoutePaths = GetBestMatches(possibleRoutePaths); return(possibleRoutePaths); }