|
| 1 | +import {Tree, TreeNode, UrlSegment, RouteSegment, rootNode} from './segments'; |
| 2 | +import {isBlank, isString, isStringMap} from 'angular2/src/facade/lang'; |
| 3 | +import {ListWrapper} from 'angular2/src/facade/collection'; |
| 4 | + |
| 5 | +export function link(segment: RouteSegment, tree: Tree<UrlSegment>, |
| 6 | + change: any[]): Tree<UrlSegment> { |
| 7 | + if (change.length === 0) return tree; |
| 8 | + let normalizedChange = (change.length === 1 && change[0] == "/") ? change : ["/"].concat(change); |
| 9 | + return new Tree<UrlSegment>(_update(rootNode(tree), normalizedChange)); |
| 10 | +} |
| 11 | + |
| 12 | +function _update(node: TreeNode<UrlSegment>, changes: any[]): TreeNode<UrlSegment> { |
| 13 | + let rest = changes.slice(1); |
| 14 | + let outlet = _outlet(changes); |
| 15 | + let segment = _segment(changes); |
| 16 | + if (isString(segment) && segment[0] == "/") segment = segment.substring(1); |
| 17 | + |
| 18 | + // reach the end of the tree => create new tree nodes. |
| 19 | + if (isBlank(node)) { |
| 20 | + let urlSegment = new UrlSegment(segment, null, outlet); |
| 21 | + let children = rest.length === 0 ? [] : [_update(null, rest)]; |
| 22 | + return new TreeNode<UrlSegment>(urlSegment, children); |
| 23 | + |
| 24 | + // different outlet => preserve the subtree |
| 25 | + } else if (outlet != node.value.outlet) { |
| 26 | + return node; |
| 27 | + |
| 28 | + // same outlet => modify the subtree |
| 29 | + } else { |
| 30 | + let urlSegment = isStringMap(segment) ? new UrlSegment(null, segment, null) : |
| 31 | + new UrlSegment(segment, null, outlet); |
| 32 | + if (rest.length === 0) { |
| 33 | + return new TreeNode<UrlSegment>(urlSegment, []); |
| 34 | + } |
| 35 | + |
| 36 | + return new TreeNode<UrlSegment>(urlSegment, |
| 37 | + _updateMany(ListWrapper.clone(node.children), rest)); |
| 38 | + } |
| 39 | +} |
| 40 | + |
| 41 | +function _updateMany(nodes: TreeNode<UrlSegment>[], changes: any[]): TreeNode<UrlSegment>[] { |
| 42 | + let outlet = _outlet(changes); |
| 43 | + let nodesInRightOutlet = nodes.filter(c => c.value.outlet == outlet); |
| 44 | + if (nodesInRightOutlet.length > 0) { |
| 45 | + let nodeRightOutlet = nodesInRightOutlet[0]; // there can be only one |
| 46 | + nodes[nodes.indexOf(nodeRightOutlet)] = _update(nodeRightOutlet, changes); |
| 47 | + } else { |
| 48 | + nodes.push(_update(null, changes)); |
| 49 | + } |
| 50 | + |
| 51 | + return nodes; |
| 52 | +} |
| 53 | + |
| 54 | +function _segment(changes: any[]): any { |
| 55 | + if (!isString(changes[0])) return changes[0]; |
| 56 | + let parts = changes[0].toString().split(":"); |
| 57 | + return parts.length > 1 ? parts[1] : changes[0]; |
| 58 | +} |
| 59 | + |
| 60 | +function _outlet(changes: any[]): string { |
| 61 | + if (!isString(changes[0])) return null; |
| 62 | + let parts = changes[0].toString().split(":"); |
| 63 | + return parts.length > 1 ? parts[0] : null; |
| 64 | +} |
0 commit comments