angular2
Version:
Angular 2 - a web framework for modern web apps
122 lines (121 loc) • 5.11 kB
JavaScript
import { isBlank, isPresent } from 'angular2/src/facade/lang';
import { BaseException } from 'angular2/src/facade/exceptions';
import { Map } from 'angular2/src/facade/collection';
import { PromiseWrapper } from 'angular2/src/facade/async';
import { RouteRecognizer, RedirectRecognizer } from './route_recognizer';
import { Route, AsyncRoute, AuxRoute, Redirect } from './route_config_impl';
import { AsyncRouteHandler } from './async_route_handler';
import { SyncRouteHandler } from './sync_route_handler';
/**
* `ComponentRecognizer` is responsible for recognizing routes for a single component.
* It is consumed by `RouteRegistry`, which knows how to recognize an entire hierarchy of
* components.
*/
export class ComponentRecognizer {
constructor() {
this.names = new Map();
// map from name to recognizer
this.auxNames = new Map();
// map from starting path to recognizer
this.auxRoutes = new Map();
// TODO: optimize this into a trie
this.matchers = [];
this.defaultRoute = null;
}
/**
* returns whether or not the config is terminal
*/
config(config) {
var handler;
if (isPresent(config.name) && config.name[0].toUpperCase() != config.name[0]) {
var suggestedName = config.name[0].toUpperCase() + config.name.substring(1);
throw new BaseException(`Route "${config.path}" with name "${config.name}" does not begin with an uppercase letter. Route names should be CamelCase like "${suggestedName}".`);
}
if (config instanceof AuxRoute) {
handler = new SyncRouteHandler(config.component, config.data);
let path = config.path.startsWith('/') ? config.path.substring(1) : config.path;
var recognizer = new RouteRecognizer(config.path, handler);
this.auxRoutes.set(path, recognizer);
if (isPresent(config.name)) {
this.auxNames.set(config.name, recognizer);
}
return recognizer.terminal;
}
var useAsDefault = false;
if (config instanceof Redirect) {
let redirector = new RedirectRecognizer(config.path, config.redirectTo);
this._assertNoHashCollision(redirector.hash, config.path);
this.matchers.push(redirector);
return true;
}
if (config instanceof Route) {
handler = new SyncRouteHandler(config.component, config.data);
useAsDefault = isPresent(config.useAsDefault) && config.useAsDefault;
}
else if (config instanceof AsyncRoute) {
handler = new AsyncRouteHandler(config.loader, config.data);
useAsDefault = isPresent(config.useAsDefault) && config.useAsDefault;
}
var recognizer = new RouteRecognizer(config.path, handler);
this._assertNoHashCollision(recognizer.hash, config.path);
if (useAsDefault) {
if (isPresent(this.defaultRoute)) {
throw new BaseException(`Only one route can be default`);
}
this.defaultRoute = recognizer;
}
this.matchers.push(recognizer);
if (isPresent(config.name)) {
this.names.set(config.name, recognizer);
}
return recognizer.terminal;
}
_assertNoHashCollision(hash, path) {
this.matchers.forEach((matcher) => {
if (hash == matcher.hash) {
throw new BaseException(`Configuration '${path}' conflicts with existing route '${matcher.path}'`);
}
});
}
/**
* Given a URL, returns a list of `RouteMatch`es, which are partial recognitions for some route.
*/
recognize(urlParse) {
var solutions = [];
this.matchers.forEach((routeRecognizer) => {
var pathMatch = routeRecognizer.recognize(urlParse);
if (isPresent(pathMatch)) {
solutions.push(pathMatch);
}
});
return solutions;
}
recognizeAuxiliary(urlParse) {
var routeRecognizer = this.auxRoutes.get(urlParse.path);
if (isPresent(routeRecognizer)) {
return [routeRecognizer.recognize(urlParse)];
}
return [PromiseWrapper.resolve(null)];
}
hasRoute(name) { return this.names.has(name); }
componentLoaded(name) {
return this.hasRoute(name) && isPresent(this.names.get(name).handler.componentType);
}
loadComponent(name) {
return this.names.get(name).handler.resolveComponentType();
}
generate(name, params) {
var pathRecognizer = this.names.get(name);
if (isBlank(pathRecognizer)) {
return null;
}
return pathRecognizer.generate(params);
}
generateAuxiliary(name, params) {
var pathRecognizer = this.auxNames.get(name);
if (isBlank(pathRecognizer)) {
return null;
}
return pathRecognizer.generate(params);
}
}