1+ import { RouteSegment , UrlSegment , Tree } from './segments' ;
2+ import { RoutesMetadata , RouteMetadata } from './metadata/metadata' ;
3+ import { Type , isPresent , stringify } from 'angular2/src/facade/lang' ;
4+ import { PromiseWrapper } from 'angular2/src/facade/promise' ;
5+ import { BaseException } from 'angular2/src/facade/exceptions' ;
6+ import { ComponentResolver } from 'angular2/core' ;
7+ import { reflector } from 'angular2/src/core/reflection/reflection' ;
8+
9+ export function recognize ( componentResolver : ComponentResolver , type : Type ,
10+ url : Tree < UrlSegment > ) : Promise < Tree < RouteSegment > > {
11+ return _recognize ( componentResolver , type , url , url . root )
12+ . then ( nodes => new Tree < RouteSegment > ( nodes ) ) ;
13+ }
14+
15+ function _recognize ( componentResolver : ComponentResolver , type : Type , url : Tree < UrlSegment > ,
16+ current : UrlSegment ) : Promise < RouteSegment [ ] > {
17+ let metadata = _readMetadata ( type ) ; // should read from the factory instead
18+
19+ let matched ;
20+ try {
21+ matched = _match ( metadata , url , current ) ;
22+ } catch ( e ) {
23+ return PromiseWrapper . reject ( e , null ) ;
24+ }
25+
26+ return componentResolver . resolveComponent ( matched . route . component )
27+ . then ( factory => {
28+ let segment = new RouteSegment ( matched . consumedUrlSegments , matched . parameters , "" ,
29+ matched . route . component , factory ) ;
30+
31+ if ( isPresent ( matched . leftOver ) ) {
32+ return _recognize ( componentResolver , matched . route . component , url , matched . leftOver )
33+ . then ( children => [ segment ] . concat ( children ) ) ;
34+ } else {
35+ return [ segment ] ;
36+ }
37+ } ) ;
38+ }
39+
40+ function _match ( metadata : RoutesMetadata , url : Tree < UrlSegment > ,
41+ current : UrlSegment ) : _MatchingResult {
42+ for ( let r of metadata . routes ) {
43+ let matchingResult = _matchWithParts ( r , url , current ) ;
44+ if ( isPresent ( matchingResult ) ) {
45+ return matchingResult ;
46+ }
47+ }
48+ throw new BaseException ( "Cannot match any routes" ) ;
49+ }
50+
51+ function _matchWithParts ( route : RouteMetadata , url : Tree < UrlSegment > ,
52+ current : UrlSegment ) : _MatchingResult {
53+ let parts = route . path . split ( "/" ) ;
54+ let parameters = { } ;
55+ let consumedUrlSegments = [ ] ;
56+
57+ let u = current ;
58+ for ( let i = 0 ; i < parts . length ; ++ i ) {
59+ consumedUrlSegments . push ( u ) ;
60+ let p = parts [ i ] ;
61+ if ( p . startsWith ( ":" ) ) {
62+ let segment = u . segment ;
63+ parameters [ p . substring ( 1 ) ] = segment ;
64+ } else if ( p != u . segment ) {
65+ return null ;
66+ }
67+ u = url . firstChild ( u ) ;
68+ }
69+ return new _MatchingResult ( route , consumedUrlSegments , parameters , u ) ;
70+ }
71+
72+ class _MatchingResult {
73+ constructor ( public route : RouteMetadata , public consumedUrlSegments : UrlSegment [ ] ,
74+ public parameters : { [ key : string ] : string } , public leftOver : UrlSegment ) { }
75+ }
76+
77+ function _readMetadata ( componentType : Type ) {
78+ let metadata = reflector . annotations ( componentType ) . filter ( f => f instanceof RoutesMetadata ) ;
79+ if ( metadata . length === 0 ) {
80+ throw new BaseException (
81+ `Component '${ stringify ( componentType ) } ' does not have route configuration` ) ;
82+ }
83+ return metadata [ 0 ] ;
84+ }
0 commit comments