| 
									
										
										
										
											2015-05-29 14:58:41 -07:00
										 |  |  | import { | 
					
						
							|  |  |  |   RegExp, | 
					
						
							|  |  |  |   RegExpWrapper, | 
					
						
							|  |  |  |   StringWrapper, | 
					
						
							|  |  |  |   isPresent, | 
					
						
							|  |  |  |   BaseException | 
					
						
							|  |  |  | } from 'angular2/src/facade/lang'; | 
					
						
							|  |  |  | import { | 
					
						
							|  |  |  |   Map, | 
					
						
							|  |  |  |   MapWrapper, | 
					
						
							|  |  |  |   List, | 
					
						
							|  |  |  |   ListWrapper, | 
					
						
							|  |  |  |   StringMap, | 
					
						
							|  |  |  |   StringMapWrapper | 
					
						
							|  |  |  | } from 'angular2/src/facade/collection'; | 
					
						
							| 
									
										
										
										
											2015-04-17 09:59:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | import {PathRecognizer} from './path_recognizer'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 02:05:57 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * `RouteRecognizer` is responsible for recognizing routes for a single component. | 
					
						
							| 
									
										
										
										
											2015-05-29 14:58:41 -07:00
										 |  |  |  * It is consumed by `RouteRegistry`, which knows how to recognize an entire hierarchy of | 
					
						
							|  |  |  |  * components. | 
					
						
							| 
									
										
										
										
											2015-05-15 02:05:57 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-04-17 09:59:56 -07:00
										 |  |  | export class RouteRecognizer { | 
					
						
							| 
									
										
										
										
											2015-05-29 14:58:41 -07:00
										 |  |  |   names: Map<string, PathRecognizer>; | 
					
						
							|  |  |  |   redirects: Map<string, string>; | 
					
						
							|  |  |  |   matchers: Map<RegExp, PathRecognizer>; | 
					
						
							| 
									
										
										
										
											2015-04-17 09:59:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   constructor() { | 
					
						
							|  |  |  |     this.names = MapWrapper.create(); | 
					
						
							|  |  |  |     this.matchers = MapWrapper.create(); | 
					
						
							|  |  |  |     this.redirects = MapWrapper.create(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-29 14:58:41 -07:00
										 |  |  |   addRedirect(path: string, target: string): void { MapWrapper.set(this.redirects, path, target); } | 
					
						
							| 
									
										
										
										
											2015-04-17 09:59:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-29 14:58:41 -07:00
										 |  |  |   addConfig(path: string, handler: any, alias: string = null): void { | 
					
						
							| 
									
										
										
										
											2015-04-17 09:59:56 -07:00
										 |  |  |     var recognizer = new PathRecognizer(path, handler); | 
					
						
							| 
									
										
										
										
											2015-05-15 02:05:57 -07:00
										 |  |  |     MapWrapper.forEach(this.matchers, (matcher, _) => { | 
					
						
							|  |  |  |       if (recognizer.regex.toString() == matcher.regex.toString()) { | 
					
						
							| 
									
										
										
										
											2015-05-29 14:58:41 -07:00
										 |  |  |         throw new BaseException( | 
					
						
							|  |  |  |             `Configuration '${path}' conflicts with existing route '${matcher.path}'`); | 
					
						
							| 
									
										
										
										
											2015-05-15 02:05:57 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-04-17 09:59:56 -07:00
										 |  |  |     MapWrapper.set(this.matchers, recognizer.regex, recognizer); | 
					
						
							|  |  |  |     if (isPresent(alias)) { | 
					
						
							|  |  |  |       MapWrapper.set(this.names, alias, recognizer); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 02:05:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Given a URL, returns a list of `RouteMatch`es, which are partial recognitions for some route. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2015-05-29 14:58:41 -07:00
										 |  |  |   recognize(url: string): List<RouteMatch> { | 
					
						
							| 
									
										
										
										
											2015-05-15 02:05:57 -07:00
										 |  |  |     var solutions = ListWrapper.create(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-17 09:59:56 -07:00
										 |  |  |     MapWrapper.forEach(this.redirects, (target, path) => { | 
					
						
							| 
									
										
										
										
											2015-06-15 00:45:02 -07:00
										 |  |  |       // "/" redirect case
 | 
					
						
							|  |  |  |       if (path == '/' || path == '') { | 
					
						
							|  |  |  |         if (path == url) { | 
					
						
							|  |  |  |           url = target; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } else if (StringWrapper.startsWith(url, path)) { | 
					
						
							| 
									
										
										
										
											2015-04-17 09:59:56 -07:00
										 |  |  |         url = target + StringWrapper.substring(url, path.length); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     MapWrapper.forEach(this.matchers, (pathRecognizer, regex) => { | 
					
						
							|  |  |  |       var match; | 
					
						
							|  |  |  |       if (isPresent(match = RegExpWrapper.firstMatch(regex, url))) { | 
					
						
							| 
									
										
										
										
											2015-05-29 14:58:41 -07:00
										 |  |  |         // TODO(btford): determine a good generic way to deal with terminal matches
 | 
					
						
							| 
									
										
										
										
											2015-05-15 02:05:57 -07:00
										 |  |  |         var matchedUrl = '/'; | 
					
						
							|  |  |  |         var unmatchedUrl = ''; | 
					
						
							|  |  |  |         if (url != '/') { | 
					
						
							|  |  |  |           matchedUrl = match[0]; | 
					
						
							|  |  |  |           unmatchedUrl = StringWrapper.substring(url, match[0].length); | 
					
						
							| 
									
										
										
										
											2015-04-29 15:47:12 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-15 02:05:57 -07:00
										 |  |  |         ListWrapper.push(solutions, new RouteMatch({ | 
					
						
							| 
									
										
										
										
											2015-05-29 14:58:41 -07:00
										 |  |  |                            specificity: pathRecognizer.specificity, | 
					
						
							|  |  |  |                            handler: pathRecognizer.handler, | 
					
						
							|  |  |  |                            params: pathRecognizer.parseParams(url), | 
					
						
							|  |  |  |                            matchedUrl: matchedUrl, | 
					
						
							|  |  |  |                            unmatchedUrl: unmatchedUrl | 
					
						
							|  |  |  |                          })); | 
					
						
							| 
									
										
										
										
											2015-04-17 09:59:56 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return solutions; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-29 14:58:41 -07:00
										 |  |  |   hasRoute(name: string): boolean { return MapWrapper.contains(this.names, name); } | 
					
						
							| 
									
										
										
										
											2015-04-17 09:59:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-29 14:58:41 -07:00
										 |  |  |   generate(name: string, params: any): string { | 
					
						
							| 
									
										
										
										
											2015-04-17 09:59:56 -07:00
										 |  |  |     var pathRecognizer = MapWrapper.get(this.names, name); | 
					
						
							| 
									
										
										
										
											2015-05-14 15:24:35 +02:00
										 |  |  |     return isPresent(pathRecognizer) ? pathRecognizer.generate(params) : null; | 
					
						
							| 
									
										
										
										
											2015-04-17 09:59:56 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-05-15 02:05:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | export class RouteMatch { | 
					
						
							| 
									
										
										
										
											2015-05-29 14:58:41 -07:00
										 |  |  |   specificity: number; | 
					
						
							|  |  |  |   handler: StringMap<string, any>; | 
					
						
							|  |  |  |   params: StringMap<string, string>; | 
					
						
							|  |  |  |   matchedUrl: string; | 
					
						
							|  |  |  |   unmatchedUrl: string; | 
					
						
							|  |  |  |   constructor({specificity, handler, params, matchedUrl, unmatchedUrl}: { | 
					
						
							|  |  |  |     specificity?: number, | 
					
						
							|  |  |  |     handler?: StringMap<string, any>, | 
					
						
							|  |  |  |     params?: StringMap<string, string>, | 
					
						
							|  |  |  |     matchedUrl?: string, | 
					
						
							|  |  |  |     unmatchedUrl?: string | 
					
						
							|  |  |  |   } = {}) { | 
					
						
							| 
									
										
										
										
											2015-05-15 02:05:57 -07:00
										 |  |  |     this.specificity = specificity; | 
					
						
							|  |  |  |     this.handler = handler; | 
					
						
							|  |  |  |     this.params = params; | 
					
						
							|  |  |  |     this.matchedUrl = matchedUrl; | 
					
						
							|  |  |  |     this.unmatchedUrl = unmatchedUrl; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |