text: /**
   * @license Angular v4.3.4
   * (c) 2010-2017 Google, Inc. https://angular.io/
   * License: MIT
   */
  (function (global, factory) {
  	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/common'), require('@angular/core'), require('rxjs/BehaviorSubject'), require('rxjs/Subject'), require('rxjs/observable/from'), require('rxjs/observable/of'), require('rxjs/operator/concatMap'), require('rxjs/operator/every'), require('rxjs/operator/first'), require('rxjs/operator/last'), require('rxjs/operator/map'), require('rxjs/operator/mergeMap'), require('rxjs/operator/reduce'), require('rxjs/Observable'), require('rxjs/operator/catch'), require('rxjs/operator/concatAll'), require('rxjs/util/EmptyError'), require('rxjs/observable/fromPromise'), require('rxjs/operator/mergeAll'), require('@angular/platform-browser'), require('rxjs/operator/filter')) :
  	typeof define === 'function' && define.amd ? define(['exports', '@angular/common', '@angular/core', 'rxjs/BehaviorSubject', 'rxjs/Subject', 'rxjs/observable/from', 'rxjs/observable/of', 'rxjs/operator/concatMap', 'rxjs/operator/every', 'rxjs/operator/first', 'rxjs/operator/last', 'rxjs/operator/map', 'rxjs/operator/mergeMap', 'rxjs/operator/reduce', 'rxjs/Observable', 'rxjs/operator/catch', 'rxjs/operator/concatAll', 'rxjs/util/EmptyError', 'rxjs/observable/fromPromise', 'rxjs/operator/mergeAll', '@angular/platform-browser', 'rxjs/operator/filter'], factory) :
  	(factory((global.ng = global.ng || {}, global.ng.router = global.ng.router || {}),global.ng.common,global.ng.core,global.Rx,global.Rx,global.Rx.Observable,global.Rx.Observable,global.Rx.Observable.prototype,global.Rx.Observable.prototype,global.Rx.Observable.prototype,global.Rx.Observable.prototype,global.Rx.Observable.prototype,global.Rx.Observable.prototype,global.Rx.Observable.prototype,global.Rx,global.Rx.Observable.prototype,global.Rx.Observable.prototype,global.Rx,global.Rx.Observable,global.Rx.Observable.prototype,global.ng.platformBrowser,global.Rx.Observable.prototype));
  }(this, (function (exports,_angular_common,_angular_core,rxjs_BehaviorSubject,rxjs_Subject,rxjs_observable_from,rxjs_observable_of,rxjs_operator_concatMap,rxjs_operator_every,rxjs_operator_first,rxjs_operator_last,rxjs_operator_map,rxjs_operator_mergeMap,rxjs_operator_reduce,rxjs_Observable,rxjs_operator_catch,rxjs_operator_concatAll,rxjs_util_EmptyError,rxjs_observable_fromPromise,rxjs_operator_mergeAll,_angular_platformBrowser,rxjs_operator_filter) { 'use strict';
  
  /*! *****************************************************************************
  Copyright (c) Microsoft Corporation. All rights reserved.
  Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  this file except in compliance with the License. You may obtain a copy of the
  License at http://www.apache.org/licenses/LICENSE-2.0
  
  THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
  WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
  MERCHANTABLITY OR NON-INFRINGEMENT.
  
  See the Apache Version 2.0 License for specific language governing permissions
  and limitations under the License.
  ***************************************************************************** */
  /* global Reflect, Promise */
  
  var extendStatics = Object.setPrototypeOf ||
      ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
      function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  
  function __extends(d, b) {
      extendStatics(d, b);
      function __() { this.constructor = d; }
      d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  }
  
  /**
   * @license Angular v4.3.4
   * (c) 2010-2017 Google, Inc. https://angular.io/
   * License: MIT
   */
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * \@whatItDoes Represents an event triggered when a navigation starts.
   *
   * \@stable
   */
  var NavigationStart = (function () {
      /**
       * @param {?} id
       * @param {?} url
       */
      function NavigationStart(id, url) {
          this.id = id;
          this.url = url;
      }
      /**
       * \@docsNotRequired
       * @return {?}
       */
      NavigationStart.prototype.toString = function () { return "NavigationStart(id: " + this.id + ", url: '" + this.url + "')"; };
      return NavigationStart;
  }());
  /**
   * \@whatItDoes Represents an event triggered when a navigation ends successfully.
   *
   * \@stable
   */
  var NavigationEnd = (function () {
      /**
       * @param {?} id
       * @param {?} url
       * @param {?} urlAfterRedirects
       */
      function NavigationEnd(id, url, urlAfterRedirects) {
          this.id = id;
          this.url = url;
          this.urlAfterRedirects = urlAfterRedirects;
      }
      /**
       * \@docsNotRequired
       * @return {?}
       */
      NavigationEnd.prototype.toString = function () {
          return "NavigationEnd(id: " + this.id + ", url: '" + this.url + "', urlAfterRedirects: '" + this.urlAfterRedirects + "')";
      };
      return NavigationEnd;
  }());
  /**
   * \@whatItDoes Represents an event triggered when a navigation is canceled.
   *
   * \@stable
   */
  var NavigationCancel = (function () {
      /**
       * @param {?} id
       * @param {?} url
       * @param {?} reason
       */
      function NavigationCancel(id, url, reason) {
          this.id = id;
          this.url = url;
          this.reason = reason;
      }
      /**
       * \@docsNotRequired
       * @return {?}
       */
      NavigationCancel.prototype.toString = function () { return "NavigationCancel(id: " + this.id + ", url: '" + this.url + "')"; };
      return NavigationCancel;
  }());
  /**
   * \@whatItDoes Represents an event triggered when a navigation fails due to an unexpected error.
   *
   * \@stable
   */
  var NavigationError = (function () {
      /**
       * @param {?} id
       * @param {?} url
       * @param {?} error
       */
      function NavigationError(id, url, error) {
          this.id = id;
          this.url = url;
          this.error = error;
      }
      /**
       * \@docsNotRequired
       * @return {?}
       */
      NavigationError.prototype.toString = function () {
          return "NavigationError(id: " + this.id + ", url: '" + this.url + "', error: " + this.error + ")";
      };
      return NavigationError;
  }());
  /**
   * \@whatItDoes Represents an event triggered when routes are recognized.
   *
   * \@stable
   */
  var RoutesRecognized = (function () {
      /**
       * @param {?} id
       * @param {?} url
       * @param {?} urlAfterRedirects
       * @param {?} state
       */
      function RoutesRecognized(id, url, urlAfterRedirects, state) {
          this.id = id;
          this.url = url;
          this.urlAfterRedirects = urlAfterRedirects;
          this.state = state;
      }
      /**
       * \@docsNotRequired
       * @return {?}
       */
      RoutesRecognized.prototype.toString = function () {
          return "RoutesRecognized(id: " + this.id + ", url: '" + this.url + "', urlAfterRedirects: '" + this.urlAfterRedirects + "', state: " + this.state + ")";
      };
      return RoutesRecognized;
  }());
  /**
   * \@whatItDoes Represents an event triggered before lazy loading a route config.
   *
   * \@experimental
   */
  var RouteConfigLoadStart = (function () {
      /**
       * @param {?} route
       */
      function RouteConfigLoadStart(route) {
          this.route = route;
      }
      /**
       * @return {?}
       */
      RouteConfigLoadStart.prototype.toString = function () { return "RouteConfigLoadStart(path: " + this.route.path + ")"; };
      return RouteConfigLoadStart;
  }());
  /**
   * \@whatItDoes Represents an event triggered when a route has been lazy loaded.
   *
   * \@experimental
   */
  var RouteConfigLoadEnd = (function () {
      /**
       * @param {?} route
       */
      function RouteConfigLoadEnd(route) {
          this.route = route;
      }
      /**
       * @return {?}
       */
      RouteConfigLoadEnd.prototype.toString = function () { return "RouteConfigLoadEnd(path: " + this.route.path + ")"; };
      return RouteConfigLoadEnd;
  }());
  /**
   * \@whatItDoes Represents the start of the Guard phase of routing.
   *
   * \@experimental
   */
  var GuardsCheckStart = (function () {
      /**
       * @param {?} id
       * @param {?} url
       * @param {?} urlAfterRedirects
       * @param {?} state
       */
      function GuardsCheckStart(id, url, urlAfterRedirects, state) {
          this.id = id;
          this.url = url;
          this.urlAfterRedirects = urlAfterRedirects;
          this.state = state;
      }
      /**
       * @return {?}
       */
      GuardsCheckStart.prototype.toString = function () {
          return "GuardsCheckStart(id: " + this.id + ", url: '" + this.url + "', urlAfterRedirects: '" + this.urlAfterRedirects + "', state: " + this.state + ")";
      };
      return GuardsCheckStart;
  }());
  /**
   * \@whatItDoes Represents the end of the Guard phase of routing.
   *
   * \@experimental
   */
  var GuardsCheckEnd = (function () {
      /**
       * @param {?} id
       * @param {?} url
       * @param {?} urlAfterRedirects
       * @param {?} state
       * @param {?} shouldActivate
       */
      function GuardsCheckEnd(id, url, urlAfterRedirects, state, shouldActivate) {
          this.id = id;
          this.url = url;
          this.urlAfterRedirects = urlAfterRedirects;
          this.state = state;
          this.shouldActivate = shouldActivate;
      }
      /**
       * @return {?}
       */
      GuardsCheckEnd.prototype.toString = function () {
          return "GuardsCheckEnd(id: " + this.id + ", url: '" + this.url + "', urlAfterRedirects: '" + this.urlAfterRedirects + "', state: " + this.state + ", shouldActivate: " + this.shouldActivate + ")";
      };
      return GuardsCheckEnd;
  }());
  /**
   * \@whatItDoes Represents the start of the Resolve phase of routing. The timing of this
   * event may change, thus it's experimental. In the current iteration it will run
   * in the "resolve" phase whether there's things to resolve or not. In the future this
   * behavior may change to only run when there are things to be resolved.
   *
   * \@experimental
   */
  var ResolveStart = (function () {
      /**
       * @param {?} id
       * @param {?} url
       * @param {?} urlAfterRedirects
       * @param {?} state
       */
      function ResolveStart(id, url, urlAfterRedirects, state) {
          this.id = id;
          this.url = url;
          this.urlAfterRedirects = urlAfterRedirects;
          this.state = state;
      }
      /**
       * @return {?}
       */
      ResolveStart.prototype.toString = function () {
          return "ResolveStart(id: " + this.id + ", url: '" + this.url + "', urlAfterRedirects: '" + this.urlAfterRedirects + "', state: " + this.state + ")";
      };
      return ResolveStart;
  }());
  /**
   * \@whatItDoes Represents the end of the Resolve phase of routing. See note on
   * {\@link ResolveStart} for use of this experimental API.
   *
   * \@experimental
   */
  var ResolveEnd = (function () {
      /**
       * @param {?} id
       * @param {?} url
       * @param {?} urlAfterRedirects
       * @param {?} state
       */
      function ResolveEnd(id, url, urlAfterRedirects, state) {
          this.id = id;
          this.url = url;
          this.urlAfterRedirects = urlAfterRedirects;
          this.state = state;
      }
      /**
       * @return {?}
       */
      ResolveEnd.prototype.toString = function () {
          return "ResolveEnd(id: " + this.id + ", url: '" + this.url + "', urlAfterRedirects: '" + this.urlAfterRedirects + "', state: " + this.state + ")";
      };
      return ResolveEnd;
  }());
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * \@whatItDoes Name of the primary outlet.
   *
   * \@stable
   */
  var PRIMARY_OUTLET = 'primary';
  var ParamsAsMap = (function () {
      /**
       * @param {?} params
       */
      function ParamsAsMap(params) {
          this.params = params || {};
      }
      /**
       * @param {?} name
       * @return {?}
       */
      ParamsAsMap.prototype.has = function (name) { return this.params.hasOwnProperty(name); };
      /**
       * @param {?} name
       * @return {?}
       */
      ParamsAsMap.prototype.get = function (name) {
          if (this.has(name)) {
              var /** @type {?} */ v = this.params[name];
              return Array.isArray(v) ? v[0] : v;
          }
          return null;
      };
      /**
       * @param {?} name
       * @return {?}
       */
      ParamsAsMap.prototype.getAll = function (name) {
          if (this.has(name)) {
              var /** @type {?} */ v = this.params[name];
              return Array.isArray(v) ? v : [v];
          }
          return [];
      };
      Object.defineProperty(ParamsAsMap.prototype, "keys", {
          /**
           * @return {?}
           */
          get: function () { return Object.keys(this.params); },
          enumerable: true,
          configurable: true
      });
      return ParamsAsMap;
  }());
  /**
   * Convert a {\@link Params} instance to a {\@link ParamMap}.
   *
   * \@stable
   * @param {?} params
   * @return {?}
   */
  function convertToParamMap(params) {
      return new ParamsAsMap(params);
  }
  var NAVIGATION_CANCELING_ERROR = 'ngNavigationCancelingError';
  /**
   * @param {?} message
   * @return {?}
   */
  function navigationCancelingError(message) {
      var /** @type {?} */ error = Error('NavigationCancelingError: ' + message);
      ((error))[NAVIGATION_CANCELING_ERROR] = true;
      return error;
  }
  /**
   * @param {?} error
   * @return {?}
   */
  function isNavigationCancelingError(error) {
      return ((error))[NAVIGATION_CANCELING_ERROR];
  }
  /**
   * @param {?} segments
   * @param {?} segmentGroup
   * @param {?} route
   * @return {?}
   */
  function defaultUrlMatcher(segments, segmentGroup, route) {
      var /** @type {?} */ parts = ((route.path)).split('/');
      if (parts.length > segments.length) {
          // The actual URL is shorter than the config, no match
          return null;
      }
      if (route.pathMatch === 'full' &&
          (segmentGroup.hasChildren() || parts.length < segments.length)) {
          // The config is longer than the actual URL but we are looking for a full match, return null
          return null;
      }
      var /** @type {?} */ posParams = {};
      // Check each config part against the actual URL
      for (var /** @type {?} */ index = 0; index < parts.length; index++) {
          var /** @type {?} */ part = parts[index];
          var /** @type {?} */ segment = segments[index];
          var /** @type {?} */ isParameter = part.startsWith(':');
          if (isParameter) {
              posParams[part.substring(1)] = segment;
          }
          else if (part !== segment.path) {
              // The actual URL part does not match the config, no match
              return null;
          }
      }
      return { consumed: segments.slice(0, parts.length), posParams: posParams };
  }
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  var LoadedRouterConfig = (function () {
      /**
       * @param {?} routes
       * @param {?} module
       */
      function LoadedRouterConfig(routes, module) {
          this.routes = routes;
          this.module = module;
      }
      return LoadedRouterConfig;
  }());
  /**
   * @param {?} config
   * @param {?=} parentPath
   * @return {?}
   */
  function validateConfig(config, parentPath) {
      if (parentPath === void 0) { parentPath = ''; }
      // forEach doesn't iterate undefined values
      for (var /** @type {?} */ i = 0; i < config.length; i++) {
          var /** @type {?} */ route = config[i];
          var /** @type {?} */ fullPath = getFullPath(parentPath, route);
          validateNode(route, fullPath);
      }
  }
  /**
   * @param {?} route
   * @param {?} fullPath
   * @return {?}
   */
  function validateNode(route, fullPath) {
      if (!route) {
          throw new Error("\n      Invalid configuration of route '" + fullPath + "': Encountered undefined route.\n      The reason might be an extra comma.\n\n      Example:\n      const routes: Routes = [\n        { path: '', redirectTo: '/dashboard', pathMatch: 'full' },\n        { path: 'dashboard',  component: DashboardComponent },, << two commas\n        { path: 'detail/:id', component: HeroDetailComponent }\n      ];\n    ");
      }
      if (Array.isArray(route)) {
          throw new Error("Invalid configuration of route '" + fullPath + "': Array cannot be specified");
      }
      if (!route.component && (route.outlet && route.outlet !== PRIMARY_OUTLET)) {
          throw new Error("Invalid configuration of route '" + fullPath + "': a componentless route cannot have a named outlet set");
      }
      if (route.redirectTo && route.children) {
          throw new Error("Invalid configuration of route '" + fullPath + "': redirectTo and children cannot be used together");
      }
      if (route.redirectTo && route.loadChildren) {
          throw new Error("Invalid configuration of route '" + fullPath + "': redirectTo and loadChildren cannot be used together");
      }
      if (route.children && route.loadChildren) {
          throw new Error("Invalid configuration of route '" + fullPath + "': children and loadChildren cannot be used together");
      }
      if (route.redirectTo && route.component) {
          throw new Error("Invalid configuration of route '" + fullPath + "': redirectTo and component cannot be used together");
      }
      if (route.path && route.matcher) {
          throw new Error("Invalid configuration of route '" + fullPath + "': path and matcher cannot be used together");
      }
      if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) {
          throw new Error("Invalid configuration of route '" + fullPath + "'. One of the following must be provided: component, redirectTo, children or loadChildren");
      }
      if (route.path === void 0 && route.matcher === void 0) {
          throw new Error("Invalid configuration of route '" + fullPath + "': routes must have either a path or a matcher specified");
      }
      if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
          throw new Error("Invalid configuration of route '" + fullPath + "': path cannot start with a slash");
      }
      if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
          var /** @type {?} */ exp = "The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.";
          throw new Error("Invalid configuration of route '{path: \"" + fullPath + "\", redirectTo: \"" + route.redirectTo + "\"}': please provide 'pathMatch'. " + exp);
      }
      if (route.pathMatch !== void 0 && route.pathMatch !== 'full' && route.pathMatch !== 'prefix') {
          throw new Error("Invalid configuration of route '" + fullPath + "': pathMatch can only be set to 'prefix' or 'full'");
      }
      if (route.children) {
          validateConfig(route.children, fullPath);
      }
  }
  /**
   * @param {?} parentPath
   * @param {?} currentRoute
   * @return {?}
   */
  function getFullPath(parentPath, currentRoute) {
      if (!currentRoute) {
          return parentPath;
      }
      if (!parentPath && !currentRoute.path) {
          return '';
      }
      else if (parentPath && !currentRoute.path) {
          return parentPath + "/";
      }
      else if (!parentPath && currentRoute.path) {
          return currentRoute.path;
      }
      else {
          return parentPath + "/" + currentRoute.path;
      }
  }
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * @param {?} a
   * @param {?} b
   * @return {?}
   */
  function shallowEqualArrays(a, b) {
      if (a.length !== b.length)
          return false;
      for (var /** @type {?} */ i = 0; i < a.length; ++i) {
          if (!shallowEqual(a[i], b[i]))
              return false;
      }
      return true;
  }
  /**
   * @param {?} a
   * @param {?} b
   * @return {?}
   */
  function shallowEqual(a, b) {
      var /** @type {?} */ k1 = Object.keys(a);
      var /** @type {?} */ k2 = Object.keys(b);
      if (k1.length != k2.length) {
          return false;
      }
      var /** @type {?} */ key;
      for (var /** @type {?} */ i = 0; i < k1.length; i++) {
          key = k1[i];
          if (a[key] !== b[key]) {
              return false;
          }
      }
      return true;
  }
  /**
   * @template T
   * @param {?} arr
   * @return {?}
   */
  function flatten(arr) {
      return Array.prototype.concat.apply([], arr);
  }
  /**
   * @template T
   * @param {?} a
   * @return {?}
   */
  function last$1(a) {
      return a.length > 0 ? a[a.length - 1] : null;
  }
  /**
   * @param {?} bools
   * @return {?}
   */
  /**
   * @template K, V
   * @param {?} map
   * @param {?} callback
   * @return {?}
   */
  function forEach(map$$1, callback) {
      for (var /** @type {?} */ prop in map$$1) {
          if (map$$1.hasOwnProperty(prop)) {
              callback(map$$1[prop], prop);
          }
      }
  }
  /**
   * @template A, B
   * @param {?} obj
   * @param {?} fn
   * @return {?}
   */
  function waitForMap(obj, fn) {
      if (Object.keys(obj).length === 0) {
          return rxjs_observable_of.of({});
      }
      var /** @type {?} */ waitHead = [];
      var /** @type {?} */ waitTail = [];
      var /** @type {?} */ res = {};
      forEach(obj, function (a, k) {
          var /** @type {?} */ mapped = rxjs_operator_map.map.call(fn(k, a), function (r) { return res[k] = r; });
          if (k === PRIMARY_OUTLET) {
              waitHead.push(mapped);
          }
          else {
              waitTail.push(mapped);
          }
      });
      var /** @type {?} */ concat$ = rxjs_operator_concatAll.concatAll.call(rxjs_observable_of.of.apply(void 0, waitHead.concat(waitTail)));
      var /** @type {?} */ last$ = rxjs_operator_last.last.call(concat$);
      return rxjs_operator_map.map.call(last$, function () { return res; });
  }
  /**
   * @param {?} observables
   * @return {?}
   */
  function andObservables(observables) {
      var /** @type {?} */ merged$ = rxjs_operator_mergeAll.mergeAll.call(observables);
      return rxjs_operator_every.every.call(merged$, function (result) { return result === true; });
  }
  /**
   * @template T
   * @param {?} value
   * @return {?}
   */
  function wrapIntoObservable(value) {
      if (_angular_core.ɵisObservable(value)) {
          return value;
      }
      if (_angular_core.ɵisPromise(value)) {
          // Use `Promise.resolve()` to wrap promise-like instances.
          // Required ie when a Resolver returns a AngularJS `$q` promise to correctly trigger the
          // change detection.
          return rxjs_observable_fromPromise.fromPromise(Promise.resolve(value));
      }
      return rxjs_observable_of.of(/** @type {?} */ (value));
  }
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * @return {?}
   */
  function createEmptyUrlTree() {
      return new UrlTree(new UrlSegmentGroup([], {}), {}, null);
  }
  /**
   * @param {?} container
   * @param {?} containee
   * @param {?} exact
   * @return {?}
   */
  function containsTree(container, containee, exact) {
      if (exact) {
          return equalQueryParams(container.queryParams, containee.queryParams) &&
              equalSegmentGroups(container.root, containee.root);
      }
      return containsQueryParams(container.queryParams, containee.queryParams) &&
          containsSegmentGroup(container.root, containee.root);
  }
  /**
   * @param {?} container
   * @param {?} containee
   * @return {?}
   */
  function equalQueryParams(container, containee) {
      return shallowEqual(container, containee);
  }
  /**
   * @param {?} container
   * @param {?} containee
   * @return {?}
   */
  function equalSegmentGroups(container, containee) {
      if (!equalPath(container.segments, containee.segments))
          return false;
      if (container.numberOfChildren !== containee.numberOfChildren)
          return false;
      for (var /** @type {?} */ c in containee.children) {
          if (!container.children[c])
              return false;
          if (!equalSegmentGroups(container.children[c], containee.children[c]))
              return false;
      }
      return true;
  }
  /**
   * @param {?} container
   * @param {?} containee
   * @return {?}
   */
  function containsQueryParams(container, containee) {
      return Object.keys(containee).length <= Object.keys(container).length &&
          Object.keys(containee).every(function (key) { return containee[key] === container[key]; });
  }
  /**
   * @param {?} container
   * @param {?} containee
   * @return {?}
   */
  function containsSegmentGroup(container, containee) {
      return containsSegmentGroupHelper(container, containee, containee.segments);
  }
  /**
   * @param {?} container
   * @param {?} containee
   * @param {?} containeePaths
   * @return {?}
   */
  function containsSegmentGroupHelper(container, containee, containeePaths) {
      if (container.segments.length > containeePaths.length) {
          var /** @type {?} */ current = container.segments.slice(0, containeePaths.length);
          if (!equalPath(current, containeePaths))
              return false;
          if (containee.hasChildren())
              return false;
          return true;
      }
      else if (container.segments.length === containeePaths.length) {
          if (!equalPath(container.segments, containeePaths))
              return false;
          for (var /** @type {?} */ c in containee.children) {
              if (!container.children[c])
                  return false;
              if (!containsSegmentGroup(container.children[c], containee.children[c]))
                  return false;
          }
          return true;
      }
      else {
          var /** @type {?} */ current = containeePaths.slice(0, container.segments.length);
          var /** @type {?} */ next = containeePaths.slice(container.segments.length);
          if (!equalPath(container.segments, current))
              return false;
          if (!container.children[PRIMARY_OUTLET])
              return false;
          return containsSegmentGroupHelper(container.children[PRIMARY_OUTLET], containee, next);
      }
  }
  /**
   * \@whatItDoes Represents the parsed URL.
   *
   * \@howToUse
   *
   * ```
   * \@Component({templateUrl:'template.html'})
   * class MyComponent {
   *   constructor(router: Router) {
   *     const tree: UrlTree =
   *       router.parseUrl('/team/33/(user/victor//support:help)?debug=true#fragment');
   *     const f = tree.fragment; // return 'fragment'
   *     const q = tree.queryParams; // returns {debug: 'true'}
   *     const g: UrlSegmentGroup = tree.root.children[PRIMARY_OUTLET];
   *     const s: UrlSegment[] = g.segments; // returns 2 segments 'team' and '33'
   *     g.children[PRIMARY_OUTLET].segments; // returns 2 segments 'user' and 'victor'
   *     g.children['support'].segments; // return 1 segment 'help'
   *   }
   * }
   * ```
   *
   * \@description
   *
   * Since a router state is a tree, and the URL is nothing but a serialized state, the URL is a
   * serialized tree.
   * UrlTree is a data structure that provides a lot of affordances in dealing with URLs
   *
   * \@stable
   */
  var UrlTree = (function () {
      /**
       * \@internal
       * @param {?} root
       * @param {?} queryParams
       * @param {?} fragment
       */
      function UrlTree(root, queryParams, fragment) {
          this.root = root;
          this.queryParams = queryParams;
          this.fragment = fragment;
      }
      Object.defineProperty(UrlTree.prototype, "queryParamMap", {
          /**
           * @return {?}
           */
          get: function () {
              if (!this._queryParamMap) {
                  this._queryParamMap = convertToParamMap(this.queryParams);
              }
              return this._queryParamMap;
          },
          enumerable: true,
          configurable: true
      });
      /**
       * \@docsNotRequired
       * @return {?}
       */
      UrlTree.prototype.toString = function () { return DEFAULT_SERIALIZER.serialize(this); };
      return UrlTree;
  }());
  /**
   * \@whatItDoes Represents the parsed URL segment group.
   *
   * See {\@link UrlTree} for more information.
   *
   * \@stable
   */
  var UrlSegmentGroup = (function () {
      /**
       * @param {?} segments
       * @param {?} children
       */
      function UrlSegmentGroup(segments, children) {
          var _this = this;
          this.segments = segments;
          this.children = children;
          /**
           * The parent node in the url tree
           */
          this.parent = null;
          forEach(children, function (v, k) { return v.parent = _this; });
      }
      /**
       * Whether the segment has child segments
       * @return {?}
       */
      UrlSegmentGroup.prototype.hasChildren = function () { return this.numberOfChildren > 0; };
      Object.defineProperty(UrlSegmentGroup.prototype, "numberOfChildren", {
          /**
           * Number of child segments
           * @return {?}
           */
          get: function () { return Object.keys(this.children).length; },
          enumerable: true,
          configurable: true
      });
      /**
       * \@docsNotRequired
       * @return {?}
       */
      UrlSegmentGroup.prototype.toString = function () { return serializePaths(this); };
      return UrlSegmentGroup;
  }());
  /**
   * \@whatItDoes Represents a single URL segment.
   *
   * \@howToUse
   *
   * ```
   * \@Component({templateUrl:'template.html'})
   * class MyComponent {
   *   constructor(router: Router) {
   *     const tree: UrlTree = router.parseUrl('/team;id=33');
   *     const g: UrlSegmentGroup = tree.root.children[PRIMARY_OUTLET];
   *     const s: UrlSegment[] = g.segments;
   *     s[0].path; // returns 'team'
   *     s[0].parameters; // returns {id: 33}
   *   }
   * }
   * ```
   *
   * \@description
   *
   * A UrlSegment is a part of a URL between the two slashes. It contains a path and the matrix
   * parameters associated with the segment.
   *
   * \@stable
   */
  var UrlSegment = (function () {
      /**
       * @param {?} path
       * @param {?} parameters
       */
      function UrlSegment(path, parameters) {
          this.path = path;
          this.parameters = parameters;
      }
      Object.defineProperty(UrlSegment.prototype, "parameterMap", {
          /**
           * @return {?}
           */
          get: function () {
              if (!this._parameterMap) {
                  this._parameterMap = convertToParamMap(this.parameters);
              }
              return this._parameterMap;
          },
          enumerable: true,
          configurable: true
      });
      /**
       * \@docsNotRequired
       * @return {?}
       */
      UrlSegment.prototype.toString = function () { return serializePath(this); };
      return UrlSegment;
  }());
  /**
   * @param {?} as
   * @param {?} bs
   * @return {?}
   */
  function equalSegments(as, bs) {
      return equalPath(as, bs) && as.every(function (a, i) { return shallowEqual(a.parameters, bs[i].parameters); });
  }
  /**
   * @param {?} as
   * @param {?} bs
   * @return {?}
   */
  function equalPath(as, bs) {
      if (as.length !== bs.length)
          return false;
      return as.every(function (a, i) { return a.path === bs[i].path; });
  }
  /**
   * @template T
   * @param {?} segment
   * @param {?} fn
   * @return {?}
   */
  function mapChildrenIntoArray(segment, fn) {
      var /** @type {?} */ res = [];
      forEach(segment.children, function (child, childOutlet) {
          if (childOutlet === PRIMARY_OUTLET) {
              res = res.concat(fn(child, childOutlet));
          }
      });
      forEach(segment.children, function (child, childOutlet) {
          if (childOutlet !== PRIMARY_OUTLET) {
              res = res.concat(fn(child, childOutlet));
          }
      });
      return res;
  }
  /**
   * \@whatItDoes Serializes and deserializes a URL string into a URL tree.
   *
   * \@description The url serialization strategy is customizable. You can
   * make all URLs case insensitive by providing a custom UrlSerializer.
   *
   * See {\@link DefaultUrlSerializer} for an example of a URL serializer.
   *
   * \@stable
   * @abstract
   */
  var UrlSerializer = (function () {
      function UrlSerializer() {
      }
      /**
       * Parse a url into a {\@link UrlTree}
       * @abstract
       * @param {?} url
       * @return {?}
       */
      UrlSerializer.prototype.parse = function (url) { };
      /**
       * Converts a {\@link UrlTree} into a url
       * @abstract
       * @param {?} tree
       * @return {?}
       */
      UrlSerializer.prototype.serialize = function (tree) { };
      return UrlSerializer;
  }());
  /**
   * \@whatItDoes A default implementation of the {\@link UrlSerializer}.
   *
   * \@description
   *
   * Example URLs:
   *
   * ```
   * /inbox/33(popup:compose)
   * /inbox/33;open=true/messages/44
   * ```
   *
   * DefaultUrlSerializer uses parentheses to serialize secondary segments (e.g., popup:compose), the
   * colon syntax to specify the outlet, and the ';parameter=value' syntax (e.g., open=true) to
   * specify route specific parameters.
   *
   * \@stable
   */
  var DefaultUrlSerializer = (function () {
      function DefaultUrlSerializer() {
      }
      /**
       * Parses a url into a {\@link UrlTree}
       * @param {?} url
       * @return {?}
       */
      DefaultUrlSerializer.prototype.parse = function (url) {
          var /** @type {?} */ p = new UrlParser(url);
          return new UrlTree(p.parseRootSegment(), p.parseQueryParams(), p.parseFragment());
      };
      /**
       * Converts a {\@link UrlTree} into a url
       * @param {?} tree
       * @return {?}
       */
      DefaultUrlSerializer.prototype.serialize = function (tree) {
          var /** @type {?} */ segment = "/" + serializeSegment(tree.root, true);
          var /** @type {?} */ query = serializeQueryParams(tree.queryParams);
          var /** @type {?} */ fragment = typeof tree.fragment === "string" ? "#" + encodeURI(/** @type {?} */ ((tree.fragment))) : '';
          return "" + segment + query + fragment;
      };
      return DefaultUrlSerializer;
  }());
  var DEFAULT_SERIALIZER = new DefaultUrlSerializer();
  /**
   * @param {?} segment
   * @return {?}
   */
  function serializePaths(segment) {
      return segment.segments.map(function (p) { return serializePath(p); }).join('/');
  }
  /**
   * @param {?} segment
   * @param {?} root
   * @return {?}
   */
  function serializeSegment(segment, root) {
      if (!segment.hasChildren()) {
          return serializePaths(segment);
      }
      if (root) {
          var /** @type {?} */ primary = segment.children[PRIMARY_OUTLET] ?
              serializeSegment(segment.children[PRIMARY_OUTLET], false) :
              '';
          var /** @type {?} */ children_1 = [];
          forEach(segment.children, function (v, k) {
              if (k !== PRIMARY_OUTLET) {
                  children_1.push(k + ":" + serializeSegment(v, false));
              }
          });
          return children_1.length > 0 ? primary + "(" + children_1.join('//') + ")" : primary;
      }
      else {
          var /** @type {?} */ children = mapChildrenIntoArray(segment, function (v, k) {
              if (k === PRIMARY_OUTLET) {
                  return [serializeSegment(segment.children[PRIMARY_OUTLET], false)];
              }
              return [k + ":" + serializeSegment(v, false)];
          });
          return serializePaths(segment) + "/(" + children.join('//') + ")";
      }
  }
  /**
   * This method is intended for encoding *key* or *value* parts of query component. We need a custom
   * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
   * encoded per http://tools.ietf.org/html/rfc3986:
   *    query         = *( pchar / "/" / "?" )
   *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "\@"
   *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
   *    pct-encoded   = "%" HEXDIG HEXDIG
   *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
   *                     / "*" / "+" / "," / ";" / "="
   * @param {?} s
   * @return {?}
   */
  function encode(s) {
      return encodeURIComponent(s)
          .replace(/%40/g, '@')
          .replace(/%3A/gi, ':')
          .replace(/%24/g, '$')
          .replace(/%2C/gi, ',')
          .replace(/%3B/gi, ';');
  }
  /**
   * @param {?} s
   * @return {?}
   */
  function decode(s) {
      return decodeURIComponent(s);
  }
  /**
   * @param {?} path
   * @return {?}
   */
  function serializePath(path) {
      return "" + encode(path.path) + serializeParams(path.parameters);
  }
  /**
   * @param {?} params
   * @return {?}
   */
  function serializeParams(params) {
      return Object.keys(params).map(function (key) { return ";" + encode(key) + "=" + encode(params[key]); }).join('');
  }
  /**
   * @param {?} params
   * @return {?}
   */
  function serializeQueryParams(params) {
      var /** @type {?} */ strParams = Object.keys(params).map(function (name) {
          var /** @type {?} */ value = params[name];
          return Array.isArray(value) ? value.map(function (v) { return encode(name) + "=" + encode(v); }).join('&') :
              encode(name) + "=" + encode(value);
      });
      return strParams.length ? "?" + strParams.join("&") : '';
  }
  var SEGMENT_RE = /^[^\/()?;=&#]+/;
  /**
   * @param {?} str
   * @return {?}
   */
  function matchSegments(str) {
      var /** @type {?} */ match = str.match(SEGMENT_RE);
      return match ? match[0] : '';
  }
  var QUERY_PARAM_RE = /^[^=?&#]+/;
  /**
   * @param {?} str
   * @return {?}
   */
  function matchQueryParams(str) {
      var /** @type {?} */ match = str.match(QUERY_PARAM_RE);
      return match ? match[0] : '';
  }
  var QUERY_PARAM_VALUE_RE = /^[^?&#]+/;
  /**
   * @param {?} str
   * @return {?}
   */
  function matchUrlQueryParamValue(str) {
      var /** @type {?} */ match = str.match(QUERY_PARAM_VALUE_RE);
      return match ? match[0] : '';
  }
  var UrlParser = (function () {
      /**
       * @param {?} url
       */
      function UrlParser(url) {
          this.url = url;
          this.remaining = url;
      }
      /**
       * @return {?}
       */
      UrlParser.prototype.parseRootSegment = function () {
          this.consumeOptional('/');
          if (this.remaining === '' || this.peekStartsWith('?') || this.peekStartsWith('#')) {
              return new UrlSegmentGroup([], {});
          }
          // The root segment group never has segments
          return new UrlSegmentGroup([], this.parseChildren());
      };
      /**
       * @return {?}
       */
      UrlParser.prototype.parseQueryParams = function () {
          var /** @type {?} */ params = {};
          if (this.consumeOptional('?')) {
              do {
                  this.parseQueryParam(params);
              } while (this.consumeOptional('&'));
          }
          return params;
      };
      /**
       * @return {?}
       */
      UrlParser.prototype.parseFragment = function () {
          return this.consumeOptional('#') ? decodeURI(this.remaining) : null;
      };
      /**
       * @return {?}
       */
      UrlParser.prototype.parseChildren = function () {
          if (this.remaining === '') {
              return {};
          }
          this.consumeOptional('/');
          var /** @type {?} */ segments = [];
          if (!this.peekStartsWith('(')) {
              segments.push(this.parseSegment());
          }
          while (this.peekStartsWith('/') && !this.peekStartsWith('//') && !this.peekStartsWith('/(')) {
              this.capture('/');
              segments.push(this.parseSegment());
          }
          var /** @type {?} */ children = {};
          if (this.peekStartsWith('/(')) {
              this.capture('/');
              children = this.parseParens(true);
          }
          var /** @type {?} */ res = {};
          if (this.peekStartsWith('(')) {
              res = this.parseParens(false);
          }
          if (segments.length > 0 || Object.keys(children).length > 0) {
              res[PRIMARY_OUTLET] = new UrlSegmentGroup(segments, children);
          }
          return res;
      };
      /**
       * @return {?}
       */
      UrlParser.prototype.parseSegment = function () {
          var /** @type {?} */ path = matchSegments(this.remaining);
          if (path === '' && this.peekStartsWith(';')) {
              throw new Error("Empty path url segment cannot have parameters: '" + this.remaining + "'.");
          }
          this.capture(path);
          return new UrlSegment(decode(path), this.parseMatrixParams());
      };
      /**
       * @return {?}
       */
      UrlParser.prototype.parseMatrixParams = function () {
          var /** @type {?} */ params = {};
          while (this.consumeOptional(';')) {
              this.parseParam(params);
          }
          return params;
      };
      /**
       * @param {?} params
       * @return {?}
       */
      UrlParser.prototype.parseParam = function (params) {
          var /** @type {?} */ key = matchSegments(this.remaining);
          if (!key) {
              return;
          }
          this.capture(key);
          var /** @type {?} */ value = '';
          if (this.consumeOptional('=')) {
              var /** @type {?} */ valueMatch = matchSegments(this.remaining);
              if (valueMatch) {
                  value = valueMatch;
                  this.capture(value);
              }
          }
          params[decode(key)] = decode(value);
      };
      /**
       * @param {?} params
       * @return {?}
       */
      UrlParser.prototype.parseQueryParam = function (params) {
          var /** @type {?} */ key = matchQueryParams(this.remaining);
          if (!key) {
              return;
          }
          this.capture(key);
          var /** @type {?} */ value = '';
          if (this.consumeOptional('=')) {
              var /** @type {?} */ valueMatch = matchUrlQueryParamValue(this.remaining);
              if (valueMatch) {
                  value = valueMatch;
                  this.capture(value);
              }
          }
          var /** @type {?} */ decodedKey = decode(key);
          var /** @type {?} */ decodedVal = decode(value);
          if (params.hasOwnProperty(decodedKey)) {
              // Append to existing values
              var /** @type {?} */ currentVal = params[decodedKey];
              if (!Array.isArray(currentVal)) {
                  currentVal = [currentVal];
                  params[decodedKey] = currentVal;
              }
              currentVal.push(decodedVal);
          }
          else {
              // Create a new value
              params[decodedKey] = decodedVal;
          }
      };
      /**
       * @param {?} allowPrimary
       * @return {?}
       */
      UrlParser.prototype.parseParens = function (allowPrimary) {
          var /** @type {?} */ segments = {};
          this.capture('(');
          while (!this.consumeOptional(')') && this.remaining.length > 0) {
              var /** @type {?} */ path = matchSegments(this.remaining);
              var /** @type {?} */ next = this.remaining[path.length];
              // if is is not one of these characters, then the segment was unescaped
              // or the group was not closed
              if (next !== '/' && next !== ')' && next !== ';') {
                  throw new Error("Cannot parse url '" + this.url + "'");
              }
              var /** @type {?} */ outletName = ((undefined));
              if (path.indexOf(':') > -1) {
                  outletName = path.substr(0, path.indexOf(':'));
                  this.capture(outletName);
                  this.capture(':');
              }
              else if (allowPrimary) {
                  outletName = PRIMARY_OUTLET;
              }
              var /** @type {?} */ children = this.parseChildren();
              segments[outletName] = Object.keys(children).length === 1 ? children[PRIMARY_OUTLET] :
                  new UrlSegmentGroup([], children);
              this.consumeOptional('//');
          }
          return segments;
      };
      /**
       * @param {?} str
       * @return {?}
       */
      UrlParser.prototype.peekStartsWith = function (str) { return this.remaining.startsWith(str); };
      /**
       * @param {?} str
       * @return {?}
       */
      UrlParser.prototype.consumeOptional = function (str) {
          if (this.peekStartsWith(str)) {
              this.remaining = this.remaining.substring(str.length);
              return true;
          }
          return false;
      };
      /**
       * @param {?} str
       * @return {?}
       */
      UrlParser.prototype.capture = function (str) {
          if (!this.consumeOptional(str)) {
              throw new Error("Expected \"" + str + "\".");
          }
      };
      return UrlParser;
  }());
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  var NoMatch = (function () {
      /**
       * @param {?=} segmentGroup
       */
      function NoMatch(segmentGroup) {
          this.segmentGroup = segmentGroup || null;
      }
      return NoMatch;
  }());
  var AbsoluteRedirect = (function () {
      /**
       * @param {?} urlTree
       */
      function AbsoluteRedirect(urlTree) {
          this.urlTree = urlTree;
      }
      return AbsoluteRedirect;
  }());
  /**
   * @param {?} segmentGroup
   * @return {?}
   */
  function noMatch(segmentGroup) {
      return new rxjs_Observable.Observable(function (obs) { return obs.error(new NoMatch(segmentGroup)); });
  }
  /**
   * @param {?} newTree
   * @return {?}
   */
  function absoluteRedirect(newTree) {
      return new rxjs_Observable.Observable(function (obs) { return obs.error(new AbsoluteRedirect(newTree)); });
  }
  /**
   * @param {?} redirectTo
   * @return {?}
   */
  function namedOutletsRedirect(redirectTo) {
      return new rxjs_Observable.Observable(function (obs) { return obs.error(new Error("Only absolute redirects can have named outlets. redirectTo: '" + redirectTo + "'")); });
  }
  /**
   * @param {?} route
   * @return {?}
   */
  function canLoadFails(route) {
      return new rxjs_Observable.Observable(function (obs) { return obs.error(navigationCancelingError("Cannot load children because the guard of the route \"path: '" + route.path + "'\" returned false")); });
  }
  /**
   * Returns the `UrlTree` with the redirection applied.
   *
   * Lazy modules are loaded along the way.
   * @param {?} moduleInjector
   * @param {?} configLoader
   * @param {?} urlSerializer
   * @param {?} urlTree
   * @param {?} config
   * @return {?}
   */
  function applyRedirects(moduleInjector, configLoader, urlSerializer, urlTree, config) {
      return new ApplyRedirects(moduleInjector, configLoader, urlSerializer, urlTree, config).apply();
  }
  var ApplyRedirects = (function () {
      /**
       * @param {?} moduleInjector
       * @param {?} configLoader
       * @param {?} urlSerializer
       * @param {?} urlTree
       * @param {?} config
       */
      function ApplyRedirects(moduleInjector, configLoader, urlSerializer, urlTree, config) {
          this.configLoader = configLoader;
          this.urlSerializer = urlSerializer;
          this.urlTree = urlTree;
          this.config = config;
          this.allowRedirects = true;
          this.ngModule = moduleInjector.get(_angular_core.NgModuleRef);
      }
      /**
       * @return {?}
       */
      ApplyRedirects.prototype.apply = function () {
          var _this = this;
          var /** @type {?} */ expanded$ = this.expandSegmentGroup(this.ngModule, this.config, this.urlTree.root, PRIMARY_OUTLET);
          var /** @type {?} */ urlTrees$ = rxjs_operator_map.map.call(expanded$, function (rootSegmentGroup) { return _this.createUrlTree(rootSegmentGroup, _this.urlTree.queryParams, /** @type {?} */ ((_this.urlTree.fragment))); });
          return rxjs_operator_catch._catch.call(urlTrees$, function (e) {
              if (e instanceof AbsoluteRedirect) {
                  // after an absolute redirect we do not apply any more redirects!
                  _this.allowRedirects = false;
                  // we need to run matching, so we can fetch all lazy-loaded modules
                  return _this.match(e.urlTree);
              }
              if (e instanceof NoMatch) {
                  throw _this.noMatchError(e);
              }
              throw e;
          });
      };
      /**
       * @param {?} tree
       * @return {?}
       */
      ApplyRedirects.prototype.match = function (tree) {
          var _this = this;
          var /** @type {?} */ expanded$ = this.expandSegmentGroup(this.ngModule, this.config, tree.root, PRIMARY_OUTLET);
          var /** @type {?} */ mapped$ = rxjs_operator_map.map.call(expanded$, function (rootSegmentGroup) { return _this.createUrlTree(rootSegmentGroup, tree.queryParams, /** @type {?} */ ((tree.fragment))); });
          return rxjs_operator_catch._catch.call(mapped$, function (e) {
              if (e instanceof NoMatch) {
                  throw _this.noMatchError(e);
              }
              throw e;
          });
      };
      /**
       * @param {?} e
       * @return {?}
       */
      ApplyRedirects.prototype.noMatchError = function (e) {
          return new Error("Cannot match any routes. URL Segment: '" + e.segmentGroup + "'");
      };
      /**
       * @param {?} rootCandidate
       * @param {?} queryParams
       * @param {?} fragment
       * @return {?}
       */
      ApplyRedirects.prototype.createUrlTree = function (rootCandidate, queryParams, fragment) {
          var /** @type {?} */ root = rootCandidate.segments.length > 0 ?
              new UrlSegmentGroup([], (_a = {}, _a[PRIMARY_OUTLET] = rootCandidate, _a)) :
              rootCandidate;
          return new UrlTree(root, queryParams, fragment);
          var _a;
      };
      /**
       * @param {?} ngModule
       * @param {?} routes
       * @param {?} segmentGroup
       * @param {?} outlet
       * @return {?}
       */
      ApplyRedirects.prototype.expandSegmentGroup = function (ngModule, routes, segmentGroup, outlet) {
          if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
              return rxjs_operator_map.map.call(this.expandChildren(ngModule, routes, segmentGroup), function (children) { return new UrlSegmentGroup([], children); });
          }
          return this.expandSegment(ngModule, segmentGroup, routes, segmentGroup.segments, outlet, true);
      };
      /**
       * @param {?} ngModule
       * @param {?} routes
       * @param {?} segmentGroup
       * @return {?}
       */
      ApplyRedirects.prototype.expandChildren = function (ngModule, routes, segmentGroup) {
          var _this = this;
          return waitForMap(segmentGroup.children, function (childOutlet, child) { return _this.expandSegmentGroup(ngModule, routes, child, childOutlet); });
      };
      /**
       * @param {?} ngModule
       * @param {?} segmentGroup
       * @param {?} routes
       * @param {?} segments
       * @param {?} outlet
       * @param {?} allowRedirects
       * @return {?}
       */
      ApplyRedirects.prototype.expandSegment = function (ngModule, segmentGroup, routes, segments, outlet, allowRedirects) {
          var _this = this;
          var /** @type {?} */ routes$ = rxjs_observable_of.of.apply(void 0, routes);
          var /** @type {?} */ processedRoutes$ = rxjs_operator_map.map.call(routes$, function (r) {
              var /** @type {?} */ expanded$ = _this.expandSegmentAgainstRoute(ngModule, segmentGroup, routes, r, segments, outlet, allowRedirects);
              return rxjs_operator_catch._catch.call(expanded$, function (e) {
                  if (e instanceof NoMatch) {
                      return rxjs_observable_of.of(null);
                  }
                  throw e;
              });
          });
          var /** @type {?} */ concattedProcessedRoutes$ = rxjs_operator_concatAll.concatAll.call(processedRoutes$);
          var /** @type {?} */ first$ = rxjs_operator_first.first.call(concattedProcessedRoutes$, function (s) { return !!s; });
          return rxjs_operator_catch._catch.call(first$, function (e, _) {
              if (e instanceof rxjs_util_EmptyError.EmptyError) {
                  if (_this.noLeftoversInUrl(segmentGroup, segments, outlet)) {
                      return rxjs_observable_of.of(new UrlSegmentGroup([], {}));
                  }
                  throw new NoMatch(segmentGroup);
              }
              throw e;
          });
      };
      /**
       * @param {?} segmentGroup
       * @param {?} segments
       * @param {?} outlet
       * @return {?}
       */
      ApplyRedirects.prototype.noLeftoversInUrl = function (segmentGroup, segments, outlet) {
          return segments.length === 0 && !segmentGroup.children[outlet];
      };
      /**
       * @param {?} ngModule
       * @param {?} segmentGroup
       * @param {?} routes
       * @param {?} route
       * @param {?} paths
       * @param {?} outlet
       * @param {?} allowRedirects
       * @return {?}
       */
      ApplyRedirects.prototype.expandSegmentAgainstRoute = function (ngModule, segmentGroup, routes, route, paths, outlet, allowRedirects) {
          if (getOutlet(route) !== outlet) {
              return noMatch(segmentGroup);
          }
          if (route.redirectTo === undefined) {
              return this.matchSegmentAgainstRoute(ngModule, segmentGroup, route, paths);
          }
          if (allowRedirects && this.allowRedirects) {
              return this.expandSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, paths, outlet);
          }
          return noMatch(segmentGroup);
      };
      /**
       * @param {?} ngModule
       * @param {?} segmentGroup
       * @param {?} routes
       * @param {?} route
       * @param {?} segments
       * @param {?} outlet
       * @return {?}
       */
      ApplyRedirects.prototype.expandSegmentAgainstRouteUsingRedirect = function (ngModule, segmentGroup, routes, route, segments, outlet) {
          if (route.path === '**') {
              return this.expandWildCardWithParamsAgainstRouteUsingRedirect(ngModule, routes, route, outlet);
          }
          return this.expandRegularSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet);
      };
      /**
       * @param {?} ngModule
       * @param {?} routes
       * @param {?} route
       * @param {?} outlet
       * @return {?}
       */
      ApplyRedirects.prototype.expandWildCardWithParamsAgainstRouteUsingRedirect = function (ngModule, routes, route, outlet) {
          var _this = this;
          var /** @type {?} */ newTree = this.applyRedirectCommands([], /** @type {?} */ ((route.redirectTo)), {});
          if (((route.redirectTo)).startsWith('/')) {
              return absoluteRedirect(newTree);
          }
          return rxjs_operator_mergeMap.mergeMap.call(this.lineralizeSegments(route, newTree), function (newSegments) {
              var /** @type {?} */ group = new UrlSegmentGroup(newSegments, {});
              return _this.expandSegment(ngModule, group, routes, newSegments, outlet, false);
          });
      };
      /**
       * @param {?} ngModule
       * @param {?} segmentGroup
       * @param {?} routes
       * @param {?} route
       * @param {?} segments
       * @param {?} outlet
       * @return {?}
       */
      ApplyRedirects.prototype.expandRegularSegmentAgainstRouteUsingRedirect = function (ngModule, segmentGroup, routes, route, segments, outlet) {
          var _this = this;
          var _a = match(segmentGroup, route, segments), matched = _a.matched, consumedSegments = _a.consumedSegments, lastChild = _a.lastChild, positionalParamSegments = _a.positionalParamSegments;
          if (!matched)
              return noMatch(segmentGroup);
          var /** @type {?} */ newTree = this.applyRedirectCommands(consumedSegments, /** @type {?} */ ((route.redirectTo)), /** @type {?} */ (positionalParamSegments));
          if (((route.redirectTo)).startsWith('/')) {
              return absoluteRedirect(newTree);
          }
          return rxjs_operator_mergeMap.mergeMap.call(this.lineralizeSegments(route, newTree), function (newSegments) {
              return _this.expandSegment(ngModule, segmentGroup, routes, newSegments.concat(segments.slice(lastChild)), outlet, false);
          });
      };
      /**
       * @param {?} ngModule
       * @param {?} rawSegmentGroup
       * @param {?} route
       * @param {?} segments
       * @return {?}
       */
      ApplyRedirects.prototype.matchSegmentAgainstRoute = function (ngModule, rawSegmentGroup, route, segments) {
          var _this = this;
          if (route.path === '**') {
              if (route.loadChildren) {
                  return rxjs_operator_map.map.call(this.configLoader.load(ngModule.injector, route), function (cfg) {
                      route._loadedConfig = cfg;
                      return new UrlSegmentGroup(segments, {});
                  });
              }
              return rxjs_observable_of.of(new UrlSegmentGroup(segments, {}));
          }
          var _a = match(rawSegmentGroup, route, segments), matched = _a.matched, consumedSegments = _a.consumedSegments, lastChild = _a.lastChild;
          if (!matched)
              return noMatch(rawSegmentGroup);
          var /** @type {?} */ rawSlicedSegments = segments.slice(lastChild);
          var /** @type {?} */ childConfig$ = this.getChildConfig(ngModule, route);
          return rxjs_operator_mergeMap.mergeMap.call(childConfig$, function (routerConfig) {
              var /** @type {?} */ childModule = routerConfig.module;
              var /** @type {?} */ childConfig = routerConfig.routes;
              var _a = split(rawSegmentGroup, consumedSegments, rawSlicedSegments, childConfig), segmentGroup = _a.segmentGroup, slicedSegments = _a.slicedSegments;
              if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
                  var /** @type {?} */ expanded$_1 = _this.expandChildren(childModule, childConfig, segmentGroup);
                  return rxjs_operator_map.map.call(expanded$_1, function (children) { return new UrlSegmentGroup(consumedSegments, children); });
              }
              if (childConfig.length === 0 && slicedSegments.length === 0) {
                  return rxjs_observable_of.of(new UrlSegmentGroup(consumedSegments, {}));
              }
              var /** @type {?} */ expanded$ = _this.expandSegment(childModule, segmentGroup, childConfig, slicedSegments, PRIMARY_OUTLET, true);
              return rxjs_operator_map.map.call(expanded$, function (cs) { return new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children); });
          });
      };
      /**
       * @param {?} ngModule
       * @param {?} route
       * @return {?}
       */
      ApplyRedirects.prototype.getChildConfig = function (ngModule, route) {
          var _this = this;
          if (route.children) {
              // The children belong to the same module
              return rxjs_observable_of.of(new LoadedRouterConfig(route.children, ngModule));
          }
          if (route.loadChildren) {
              // lazy children belong to the loaded module
              if (route._loadedConfig !== undefined) {
                  return rxjs_observable_of.of(route._loadedConfig);
              }
              return rxjs_operator_mergeMap.mergeMap.call(runCanLoadGuard(ngModule.injector, route), function (shouldLoad) {
                  if (shouldLoad) {
                      return rxjs_operator_map.map.call(_this.configLoader.load(ngModule.injector, route), function (cfg) {
                          route._loadedConfig = cfg;
                          return cfg;
                      });
                  }
                  return canLoadFails(route);
              });
          }
          return rxjs_observable_of.of(new LoadedRouterConfig([], ngModule));
      };
      /**
       * @param {?} route
       * @param {?} urlTree
       * @return {?}
       */
      ApplyRedirects.prototype.lineralizeSegments = function (route, urlTree) {
          var /** @type {?} */ res = [];
          var /** @type {?} */ c = urlTree.root;
          while (true) {
              res = res.concat(c.segments);
              if (c.numberOfChildren === 0) {
                  return rxjs_observable_of.of(res);
              }
              if (c.numberOfChildren > 1 || !c.children[PRIMARY_OUTLET]) {
                  return namedOutletsRedirect(/** @type {?} */ ((route.redirectTo)));
              }
              c = c.children[PRIMARY_OUTLET];
          }
      };
      /**
       * @param {?} segments
       * @param {?} redirectTo
       * @param {?} posParams
       * @return {?}
       */
      ApplyRedirects.prototype.applyRedirectCommands = function (segments, redirectTo, posParams) {
          return this.applyRedirectCreatreUrlTree(redirectTo, this.urlSerializer.parse(redirectTo), segments, posParams);
      };
      /**
       * @param {?} redirectTo
       * @param {?} urlTree
       * @param {?} segments
       * @param {?} posParams
       * @return {?}
       */
      ApplyRedirects.prototype.applyRedirectCreatreUrlTree = function (redirectTo, urlTree, segments, posParams) {
          var /** @type {?} */ newRoot = this.createSegmentGroup(redirectTo, urlTree.root, segments, posParams);
          return new UrlTree(newRoot, this.createQueryParams(urlTree.queryParams, this.urlTree.queryParams), urlTree.fragment);
      };
      /**
       * @param {?} redirectToParams
       * @param {?} actualParams
       * @return {?}
       */
      ApplyRedirects.prototype.createQueryParams = function (redirectToParams, actualParams) {
          var /** @type {?} */ res = {};
          forEach(redirectToParams, function (v, k) {
              var /** @type {?} */ copySourceValue = typeof v === 'string' && v.startsWith(':');
              if (copySourceValue) {
                  var /** @type {?} */ sourceName = v.substring(1);
                  res[k] = actualParams[sourceName];
              }
              else {
                  res[k] = v;
              }
          });
          return res;
      };
      /**
       * @param {?} redirectTo
       * @param {?} group
       * @param {?} segments
       * @param {?} posParams
       * @return {?}
       */
      ApplyRedirects.prototype.createSegmentGroup = function (redirectTo, group, segments, posParams) {
          var _this = this;
          var /** @type {?} */ updatedSegments = this.createSegments(redirectTo, group.segments, segments, posParams);
          var /** @type {?} */ children = {};
          forEach(group.children, function (child, name) {
              children[name] = _this.createSegmentGroup(redirectTo, child, segments, posParams);
          });
          return new UrlSegmentGroup(updatedSegments, children);
      };
      /**
       * @param {?} redirectTo
       * @param {?} redirectToSegments
       * @param {?} actualSegments
       * @param {?} posParams
       * @return {?}
       */
      ApplyRedirects.prototype.createSegments = function (redirectTo, redirectToSegments, actualSegments, posParams) {
          var _this = this;
          return redirectToSegments.map(function (s) { return s.path.startsWith(':') ? _this.findPosParam(redirectTo, s, posParams) :
              _this.findOrReturn(s, actualSegments); });
      };
      /**
       * @param {?} redirectTo
       * @param {?} redirectToUrlSegment
       * @param {?} posParams
       * @return {?}
       */
      ApplyRedirects.prototype.findPosParam = function (redirectTo, redirectToUrlSegment, posParams) {
          var /** @type {?} */ pos = posParams[redirectToUrlSegment.path.substring(1)];
          if (!pos)
              throw new Error("Cannot redirect to '" + redirectTo + "'. Cannot find '" + redirectToUrlSegment.path + "'.");
          return pos;
      };
      /**
       * @param {?} redirectToUrlSegment
       * @param {?} actualSegments
       * @return {?}
       */
      ApplyRedirects.prototype.findOrReturn = function (redirectToUrlSegment, actualSegments) {
          var /** @type {?} */ idx = 0;
          for (var _i = 0, actualSegments_1 = actualSegments; _i < actualSegments_1.length; _i++) {
              var s = actualSegments_1[_i];
              if (s.path === redirectToUrlSegment.path) {
                  actualSegments.splice(idx);
                  return s;
              }
              idx++;
          }
          return redirectToUrlSegment;
      };
      return ApplyRedirects;
  }());
  /**
   * @param {?} moduleInjector
   * @param {?} route
   * @return {?}
   */
  function runCanLoadGuard(moduleInjector, route) {
      var /** @type {?} */ canLoad = route.canLoad;
      if (!canLoad || canLoad.length === 0)
          return rxjs_observable_of.of(true);
      var /** @type {?} */ obs = rxjs_operator_map.map.call(rxjs_observable_from.from(canLoad), function (injectionToken) {
          var /** @type {?} */ guard = moduleInjector.get(injectionToken);
          return wrapIntoObservable(guard.canLoad ? guard.canLoad(route) : guard(route));
      });
      return andObservables(obs);
  }
  /**
   * @param {?} segmentGroup
   * @param {?} route
   * @param {?} segments
   * @return {?}
   */
  function match(segmentGroup, route, segments) {
      if (route.path === '') {
          if ((route.pathMatch === 'full') && (segmentGroup.hasChildren() || segments.length > 0)) {
              return { matched: false, consumedSegments: [], lastChild: 0, positionalParamSegments: {} };
          }
          return { matched: true, consumedSegments: [], lastChild: 0, positionalParamSegments: {} };
      }
      var /** @type {?} */ matcher = route.matcher || defaultUrlMatcher;
      var /** @type {?} */ res = matcher(segments, segmentGroup, route);
      if (!res) {
          return {
              matched: false,
              consumedSegments: /** @type {?} */ ([]),
              lastChild: 0,
              positionalParamSegments: {},
          };
      }
      return {
          matched: true,
          consumedSegments: /** @type {?} */ ((res.consumed)),
          lastChild: /** @type {?} */ ((res.consumed.length)),
          positionalParamSegments: /** @type {?} */ ((res.posParams)),
      };
  }
  /**
   * @param {?} segmentGroup
   * @param {?} consumedSegments
   * @param {?} slicedSegments
   * @param {?} config
   * @return {?}
   */
  function split(segmentGroup, consumedSegments, slicedSegments, config) {
      if (slicedSegments.length > 0 &&
          containsEmptyPathRedirectsWithNamedOutlets(segmentGroup, slicedSegments, config)) {
          var /** @type {?} */ s = new UrlSegmentGroup(consumedSegments, createChildrenForEmptySegments(config, new UrlSegmentGroup(slicedSegments, segmentGroup.children)));
          return { segmentGroup: mergeTrivialChildren(s), slicedSegments: [] };
      }
      if (slicedSegments.length === 0 &&
          containsEmptyPathRedirects(segmentGroup, slicedSegments, config)) {
          var /** @type {?} */ s = new UrlSegmentGroup(segmentGroup.segments, addEmptySegmentsToChildrenIfNeeded(segmentGroup, slicedSegments, config, segmentGroup.children));
          return { segmentGroup: mergeTrivialChildren(s), slicedSegments: slicedSegments };
      }
      return { segmentGroup: segmentGroup, slicedSegments: slicedSegments };
  }
  /**
   * @param {?} s
   * @return {?}
   */
  function mergeTrivialChildren(s) {
      if (s.numberOfChildren === 1 && s.children[PRIMARY_OUTLET]) {
          var /** @type {?} */ c = s.children[PRIMARY_OUTLET];
          return new UrlSegmentGroup(s.segments.concat(c.segments), c.children);
      }
      return s;
  }
  /**
   * @param {?} segmentGroup
   * @param {?} slicedSegments
   * @param {?} routes
   * @param {?} children
   * @return {?}
   */
  function addEmptySegmentsToChildrenIfNeeded(segmentGroup, slicedSegments, routes, children) {
      var /** @type {?} */ res = {};
      for (var _i = 0, routes_1 = routes; _i < routes_1.length; _i++) {
          var r = routes_1[_i];
          if (isEmptyPathRedirect(segmentGroup, slicedSegments, r) && !children[getOutlet(r)]) {
              res[getOutlet(r)] = new UrlSegmentGroup([], {});
          }
      }
      return Object.assign({}, children, res);
  }
  /**
   * @param {?} routes
   * @param {?} primarySegmentGroup
   * @return {?}
   */
  function createChildrenForEmptySegments(routes, primarySegmentGroup) {
      var /** @type {?} */ res = {};
      res[PRIMARY_OUTLET] = primarySegmentGroup;
      for (var _i = 0, routes_2 = routes; _i < routes_2.length; _i++) {
          var r = routes_2[_i];
          if (r.path === '' && getOutlet(r) !== PRIMARY_OUTLET) {
              res[getOutlet(r)] = new UrlSegmentGroup([], {});
          }
      }
      return res;
  }
  /**
   * @param {?} segmentGroup
   * @param {?} segments
   * @param {?} routes
   * @return {?}
   */
  function containsEmptyPathRedirectsWithNamedOutlets(segmentGroup, segments, routes) {
      return routes.some(function (r) { return isEmptyPathRedirect(segmentGroup, segments, r) && getOutlet(r) !== PRIMARY_OUTLET; });
  }
  /**
   * @param {?} segmentGroup
   * @param {?} segments
   * @param {?} routes
   * @return {?}
   */
  function containsEmptyPathRedirects(segmentGroup, segments, routes) {
      return routes.some(function (r) { return isEmptyPathRedirect(segmentGroup, segments, r); });
  }
  /**
   * @param {?} segmentGroup
   * @param {?} segments
   * @param {?} r
   * @return {?}
   */
  function isEmptyPathRedirect(segmentGroup, segments, r) {
      if ((segmentGroup.hasChildren() || segments.length > 0) && r.pathMatch === 'full') {
          return false;
      }
      return r.path === '' && r.redirectTo !== undefined;
  }
  /**
   * @param {?} route
   * @return {?}
   */
  function getOutlet(route) {
      return route.outlet || PRIMARY_OUTLET;
  }
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  var Tree = (function () {
      /**
       * @param {?} root
       */
      function Tree(root) {
          this._root = root;
      }
      Object.defineProperty(Tree.prototype, "root", {
          /**
           * @return {?}
           */
          get: function () { return this._root.value; },
          enumerable: true,
          configurable: true
      });
      /**
       * \@internal
       * @param {?} t
       * @return {?}
       */
      Tree.prototype.parent = function (t) {
          var /** @type {?} */ p = this.pathFromRoot(t);
          return p.length > 1 ? p[p.length - 2] : null;
      };
      /**
       * \@internal
       * @param {?} t
       * @return {?}
       */
      Tree.prototype.children = function (t) {
          var /** @type {?} */ n = findNode(t, this._root);
          return n ? n.children.map(function (t) { return t.value; }) : [];
      };
      /**
       * \@internal
       * @param {?} t
       * @return {?}
       */
      Tree.prototype.firstChild = function (t) {
          var /** @type {?} */ n = findNode(t, this._root);
          return n && n.children.length > 0 ? n.children[0].value : null;
      };
      /**
       * \@internal
       * @param {?} t
       * @return {?}
       */
      Tree.prototype.siblings = function (t) {
          var /** @type {?} */ p = findPath(t, this._root);
          if (p.length < 2)
              return [];
          var /** @type {?} */ c = p[p.length - 2].children.map(function (c) { return c.value; });
          return c.filter(function (cc) { return cc !== t; });
      };
      /**
       * \@internal
       * @param {?} t
       * @return {?}
       */
      Tree.prototype.pathFromRoot = function (t) { return findPath(t, this._root).map(function (s) { return s.value; }); };
      return Tree;
  }());
  /**
   * @template T
   * @param {?} value
   * @param {?} node
   * @return {?}
   */
  function findNode(value, node) {
      if (value === node.value)
          return node;
      for (var _i = 0, _a = node.children; _i < _a.length; _i++) {
          var child = _a[_i];
          var /** @type {?} */ node_1 = findNode(value, child);
          if (node_1)
              return node_1;
      }
      return null;
  }
  /**
   * @template T
   * @param {?} value
   * @param {?} node
   * @return {?}
   */
  function findPath(value, node) {
      if (value === node.value)
          return [node];
      for (var _i = 0, _a = node.children; _i < _a.length; _i++) {
          var child = _a[_i];
          var /** @type {?} */ path = findPath(value, child);
          if (path.length) {
              path.unshift(node);
              return path;
          }
      }
      return [];
  }
  var TreeNode = (function () {
      /**
       * @param {?} value
       * @param {?} children
       */
      function TreeNode(value, children) {
          this.value = value;
          this.children = children;
      }
      /**
       * @return {?}
       */
      TreeNode.prototype.toString = function () { return "TreeNode(" + this.value + ")"; };
      return TreeNode;
  }());
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * \@whatItDoes Represents the state of the router.
   *
   * \@howToUse
   *
   * ```
   * \@Component({templateUrl:'template.html'})
   * class MyComponent {
   *   constructor(router: Router) {
   *     const state: RouterState = router.routerState;
   *     const root: ActivatedRoute = state.root;
   *     const child = root.firstChild;
   *     const id: Observable<string> = child.params.map(p => p.id);
   *     //...
   *   }
   * }
   * ```
   *
   * \@description
   * RouterState is a tree of activated routes. Every node in this tree knows about the "consumed" URL
   * segments, the extracted parameters, and the resolved data.
   *
   * See {\@link ActivatedRoute} for more information.
   *
   * \@stable
   */
  var RouterState = (function (_super) {
      __extends(RouterState, _super);
      /**
       * \@internal
       * @param {?} root
       * @param {?} snapshot
       */
      function RouterState(root, snapshot) {
          var _this = _super.call(this, root) || this;
          _this.snapshot = snapshot;
          setRouterState(_this, root);
          return _this;
      }
      /**
       * @return {?}
       */
      RouterState.prototype.toString = function () { return this.snapshot.toString(); };
      return RouterState;
  }(Tree));
  /**
   * @param {?} urlTree
   * @param {?} rootComponent
   * @return {?}
   */
  function createEmptyState(urlTree, rootComponent) {
      var /** @type {?} */ snapshot = createEmptyStateSnapshot(urlTree, rootComponent);
      var /** @type {?} */ emptyUrl = new rxjs_BehaviorSubject.BehaviorSubject([new UrlSegment('', {})]);
      var /** @type {?} */ emptyParams = new rxjs_BehaviorSubject.BehaviorSubject({});
      var /** @type {?} */ emptyData = new rxjs_BehaviorSubject.BehaviorSubject({});
      var /** @type {?} */ emptyQueryParams = new rxjs_BehaviorSubject.BehaviorSubject({});
      var /** @type {?} */ fragment = new rxjs_BehaviorSubject.BehaviorSubject('');
      var /** @type {?} */ activated = new ActivatedRoute(emptyUrl, emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, snapshot.root);
      activated.snapshot = snapshot.root;
      return new RouterState(new TreeNode(activated, []), snapshot);
  }
  /**
   * @param {?} urlTree
   * @param {?} rootComponent
   * @return {?}
   */
  function createEmptyStateSnapshot(urlTree, rootComponent) {
      var /** @type {?} */ emptyParams = {};
      var /** @type {?} */ emptyData = {};
      var /** @type {?} */ emptyQueryParams = {};
      var /** @type {?} */ fragment = '';
      var /** @type {?} */ activated = new ActivatedRouteSnapshot([], emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, null, urlTree.root, -1, {});
      return new RouterStateSnapshot('', new TreeNode(activated, []));
  }
  /**
   * \@whatItDoes Contains the information about a route associated with a component loaded in an
   * outlet.
   * An `ActivatedRoute` can also be used to traverse the router state tree.
   *
   * \@howToUse
   *
   * ```
   * \@Component({...})
   * class MyComponent {
   *   constructor(route: ActivatedRoute) {
   *     const id: Observable<string> = route.params.map(p => p.id);
   *     const url: Observable<string> = route.url.map(segments => segments.join(''));
   *     // route.data includes both `data` and `resolve`
   *     const user = route.data.map(d => d.user);
   *   }
   * }
   * ```
   *
   * \@stable
   */
  var ActivatedRoute = (function () {
      /**
       * \@internal
       * @param {?} url
       * @param {?} params
       * @param {?} queryParams
       * @param {?} fragment
       * @param {?} data
       * @param {?} outlet
       * @param {?} component
       * @param {?} futureSnapshot
       */
      function ActivatedRoute(url, params, queryParams, fragment, data, outlet, component, futureSnapshot) {
          this.url = url;
          this.params = params;
          this.queryParams = queryParams;
          this.fragment = fragment;
          this.data = data;
          this.outlet = outlet;
          this.component = component;
          this._futureSnapshot = futureSnapshot;
      }
      Object.defineProperty(ActivatedRoute.prototype, "routeConfig", {
          /**
           * The configuration used to match this route
           * @return {?}
           */
          get: function () { return this._futureSnapshot.routeConfig; },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ActivatedRoute.prototype, "root", {
          /**
           * The root of the router state
           * @return {?}
           */
          get: function () { return this._routerState.root; },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ActivatedRoute.prototype, "parent", {
          /**
           * The parent of this route in the router state tree
           * @return {?}
           */
          get: function () { return this._routerState.parent(this); },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ActivatedRoute.prototype, "firstChild", {
          /**
           * The first child of this route in the router state tree
           * @return {?}
           */
          get: function () { return this._routerState.firstChild(this); },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ActivatedRoute.prototype, "children", {
          /**
           * The children of this route in the router state tree
           * @return {?}
           */
          get: function () { return this._routerState.children(this); },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ActivatedRoute.prototype, "pathFromRoot", {
          /**
           * The path from the root of the router state tree to this route
           * @return {?}
           */
          get: function () { return this._routerState.pathFromRoot(this); },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ActivatedRoute.prototype, "paramMap", {
          /**
           * @return {?}
           */
          get: function () {
              if (!this._paramMap) {
                  this._paramMap = rxjs_operator_map.map.call(this.params, function (p) { return convertToParamMap(p); });
              }
              return this._paramMap;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ActivatedRoute.prototype, "queryParamMap", {
          /**
           * @return {?}
           */
          get: function () {
              if (!this._queryParamMap) {
                  this._queryParamMap =
                      rxjs_operator_map.map.call(this.queryParams, function (p) { return convertToParamMap(p); });
              }
              return this._queryParamMap;
          },
          enumerable: true,
          configurable: true
      });
      /**
       * @return {?}
       */
      ActivatedRoute.prototype.toString = function () {
          return this.snapshot ? this.snapshot.toString() : "Future(" + this._futureSnapshot + ")";
      };
      return ActivatedRoute;
  }());
  /**
   * \@internal
   * @param {?} route
   * @return {?}
   */
  function inheritedParamsDataResolve(route) {
      var /** @type {?} */ pathToRoot = route.pathFromRoot;
      var /** @type {?} */ inhertingStartingFrom = pathToRoot.length - 1;
      while (inhertingStartingFrom >= 1) {
          var /** @type {?} */ current = pathToRoot[inhertingStartingFrom];
          var /** @type {?} */ parent = pathToRoot[inhertingStartingFrom - 1];
          // current route is an empty path => inherits its parent's params and data
          if (current.routeConfig && current.routeConfig.path === '') {
              inhertingStartingFrom--;
              // parent is componentless => current route should inherit its params and data
          }
          else if (!parent.component) {
              inhertingStartingFrom--;
          }
          else {
              break;
          }
      }
      return pathToRoot.slice(inhertingStartingFrom).reduce(function (res, curr) {
          var /** @type {?} */ params = Object.assign({}, res.params, curr.params);
          var /** @type {?} */ data = Object.assign({}, res.data, curr.data);
          var /** @type {?} */ resolve = Object.assign({}, res.resolve, curr._resolvedData);
          return { params: params, data: data, resolve: resolve };
      }, /** @type {?} */ ({ params: {}, data: {}, resolve: {} }));
  }
  /**
   * \@whatItDoes Contains the information about a route associated with a component loaded in an
   * outlet
   * at a particular moment in time. ActivatedRouteSnapshot can also be used to traverse the router
   * state tree.
   *
   * \@howToUse
   *
   * ```
   * \@Component({templateUrl:'./my-component.html'})
   * class MyComponent {
   *   constructor(route: ActivatedRoute) {
   *     const id: string = route.snapshot.params.id;
   *     const url: string = route.snapshot.url.join('');
   *     const user = route.snapshot.data.user;
   *   }
   * }
   * ```
   *
   * \@stable
   */
  var ActivatedRouteSnapshot = (function () {
      /**
       * \@internal
       * @param {?} url
       * @param {?} params
       * @param {?} queryParams
       * @param {?} fragment
       * @param {?} data
       * @param {?} outlet
       * @param {?} component
       * @param {?} routeConfig
       * @param {?} urlSegment
       * @param {?} lastPathIndex
       * @param {?} resolve
       */
      function ActivatedRouteSnapshot(url, params, queryParams, fragment, data, outlet, component, routeConfig, urlSegment, lastPathIndex, resolve) {
          this.url = url;
          this.params = params;
          this.queryParams = queryParams;
          this.fragment = fragment;
          this.data = data;
          this.outlet = outlet;
          this.component = component;
          this._routeConfig = routeConfig;
          this._urlSegment = urlSegment;
          this._lastPathIndex = lastPathIndex;
          this._resolve = resolve;
      }
      Object.defineProperty(ActivatedRouteSnapshot.prototype, "routeConfig", {
          /**
           * The configuration used to match this route
           * @return {?}
           */
          get: function () { return this._routeConfig; },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ActivatedRouteSnapshot.prototype, "root", {
          /**
           * The root of the router state
           * @return {?}
           */
          get: function () { return this._routerState.root; },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ActivatedRouteSnapshot.prototype, "parent", {
          /**
           * The parent of this route in the router state tree
           * @return {?}
           */
          get: function () { return this._routerState.parent(this); },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ActivatedRouteSnapshot.prototype, "firstChild", {
          /**
           * The first child of this route in the router state tree
           * @return {?}
           */
          get: function () { return this._routerState.firstChild(this); },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ActivatedRouteSnapshot.prototype, "children", {
          /**
           * The children of this route in the router state tree
           * @return {?}
           */
          get: function () { return this._routerState.children(this); },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ActivatedRouteSnapshot.prototype, "pathFromRoot", {
          /**
           * The path from the root of the router state tree to this route
           * @return {?}
           */
          get: function () { return this._routerState.pathFromRoot(this); },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ActivatedRouteSnapshot.prototype, "paramMap", {
          /**
           * @return {?}
           */
          get: function () {
              if (!this._paramMap) {
                  this._paramMap = convertToParamMap(this.params);
              }
              return this._paramMap;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ActivatedRouteSnapshot.prototype, "queryParamMap", {
          /**
           * @return {?}
           */
          get: function () {
              if (!this._queryParamMap) {
                  this._queryParamMap = convertToParamMap(this.queryParams);
              }
              return this._queryParamMap;
          },
          enumerable: true,
          configurable: true
      });
      /**
       * @return {?}
       */
      ActivatedRouteSnapshot.prototype.toString = function () {
          var /** @type {?} */ url = this.url.map(function (segment) { return segment.toString(); }).join('/');
          var /** @type {?} */ matched = this._routeConfig ? this._routeConfig.path : '';
          return "Route(url:'" + url + "', path:'" + matched + "')";
      };
      return ActivatedRouteSnapshot;
  }());
  /**
   * \@whatItDoes Represents the state of the router at a moment in time.
   *
   * \@howToUse
   *
   * ```
   * \@Component({templateUrl:'template.html'})
   * class MyComponent {
   *   constructor(router: Router) {
   *     const state: RouterState = router.routerState;
   *     const snapshot: RouterStateSnapshot = state.snapshot;
   *     const root: ActivatedRouteSnapshot = snapshot.root;
   *     const child = root.firstChild;
   *     const id: Observable<string> = child.params.map(p => p.id);
   *     //...
   *   }
   * }
   * ```
   *
   * \@description
   * RouterStateSnapshot is a tree of activated route snapshots. Every node in this tree knows about
   * the "consumed" URL segments, the extracted parameters, and the resolved data.
   *
   * \@stable
   */
  var RouterStateSnapshot = (function (_super) {
      __extends(RouterStateSnapshot, _super);
      /**
       * \@internal
       * @param {?} url
       * @param {?} root
       */
      function RouterStateSnapshot(url, root) {
          var _this = _super.call(this, root) || this;
          _this.url = url;
          setRouterState(_this, root);
          return _this;
      }
      /**
       * @return {?}
       */
      RouterStateSnapshot.prototype.toString = function () { return serializeNode(this._root); };
      return RouterStateSnapshot;
  }(Tree));
  /**
   * @template U, T
   * @param {?} state
   * @param {?} node
   * @return {?}
   */
  function setRouterState(state, node) {
      node.value._routerState = state;
      node.children.forEach(function (c) { return setRouterState(state, c); });
  }
  /**
   * @param {?} node
   * @return {?}
   */
  function serializeNode(node) {
      var /** @type {?} */ c = node.children.length > 0 ? " { " + node.children.map(serializeNode).join(", ") + " } " : '';
      return "" + node.value + c;
  }
  /**
   * The expectation is that the activate route is created with the right set of parameters.
   * So we push new values into the observables only when they are not the initial values.
   * And we detect that by checking if the snapshot field is set.
   * @param {?} route
   * @return {?}
   */
  function advanceActivatedRoute(route) {
      if (route.snapshot) {
          var /** @type {?} */ currentSnapshot = route.snapshot;
          var /** @type {?} */ nextSnapshot = route._futureSnapshot;
          route.snapshot = nextSnapshot;
          if (!shallowEqual(currentSnapshot.queryParams, nextSnapshot.queryParams)) {
              ((route.queryParams)).next(nextSnapshot.queryParams);
          }
          if (currentSnapshot.fragment !== nextSnapshot.fragment) {
              ((route.fragment)).next(nextSnapshot.fragment);
          }
          if (!shallowEqual(currentSnapshot.params, nextSnapshot.params)) {
              ((route.params)).next(nextSnapshot.params);
          }
          if (!shallowEqualArrays(currentSnapshot.url, nextSnapshot.url)) {
              ((route.url)).next(nextSnapshot.url);
          }
          if (!shallowEqual(currentSnapshot.data, nextSnapshot.data)) {
              ((route.data)).next(nextSnapshot.data);
          }
      }
      else {
          route.snapshot = route._futureSnapshot;
          // this is for resolved data
          ((route.data)).next(route._futureSnapshot.data);
      }
  }
  /**
   * @param {?} a
   * @param {?} b
   * @return {?}
   */
  function equalParamsAndUrlSegments(a, b) {
      var /** @type {?} */ equalUrlParams = shallowEqual(a.params, b.params) && equalSegments(a.url, b.url);
      var /** @type {?} */ parentsMismatch = !a.parent !== !b.parent;
      return equalUrlParams && !parentsMismatch &&
          (!a.parent || equalParamsAndUrlSegments(a.parent, /** @type {?} */ ((b.parent))));
  }
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * @param {?} routeReuseStrategy
   * @param {?} curr
   * @param {?} prevState
   * @return {?}
   */
  function createRouterState(routeReuseStrategy, curr, prevState) {
      var /** @type {?} */ root = createNode(routeReuseStrategy, curr._root, prevState ? prevState._root : undefined);
      return new RouterState(root, curr);
  }
  /**
   * @param {?} routeReuseStrategy
   * @param {?} curr
   * @param {?=} prevState
   * @return {?}
   */
  function createNode(routeReuseStrategy, curr, prevState) {
      // reuse an activated route that is currently displayed on the screen
      if (prevState && routeReuseStrategy.shouldReuseRoute(curr.value, prevState.value.snapshot)) {
          var /** @type {?} */ value = prevState.value;
          value._futureSnapshot = curr.value;
          var /** @type {?} */ children = createOrReuseChildren(routeReuseStrategy, curr, prevState);
          return new TreeNode(value, children);
          // retrieve an activated route that is used to be displayed, but is not currently displayed
      }
      else if (routeReuseStrategy.retrieve(curr.value)) {
          var /** @type {?} */ tree_1 = ((routeReuseStrategy.retrieve(curr.value))).route;
          setFutureSnapshotsOfActivatedRoutes(curr, tree_1);
          return tree_1;
      }
      else {
          var /** @type {?} */ value = createActivatedRoute(curr.value);
          var /** @type {?} */ children = curr.children.map(function (c) { return createNode(routeReuseStrategy, c); });
          return new TreeNode(value, children);
      }
  }
  /**
   * @param {?} curr
   * @param {?} result
   * @return {?}
   */
  function setFutureSnapshotsOfActivatedRoutes(curr, result) {
      if (curr.value.routeConfig !== result.value.routeConfig) {
          throw new Error('Cannot reattach ActivatedRouteSnapshot created from a different route');
      }
      if (curr.children.length !== result.children.length) {
          throw new Error('Cannot reattach ActivatedRouteSnapshot with a different number of children');
      }
      result.value._futureSnapshot = curr.value;
      for (var /** @type {?} */ i = 0; i < curr.children.length; ++i) {
          setFutureSnapshotsOfActivatedRoutes(curr.children[i], result.children[i]);
      }
  }
  /**
   * @param {?} routeReuseStrategy
   * @param {?} curr
   * @param {?} prevState
   * @return {?}
   */
  function createOrReuseChildren(routeReuseStrategy, curr, prevState) {
      return curr.children.map(function (child) {
          for (var _i = 0, _a = prevState.children; _i < _a.length; _i++) {
              var p = _a[_i];
              if (routeReuseStrategy.shouldReuseRoute(p.value.snapshot, child.value)) {
                  return createNode(routeReuseStrategy, child, p);
              }
          }
          return createNode(routeReuseStrategy, child);
      });
  }
  /**
   * @param {?} c
   * @return {?}
   */
  function createActivatedRoute(c) {
      return new ActivatedRoute(new rxjs_BehaviorSubject.BehaviorSubject(c.url), new rxjs_BehaviorSubject.BehaviorSubject(c.params), new rxjs_BehaviorSubject.BehaviorSubject(c.queryParams), new rxjs_BehaviorSubject.BehaviorSubject(c.fragment), new rxjs_BehaviorSubject.BehaviorSubject(c.data), c.outlet, c.component, c);
  }
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * @param {?} route
   * @param {?} urlTree
   * @param {?} commands
   * @param {?} queryParams
   * @param {?} fragment
   * @return {?}
   */
  function createUrlTree(route, urlTree, commands, queryParams, fragment) {
      if (commands.length === 0) {
          return tree(urlTree.root, urlTree.root, urlTree, queryParams, fragment);
      }
      var /** @type {?} */ nav = computeNavigation(commands);
      if (nav.toRoot()) {
          return tree(urlTree.root, new UrlSegmentGroup([], {}), urlTree, queryParams, fragment);
      }
      var /** @type {?} */ startingPosition = findStartingPosition(nav, urlTree, route);
      var /** @type {?} */ segmentGroup = startingPosition.processChildren ?
          updateSegmentGroupChildren(startingPosition.segmentGroup, startingPosition.index, nav.commands) :
          updateSegmentGroup(startingPosition.segmentGroup, startingPosition.index, nav.commands);
      return tree(startingPosition.segmentGroup, segmentGroup, urlTree, queryParams, fragment);
  }
  /**
   * @param {?} command
   * @return {?}
   */
  function isMatrixParams(command) {
      return typeof command === 'object' && command != null && !command.outlets && !command.segmentPath;
  }
  /**
   * @param {?} oldSegmentGroup
   * @param {?} newSegmentGroup
   * @param {?} urlTree
   * @param {?} queryParams
   * @param {?} fragment
   * @return {?}
   */
  function tree(oldSegmentGroup, newSegmentGroup, urlTree, queryParams, fragment) {
      var /** @type {?} */ qp = {};
      if (queryParams) {
          forEach(queryParams, function (value, name) {
              qp[name] = Array.isArray(value) ? value.map(function (v) { return "" + v; }) : "" + value;
          });
      }
      if (urlTree.root === oldSegmentGroup) {
          return new UrlTree(newSegmentGroup, qp, fragment);
      }
      return new UrlTree(replaceSegment(urlTree.root, oldSegmentGroup, newSegmentGroup), qp, fragment);
  }
  /**
   * @param {?} current
   * @param {?} oldSegment
   * @param {?} newSegment
   * @return {?}
   */
  function replaceSegment(current, oldSegment, newSegment) {
      var /** @type {?} */ children = {};
      forEach(current.children, function (c, outletName) {
          if (c === oldSegment) {
              children[outletName] = newSegment;
          }
          else {
              children[outletName] = replaceSegment(c, oldSegment, newSegment);
          }
      });
      return new UrlSegmentGroup(current.segments, children);
  }
  var Navigation = (function () {
      /**
       * @param {?} isAbsolute
       * @param {?} numberOfDoubleDots
       * @param {?} commands
       */
      function Navigation(isAbsolute, numberOfDoubleDots, commands) {
          this.isAbsolute = isAbsolute;
          this.numberOfDoubleDots = numberOfDoubleDots;
          this.commands = commands;
          if (isAbsolute && commands.length > 0 && isMatrixParams(commands[0])) {
              throw new Error('Root segment cannot have matrix parameters');
          }
          var cmdWithOutlet = commands.find(function (c) { return typeof c === 'object' && c != null && c.outlets; });
          if (cmdWithOutlet && cmdWithOutlet !== last$1(commands)) {
              throw new Error('{outlets:{}} has to be the last command');
          }
      }
      /**
       * @return {?}
       */
      Navigation.prototype.toRoot = function () {
          return this.isAbsolute && this.commands.length === 1 && this.commands[0] == '/';
      };
      return Navigation;
  }());
  /**
   * Transforms commands to a normalized `Navigation`
   * @param {?} commands
   * @return {?}
   */
  function computeNavigation(commands) {
      if ((typeof commands[0] === 'string') && commands.length === 1 && commands[0] === '/') {
          return new Navigation(true, 0, commands);
      }
      var /** @type {?} */ numberOfDoubleDots = 0;
      var /** @type {?} */ isAbsolute = false;
      var /** @type {?} */ res = commands.reduce(function (res, cmd, cmdIdx) {
          if (typeof cmd === 'object' && cmd != null) {
              if (cmd.outlets) {
                  var /** @type {?} */ outlets_1 = {};
                  forEach(cmd.outlets, function (commands, name) {
                      outlets_1[name] = typeof commands === 'string' ? commands.split('/') : commands;
                  });
                  return res.concat([{ outlets: outlets_1 }]);
              }
              if (cmd.segmentPath) {
                  return res.concat([cmd.segmentPath]);
              }
          }
          if (!(typeof cmd === 'string')) {
              return res.concat([cmd]);
          }
          if (cmdIdx === 0) {
              cmd.split('/').forEach(function (urlPart, partIndex) {
                  if (partIndex == 0 && urlPart === '.') {
                      // skip './a'
                  }
                  else if (partIndex == 0 && urlPart === '') {
                      isAbsolute = true;
                  }
                  else if (urlPart === '..') {
                      numberOfDoubleDots++;
                  }
                  else if (urlPart != '') {
                      res.push(urlPart);
                  }
              });
              return res;
          }
          return res.concat([cmd]);
      }, []);
      return new Navigation(isAbsolute, numberOfDoubleDots, res);
  }
  var Position = (function () {
      /**
       * @param {?} segmentGroup
       * @param {?} processChildren
       * @param {?} index
       */
      function Position(segmentGroup, processChildren, index) {
          this.segmentGroup = segmentGroup;
          this.processChildren = processChildren;
          this.index = index;
      }
      return Position;
  }());
  /**
   * @param {?} nav
   * @param {?} tree
   * @param {?} route
   * @return {?}
   */
  function findStartingPosition(nav, tree, route) {
      if (nav.isAbsolute) {
          return new Position(tree.root, true, 0);
      }
      if (route.snapshot._lastPathIndex === -1) {
          return new Position(route.snapshot._urlSegment, true, 0);
      }
      var /** @type {?} */ modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;
      var /** @type {?} */ index = route.snapshot._lastPathIndex + modifier;
      return createPositionApplyingDoubleDots(route.snapshot._urlSegment, index, nav.numberOfDoubleDots);
  }
  /**
   * @param {?} group
   * @param {?} index
   * @param {?} numberOfDoubleDots
   * @return {?}
   */
  function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) {
      var /** @type {?} */ g = group;
      var /** @type {?} */ ci = index;
      var /** @type {?} */ dd = numberOfDoubleDots;
      while (dd > ci) {
          dd -= ci;
          g = ((g.parent));
          if (!g) {
              throw new Error('Invalid number of \'../\'');
          }
          ci = g.segments.length;
      }
      return new Position(g, false, ci - dd);
  }
  /**
   * @param {?} command
   * @return {?}
   */
  function getPath(command) {
      if (typeof command === 'object' && command != null && command.outlets) {
          return command.outlets[PRIMARY_OUTLET];
      }
      return "" + command;
  }
  /**
   * @param {?} commands
   * @return {?}
   */
  function getOutlets(commands) {
      if (!(typeof commands[0] === 'object'))
          return _a = {}, _a[PRIMARY_OUTLET] = commands, _a;
      if (commands[0].outlets === undefined)
          return _b = {}, _b[PRIMARY_OUTLET] = commands, _b;
      return commands[0].outlets;
      var _a, _b;
  }
  /**
   * @param {?} segmentGroup
   * @param {?} startIndex
   * @param {?} commands
   * @return {?}
   */
  function updateSegmentGroup(segmentGroup, startIndex, commands) {
      if (!segmentGroup) {
          segmentGroup = new UrlSegmentGroup([], {});
      }
      if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
          return updateSegmentGroupChildren(segmentGroup, startIndex, commands);
      }
      var /** @type {?} */ m = prefixedWith(segmentGroup, startIndex, commands);
      var /** @type {?} */ slicedCommands = commands.slice(m.commandIndex);
      if (m.match && m.pathIndex < segmentGroup.segments.length) {
          var /** @type {?} */ g = new UrlSegmentGroup(segmentGroup.segments.slice(0, m.pathIndex), {});
          g.children[PRIMARY_OUTLET] =
              new UrlSegmentGroup(segmentGroup.segments.slice(m.pathIndex), segmentGroup.children);
          return updateSegmentGroupChildren(g, 0, slicedCommands);
      }
      else if (m.match && slicedCommands.length === 0) {
          return new UrlSegmentGroup(segmentGroup.segments, {});
      }
      else if (m.match && !segmentGroup.hasChildren()) {
          return createNewSegmentGroup(segmentGroup, startIndex, commands);
      }
      else if (m.match) {
          return updateSegmentGroupChildren(segmentGroup, 0, slicedCommands);
      }
      else {
          return createNewSegmentGroup(segmentGroup, startIndex, commands);
      }
  }
  /**
   * @param {?} segmentGroup
   * @param {?} startIndex
   * @param {?} commands
   * @return {?}
   */
  function updateSegmentGroupChildren(segmentGroup, startIndex, commands) {
      if (commands.length === 0) {
          return new UrlSegmentGroup(segmentGroup.segments, {});
      }
      else {
          var /** @type {?} */ outlets_2 = getOutlets(commands);
          var /** @type {?} */ children_2 = {};
          forEach(outlets_2, function (commands, outlet) {
              if (commands !== null) {
                  children_2[outlet] = updateSegmentGroup(segmentGroup.children[outlet], startIndex, commands);
              }
          });
          forEach(segmentGroup.children, function (child, childOutlet) {
              if (outlets_2[childOutlet] === undefined) {
                  children_2[childOutlet] = child;
              }
          });
          return new UrlSegmentGroup(segmentGroup.segments, children_2);
      }
  }
  /**
   * @param {?} segmentGroup
   * @param {?} startIndex
   * @param {?} commands
   * @return {?}
   */
  function prefixedWith(segmentGroup, startIndex, commands) {
      var /** @type {?} */ currentCommandIndex = 0;
      var /** @type {?} */ currentPathIndex = startIndex;
      var /** @type {?} */ noMatch = { match: false, pathIndex: 0, commandIndex: 0 };
      while (currentPathIndex < segmentGroup.segments.length) {
          if (currentCommandIndex >= commands.length)
              return noMatch;
          var /** @type {?} */ path = segmentGroup.segments[currentPathIndex];
          var /** @type {?} */ curr = getPath(commands[currentCommandIndex]);
          var /** @type {?} */ next = currentCommandIndex < commands.length - 1 ? commands[currentCommandIndex + 1] : null;
          if (currentPathIndex > 0 && curr === undefined)
              break;
          if (curr && next && (typeof next === 'object') && next.outlets === undefined) {
              if (!compare(curr, next, path))
                  return noMatch;
              currentCommandIndex += 2;
          }
          else {
              if (!compare(curr, {}, path))
                  return noMatch;
              currentCommandIndex++;
          }
          currentPathIndex++;
      }
      return { match: true, pathIndex: currentPathIndex, commandIndex: currentCommandIndex };
  }
  /**
   * @param {?} segmentGroup
   * @param {?} startIndex
   * @param {?} commands
   * @return {?}
   */
  function createNewSegmentGroup(segmentGroup, startIndex, commands) {
      var /** @type {?} */ paths = segmentGroup.segments.slice(0, startIndex);
      var /** @type {?} */ i = 0;
      while (i < commands.length) {
          if (typeof commands[i] === 'object' && commands[i].outlets !== undefined) {
              var /** @type {?} */ children = createNewSegmentChildren(commands[i].outlets);
              return new UrlSegmentGroup(paths, children);
          }
          // if we start with an object literal, we need to reuse the path part from the segment
          if (i === 0 && isMatrixParams(commands[0])) {
              var /** @type {?} */ p = segmentGroup.segments[startIndex];
              paths.push(new UrlSegment(p.path, commands[0]));
              i++;
              continue;
          }
          var /** @type {?} */ curr = getPath(commands[i]);
          var /** @type {?} */ next = (i < commands.length - 1) ? commands[i + 1] : null;
          if (curr && next && isMatrixParams(next)) {
              paths.push(new UrlSegment(curr, stringify(next)));
              i += 2;
          }
          else {
              paths.push(new UrlSegment(curr, {}));
              i++;
          }
      }
      return new UrlSegmentGroup(paths, {});
  }
  /**
   * @param {?} outlets
   * @return {?}
   */
  function createNewSegmentChildren(outlets) {
      var /** @type {?} */ children = {};
      forEach(outlets, function (commands, outlet) {
          if (commands !== null) {
              children[outlet] = createNewSegmentGroup(new UrlSegmentGroup([], {}), 0, commands);
          }
      });
      return children;
  }
  /**
   * @param {?} params
   * @return {?}
   */
  function stringify(params) {
      var /** @type {?} */ res = {};
      forEach(params, function (v, k) { return res[k] = "" + v; });
      return res;
  }
  /**
   * @param {?} path
   * @param {?} params
   * @param {?} segment
   * @return {?}
   */
  function compare(path, params, segment) {
      return path == segment.path && shallowEqual(params, segment.parameters);
  }
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  var NoMatch$1 = (function () {
      function NoMatch$1() {
      }
      return NoMatch$1;
  }());
  /**
   * @param {?} rootComponentType
   * @param {?} config
   * @param {?} urlTree
   * @param {?} url
   * @return {?}
   */
  function recognize(rootComponentType, config, urlTree, url) {
      return new Recognizer(rootComponentType, config, urlTree, url).recognize();
  }
  var Recognizer = (function () {
      /**
       * @param {?} rootComponentType
       * @param {?} config
       * @param {?} urlTree
       * @param {?} url
       */
      function Recognizer(rootComponentType, config, urlTree, url) {
          this.rootComponentType = rootComponentType;
          this.config = config;
          this.urlTree = urlTree;
          this.url = url;
      }
      /**
       * @return {?}
       */
      Recognizer.prototype.recognize = function () {
          try {
              var /** @type {?} */ rootSegmentGroup = split$1(this.urlTree.root, [], [], this.config).segmentGroup;
              var /** @type {?} */ children = this.processSegmentGroup(this.config, rootSegmentGroup, PRIMARY_OUTLET);
              var /** @type {?} */ root = new ActivatedRouteSnapshot([], Object.freeze({}), Object.freeze(this.urlTree.queryParams), /** @type {?} */ ((this.urlTree.fragment)), {}, PRIMARY_OUTLET, this.rootComponentType, null, this.urlTree.root, -1, {});
              var /** @type {?} */ rootNode = new TreeNode(root, children);
              var /** @type {?} */ routeState = new RouterStateSnapshot(this.url, rootNode);
              this.inheritParamsAndData(routeState._root);
              return rxjs_observable_of.of(routeState);
          }
          catch (e) {
              return new rxjs_Observable.Observable(function (obs) { return obs.error(e); });
          }
      };
      /**
       * @param {?} routeNode
       * @return {?}
       */
      Recognizer.prototype.inheritParamsAndData = function (routeNode) {
          var _this = this;
          var /** @type {?} */ route = routeNode.value;
          var /** @type {?} */ i = inheritedParamsDataResolve(route);
          route.params = Object.freeze(i.params);
          route.data = Object.freeze(i.data);
          routeNode.children.forEach(function (n) { return _this.inheritParamsAndData(n); });
      };
      /**
       * @param {?} config
       * @param {?} segmentGroup
       * @param {?} outlet
       * @return {?}
       */
      Recognizer.prototype.processSegmentGroup = function (config, segmentGroup, outlet) {
          if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
              return this.processChildren(config, segmentGroup);
          }
          return this.processSegment(config, segmentGroup, segmentGroup.segments, outlet);
      };
      /**
       * @param {?} config
       * @param {?} segmentGroup
       * @return {?}
       */
      Recognizer.prototype.processChildren = function (config, segmentGroup) {
          var _this = this;
          var /** @type {?} */ children = mapChildrenIntoArray(segmentGroup, function (child, childOutlet) { return _this.processSegmentGroup(config, child, childOutlet); });
          checkOutletNameUniqueness(children);
          sortActivatedRouteSnapshots(children);
          return children;
      };
      /**
       * @param {?} config
       * @param {?} segmentGroup
       * @param {?} segments
       * @param {?} outlet
       * @return {?}
       */
      Recognizer.prototype.processSegment = function (config, segmentGroup, segments, outlet) {
          for (var _i = 0, config_1 = config; _i < config_1.length; _i++) {
              var r = config_1[_i];
              try {
                  return this.processSegmentAgainstRoute(r, segmentGroup, segments, outlet);
              }
              catch (e) {
                  if (!(e instanceof NoMatch$1))
                      throw e;
              }
          }
          if (this.noLeftoversInUrl(segmentGroup, segments, outlet)) {
              return [];
          }
          throw new NoMatch$1();
      };
      /**
       * @param {?} segmentGroup
       * @param {?} segments
       * @param {?} outlet
       * @return {?}
       */
      Recognizer.prototype.noLeftoversInUrl = function (segmentGroup, segments, outlet) {
          return segments.length === 0 && !segmentGroup.children[outlet];
      };
      /**
       * @param {?} route
       * @param {?} rawSegment
       * @param {?} segments
       * @param {?} outlet
       * @return {?}
       */
      Recognizer.prototype.processSegmentAgainstRoute = function (route, rawSegment, segments, outlet) {
          if (route.redirectTo)
              throw new NoMatch$1();
          if ((route.outlet || PRIMARY_OUTLET) !== outlet)
              throw new NoMatch$1();
          if (route.path === '**') {
              var /** @type {?} */ params = segments.length > 0 ? ((last$1(segments))).parameters : {};
              var /** @type {?} */ snapshot_1 = new ActivatedRouteSnapshot(segments, params, Object.freeze(this.urlTree.queryParams), /** @type {?} */ ((this.urlTree.fragment)), getData(route), outlet, /** @type {?} */ ((route.component)), route, getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + segments.length, getResolve(route));
              return [new TreeNode(snapshot_1, [])];
          }
          var _a = match$1(rawSegment, route, segments), consumedSegments = _a.consumedSegments, parameters = _a.parameters, lastChild = _a.lastChild;
          var /** @type {?} */ rawSlicedSegments = segments.slice(lastChild);
          var /** @type {?} */ childConfig = getChildConfig(route);
          var _b = split$1(rawSegment, consumedSegments, rawSlicedSegments, childConfig), segmentGroup = _b.segmentGroup, slicedSegments = _b.slicedSegments;
          var /** @type {?} */ snapshot = new ActivatedRouteSnapshot(consumedSegments, parameters, Object.freeze(this.urlTree.queryParams), /** @type {?} */ ((this.urlTree.fragment)), getData(route), outlet, /** @type {?} */ ((route.component)), route, getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + consumedSegments.length, getResolve(route));
          if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
              var /** @type {?} */ children_3 = this.processChildren(childConfig, segmentGroup);
              return [new TreeNode(snapshot, children_3)];
          }
          if (childConfig.length === 0 && slicedSegments.length === 0) {
              return [new TreeNode(snapshot, [])];
          }
          var /** @type {?} */ children = this.processSegment(childConfig, segmentGroup, slicedSegments, PRIMARY_OUTLET);
          return [new TreeNode(snapshot, children)];
      };
      return Recognizer;
  }());
  /**
   * @param {?} nodes
   * @return {?}
   */
  function sortActivatedRouteSnapshots(nodes) {
      nodes.sort(function (a, b) {
          if (a.value.outlet === PRIMARY_OUTLET)
              return -1;
          if (b.value.outlet === PRIMARY_OUTLET)
              return 1;
          return a.value.outlet.localeCompare(b.value.outlet);
      });
  }
  /**
   * @param {?} route
   * @return {?}
   */
  function getChildConfig(route) {
      if (route.children) {
          return route.children;
      }
      if (route.loadChildren) {
          return ((route._loadedConfig)).routes;
      }
      return [];
  }
  /**
   * @param {?} segmentGroup
   * @param {?} route
   * @param {?} segments
   * @return {?}
   */
  function match$1(segmentGroup, route, segments) {
      if (route.path === '') {
          if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || segments.length > 0)) {
              throw new NoMatch$1();
          }
          return { consumedSegments: [], lastChild: 0, parameters: {} };
      }
      var /** @type {?} */ matcher = route.matcher || defaultUrlMatcher;
      var /** @type {?} */ res = matcher(segments, segmentGroup, route);
      if (!res)
          throw new NoMatch$1();
      var /** @type {?} */ posParams = {};
      forEach(/** @type {?} */ ((res.posParams)), function (v, k) { posParams[k] = v.path; });
      var /** @type {?} */ parameters = res.consumed.length > 0 ? Object.assign({}, posParams, res.consumed[res.consumed.length - 1].parameters) :
          posParams;
      return { consumedSegments: res.consumed, lastChild: res.consumed.length, parameters: parameters };
  }
  /**
   * @param {?} nodes
   * @return {?}
   */
  function checkOutletNameUniqueness(nodes) {
      var /** @type {?} */ names = {};
      nodes.forEach(function (n) {
          var /** @type {?} */ routeWithSameOutletName = names[n.value.outlet];
          if (routeWithSameOutletName) {
              var /** @type {?} */ p = routeWithSameOutletName.url.map(function (s) { return s.toString(); }).join('/');
              var /** @type {?} */ c = n.value.url.map(function (s) { return s.toString(); }).join('/');
              throw new Error("Two segments cannot have the same outlet name: '" + p + "' and '" + c + "'.");
          }
          names[n.value.outlet] = n.value;
      });
  }
  /**
   * @param {?} segmentGroup
   * @return {?}
   */
  function getSourceSegmentGroup(segmentGroup) {
      var /** @type {?} */ s = segmentGroup;
      while (s._sourceSegment) {
          s = s._sourceSegment;
      }
      return s;
  }
  /**
   * @param {?} segmentGroup
   * @return {?}
   */
  function getPathIndexShift(segmentGroup) {
      var /** @type {?} */ s = segmentGroup;
      var /** @type {?} */ res = (s._segmentIndexShift ? s._segmentIndexShift : 0);
      while (s._sourceSegment) {
          s = s._sourceSegment;
          res += (s._segmentIndexShift ? s._segmentIndexShift : 0);
      }
      return res - 1;
  }
  /**
   * @param {?} segmentGroup
   * @param {?} consumedSegments
   * @param {?} slicedSegments
   * @param {?} config
   * @return {?}
   */
  function split$1(segmentGroup, consumedSegments, slicedSegments, config) {
      if (slicedSegments.length > 0 &&
          containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, config)) {
          var /** @type {?} */ s_1 = new UrlSegmentGroup(consumedSegments, createChildrenForEmptyPaths(segmentGroup, consumedSegments, config, new UrlSegmentGroup(slicedSegments, segmentGroup.children)));
          s_1._sourceSegment = segmentGroup;
          s_1._segmentIndexShift = consumedSegments.length;
          return { segmentGroup: s_1, slicedSegments: [] };
      }
      if (slicedSegments.length === 0 &&
          containsEmptyPathMatches(segmentGroup, slicedSegments, config)) {
          var /** @type {?} */ s_2 = new UrlSegmentGroup(segmentGroup.segments, addEmptyPathsToChildrenIfNeeded(segmentGroup, slicedSegments, config, segmentGroup.children));
          s_2._sourceSegment = segmentGroup;
          s_2._segmentIndexShift = consumedSegments.length;
          return { segmentGroup: s_2, slicedSegments: slicedSegments };
      }
      var /** @type {?} */ s = new UrlSegmentGroup(segmentGroup.segments, segmentGroup.children);
      s._sourceSegment = segmentGroup;
      s._segmentIndexShift = consumedSegments.length;
      return { segmentGroup: s, slicedSegments: slicedSegments };
  }
  /**
   * @param {?} segmentGroup
   * @param {?} slicedSegments
   * @param {?} routes
   * @param {?} children
   * @return {?}
   */
  function addEmptyPathsToChildrenIfNeeded(segmentGroup, slicedSegments, routes, children) {
      var /** @type {?} */ res = {};
      for (var _i = 0, routes_3 = routes; _i < routes_3.length; _i++) {
          var r = routes_3[_i];
          if (emptyPathMatch(segmentGroup, slicedSegments, r) && !children[getOutlet$1(r)]) {
              var /** @type {?} */ s = new UrlSegmentGroup([], {});
              s._sourceSegment = segmentGroup;
              s._segmentIndexShift = segmentGroup.segments.length;
              res[getOutlet$1(r)] = s;
          }
      }
      return Object.assign({}, children, res);
  }
  /**
   * @param {?} segmentGroup
   * @param {?} consumedSegments
   * @param {?} routes
   * @param {?} primarySegment
   * @return {?}
   */
  function createChildrenForEmptyPaths(segmentGroup, consumedSegments, routes, primarySegment) {
      var /** @type {?} */ res = {};
      res[PRIMARY_OUTLET] = primarySegment;
      primarySegment._sourceSegment = segmentGroup;
      primarySegment._segmentIndexShift = consumedSegments.length;
      for (var _i = 0, routes_4 = routes; _i < routes_4.length; _i++) {
          var r = routes_4[_i];
          if (r.path === '' && getOutlet$1(r) !== PRIMARY_OUTLET) {
              var /** @type {?} */ s = new UrlSegmentGroup([], {});
              s._sourceSegment = segmentGroup;
              s._segmentIndexShift = consumedSegments.length;
              res[getOutlet$1(r)] = s;
          }
      }
      return res;
  }
  /**
   * @param {?} segmentGroup
   * @param {?} slicedSegments
   * @param {?} routes
   * @return {?}
   */
  function containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, routes) {
      return routes.some(function (r) { return emptyPathMatch(segmentGroup, slicedSegments, r) && getOutlet$1(r) !== PRIMARY_OUTLET; });
  }
  /**
   * @param {?} segmentGroup
   * @param {?} slicedSegments
   * @param {?} routes
   * @return {?}
   */
  function containsEmptyPathMatches(segmentGroup, slicedSegments, routes) {
      return routes.some(function (r) { return emptyPathMatch(segmentGroup, slicedSegments, r); });
  }
  /**
   * @param {?} segmentGroup
   * @param {?} slicedSegments
   * @param {?} r
   * @return {?}
   */
  function emptyPathMatch(segmentGroup, slicedSegments, r) {
      if ((segmentGroup.hasChildren() || slicedSegments.length > 0) && r.pathMatch === 'full') {
          return false;
      }
      return r.path === '' && r.redirectTo === undefined;
  }
  /**
   * @param {?} route
   * @return {?}
   */
  function getOutlet$1(route) {
      return route.outlet || PRIMARY_OUTLET;
  }
  /**
   * @param {?} route
   * @return {?}
   */
  function getData(route) {
      return route.data || {};
  }
  /**
   * @param {?} route
   * @return {?}
   */
  function getResolve(route) {
      return route.resolve || {};
  }
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * \@whatItDoes Provides a way to customize when activated routes get reused.
   *
   * \@experimental
   * @abstract
   */
  var RouteReuseStrategy = (function () {
      function RouteReuseStrategy() {
      }
      /**
       * Determines if this route (and its subtree) should be detached to be reused later
       * @abstract
       * @param {?} route
       * @return {?}
       */
      RouteReuseStrategy.prototype.shouldDetach = function (route) { };
      /**
       * Stores the detached route.
       *
       * Storing a `null` value should erase the previously stored value.
       * @abstract
       * @param {?} route
       * @param {?} handle
       * @return {?}
       */
      RouteReuseStrategy.prototype.store = function (route, handle) { };
      /**
       * Determines if this route (and its subtree) should be reattached
       * @abstract
       * @param {?} route
       * @return {?}
       */
      RouteReuseStrategy.prototype.shouldAttach = function (route) { };
      /**
       * Retrieves the previously stored route
       * @abstract
       * @param {?} route
       * @return {?}
       */
      RouteReuseStrategy.prototype.retrieve = function (route) { };
      /**
       * Determines if a route should be reused
       * @abstract
       * @param {?} future
       * @param {?} curr
       * @return {?}
       */
      RouteReuseStrategy.prototype.shouldReuseRoute = function (future, curr) { };
      return RouteReuseStrategy;
  }());
  /**
   * Does not detach any subtrees. Reuses routes as long as their route config is the same.
   */
  var DefaultRouteReuseStrategy = (function () {
      function DefaultRouteReuseStrategy() {
      }
      /**
       * @param {?} route
       * @return {?}
       */
      DefaultRouteReuseStrategy.prototype.shouldDetach = function (route) { return false; };
      /**
       * @param {?} route
       * @param {?} detachedTree
       * @return {?}
       */
      DefaultRouteReuseStrategy.prototype.store = function (route, detachedTree) { };
      /**
       * @param {?} route
       * @return {?}
       */
      DefaultRouteReuseStrategy.prototype.shouldAttach = function (route) { return false; };
      /**
       * @param {?} route
       * @return {?}
       */
      DefaultRouteReuseStrategy.prototype.retrieve = function (route) { return null; };
      /**
       * @param {?} future
       * @param {?} curr
       * @return {?}
       */
      DefaultRouteReuseStrategy.prototype.shouldReuseRoute = function (future, curr) {
          return future.routeConfig === curr.routeConfig;
      };
      return DefaultRouteReuseStrategy;
  }());
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * \@docsNotRequired
   * \@experimental
   */
  var ROUTES = new _angular_core.InjectionToken('ROUTES');
  var RouterConfigLoader = (function () {
      /**
       * @param {?} loader
       * @param {?} compiler
       * @param {?=} onLoadStartListener
       * @param {?=} onLoadEndListener
       */
      function RouterConfigLoader(loader, compiler, onLoadStartListener, onLoadEndListener) {
          this.loader = loader;
          this.compiler = compiler;
          this.onLoadStartListener = onLoadStartListener;
          this.onLoadEndListener = onLoadEndListener;
      }
      /**
       * @param {?} parentInjector
       * @param {?} route
       * @return {?}
       */
      RouterConfigLoader.prototype.load = function (parentInjector, route) {
          var _this = this;
          if (this.onLoadStartListener) {
              this.onLoadStartListener(route);
          }
          var /** @type {?} */ moduleFactory$ = this.loadModuleFactory(/** @type {?} */ ((route.loadChildren)));
          return rxjs_operator_map.map.call(moduleFactory$, function (factory) {
              if (_this.onLoadEndListener) {
                  _this.onLoadEndListener(route);
              }
              var /** @type {?} */ module = factory.create(parentInjector);
              return new LoadedRouterConfig(flatten(module.injector.get(ROUTES)), module);
          });
      };
      /**
       * @param {?} loadChildren
       * @return {?}
       */
      RouterConfigLoader.prototype.loadModuleFactory = function (loadChildren) {
          var _this = this;
          if (typeof loadChildren === 'string') {
              return rxjs_observable_fromPromise.fromPromise(this.loader.load(loadChildren));
          }
          else {
              return rxjs_operator_mergeMap.mergeMap.call(wrapIntoObservable(loadChildren()), function (t) {
                  if (t instanceof _angular_core.NgModuleFactory) {
                      return rxjs_observable_of.of(t);
                  }
                  else {
                      return rxjs_observable_fromPromise.fromPromise(_this.compiler.compileModuleAsync(t));
                  }
              });
          }
      };
      return RouterConfigLoader;
  }());
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * \@whatItDoes Provides a way to migrate AngularJS applications to Angular.
   *
   * \@experimental
   * @abstract
   */
  var UrlHandlingStrategy = (function () {
      function UrlHandlingStrategy() {
      }
      /**
       * Tells the router if this URL should be processed.
       *
       * When it returns true, the router will execute the regular navigation.
       * When it returns false, the router will set the router state to an empty state.
       * As a result, all the active components will be destroyed.
       *
       * @abstract
       * @param {?} url
       * @return {?}
       */
      UrlHandlingStrategy.prototype.shouldProcessUrl = function (url) { };
      /**
       * Extracts the part of the URL that should be handled by the router.
       * The rest of the URL will remain untouched.
       * @abstract
       * @param {?} url
       * @return {?}
       */
      UrlHandlingStrategy.prototype.extract = function (url) { };
      /**
       * Merges the URL fragment with the rest of the URL.
       * @abstract
       * @param {?} newUrlPart
       * @param {?} rawUrl
       * @return {?}
       */
      UrlHandlingStrategy.prototype.merge = function (newUrlPart, rawUrl) { };
      return UrlHandlingStrategy;
  }());
  /**
   * \@experimental
   */
  var DefaultUrlHandlingStrategy = (function () {
      function DefaultUrlHandlingStrategy() {
      }
      /**
       * @param {?} url
       * @return {?}
       */
      DefaultUrlHandlingStrategy.prototype.shouldProcessUrl = function (url) { return true; };
      /**
       * @param {?} url
       * @return {?}
       */
      DefaultUrlHandlingStrategy.prototype.extract = function (url) { return url; };
      /**
       * @param {?} newUrlPart
       * @param {?} wholeUrl
       * @return {?}
       */
      DefaultUrlHandlingStrategy.prototype.merge = function (newUrlPart, wholeUrl) { return newUrlPart; };
      return DefaultUrlHandlingStrategy;
  }());
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * @param {?} error
   * @return {?}
   */
  function defaultErrorHandler(error) {
      throw error;
  }
  /**
   * \@internal
   * @param {?} snapshot
   * @return {?}
   */
  function defaultRouterHook(snapshot) {
      return (rxjs_observable_of.of(null));
  }
  /**
   * \@whatItDoes Provides the navigation and url manipulation capabilities.
   *
   * See {\@link Routes} for more details and examples.
   *
   * \@ngModule RouterModule
   *
   * \@stable
   */
  var Router = (function () {
      /**
       * @param {?} rootComponentType
       * @param {?} urlSerializer
       * @param {?} rootContexts
       * @param {?} location
       * @param {?} injector
       * @param {?} loader
       * @param {?} compiler
       * @param {?} config
       */
      function Router(rootComponentType, urlSerializer, rootContexts, location, injector, loader, compiler, config) {
          var _this = this;
          this.rootComponentType = rootComponentType;
          this.urlSerializer = urlSerializer;
          this.rootContexts = rootContexts;
          this.location = location;
          this.config = config;
          this.navigations = new rxjs_BehaviorSubject.BehaviorSubject(/** @type {?} */ ((null)));
          this.routerEvents = new rxjs_Subject.Subject();
          this.navigationId = 0;
          /**
           * Error handler that is invoked when a navigation errors.
           *
           * See {\@link ErrorHandler} for more information.
           */
          this.errorHandler = defaultErrorHandler;
          /**
           * Indicates if at least one navigation happened.
           */
          this.navigated = false;
          /**
           * Used by RouterModule. This allows us to
           * pause the navigation either before preactivation or after it.
           * \@internal
           */
          this.hooks = {
              beforePreactivation: defaultRouterHook,
              afterPreactivation: defaultRouterHook
          };
          /**
           * Extracts and merges URLs. Used for AngularJS to Angular migrations.
           */
          this.urlHandlingStrategy = new DefaultUrlHandlingStrategy();
          this.routeReuseStrategy = new DefaultRouteReuseStrategy();
          var onLoadStart = function (r) { return _this.triggerEvent(new RouteConfigLoadStart(r)); };
          var onLoadEnd = function (r) { return _this.triggerEvent(new RouteConfigLoadEnd(r)); };
          this.ngModule = injector.get(_angular_core.NgModuleRef);
          this.resetConfig(config);
          this.currentUrlTree = createEmptyUrlTree();
          this.rawUrlTree = this.currentUrlTree;
          this.configLoader = new RouterConfigLoader(loader, compiler, onLoadStart, onLoadEnd);
          this.currentRouterState = createEmptyState(this.currentUrlTree, this.rootComponentType);
          this.processNavigations();
      }
      /**
       * \@internal
       * TODO: this should be removed once the constructor of the router made internal
       * @param {?} rootComponentType
       * @return {?}
       */
      Router.prototype.resetRootComponentType = function (rootComponentType) {
          this.rootComponentType = rootComponentType;
          // TODO: vsavkin router 4.0 should make the root component set to null
          // this will simplify the lifecycle of the router.
          this.currentRouterState.root.component = this.rootComponentType;
      };
      /**
       * Sets up the location change listener and performs the initial navigation.
       * @return {?}
       */
      Router.prototype.initialNavigation = function () {
          this.setUpLocationChangeListener();
          if (this.navigationId === 0) {
              this.navigateByUrl(this.location.path(true), { replaceUrl: true });
          }
      };
      /**
       * Sets up the location change listener.
       * @return {?}
       */
      Router.prototype.setUpLocationChangeListener = function () {
          var _this = this;
          // Zone.current.wrap is needed because of the issue with RxJS scheduler,
          // which does not work properly with zone.js in IE and Safari
          if (!this.locationSubscription) {
              this.locationSubscription = (this.location.subscribe(Zone.current.wrap(function (change) {
                  var /** @type {?} */ rawUrlTree = _this.urlSerializer.parse(change['url']);
                  var /** @type {?} */ source = change['type'] === 'popstate' ? 'popstate' : 'hashchange';
                  setTimeout(function () { _this.scheduleNavigation(rawUrlTree, source, { replaceUrl: true }); }, 0);
              })));
          }
      };
      Object.defineProperty(Router.prototype, "routerState", {
          /**
           * The current route state
           * @return {?}
           */
          get: function () { return this.currentRouterState; },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(Router.prototype, "url", {
          /**
           * The current url
           * @return {?}
           */
          get: function () { return this.serializeUrl(this.currentUrlTree); },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(Router.prototype, "events", {
          /**
           * An observable of router events
           * @return {?}
           */
          get: function () { return this.routerEvents; },
          enumerable: true,
          configurable: true
      });
      /**
       * \@internal
       * @param {?} e
       * @return {?}
       */
      Router.prototype.triggerEvent = function (e) { this.routerEvents.next(e); };
      /**
       * Resets the configuration used for navigation and generating links.
       *
       * ### Usage
       *
       * ```
       * router.resetConfig([
       *  { path: 'team/:id', component: TeamCmp, children: [
       *    { path: 'simple', component: SimpleCmp },
       *    { path: 'user/:name', component: UserCmp }
       *  ]}
       * ]);
       * ```
       * @param {?} config
       * @return {?}
       */
      Router.prototype.resetConfig = function (config) {
          validateConfig(config);
          this.config = config;
          this.navigated = false;
      };
      /**
       * \@docsNotRequired
       * @return {?}
       */
      Router.prototype.ngOnDestroy = function () { this.dispose(); };
      /**
       * Disposes of the router
       * @return {?}
       */
      Router.prototype.dispose = function () {
          if (this.locationSubscription) {
              this.locationSubscription.unsubscribe();
              this.locationSubscription = ((null));
          }
      };
      /**
       * Applies an array of commands to the current url tree and creates a new url tree.
       *
       * When given an activate route, applies the given commands starting from the route.
       * When not given a route, applies the given command starting from the root.
       *
       * ### Usage
       *
       * ```
       * // create /team/33/user/11
       * router.createUrlTree(['/team', 33, 'user', 11]);
       *
       * // create /team/33;expand=true/user/11
       * router.createUrlTree(['/team', 33, {expand: true}, 'user', 11]);
       *
       * // you can collapse static segments like this (this works only with the first passed-in value):
       * router.createUrlTree(['/team/33/user', userId]);
       *
       * // If the first segment can contain slashes, and you do not want the router to split it, you
       * // can do the following:
       *
       * router.createUrlTree([{segmentPath: '/one/two'}]);
       *
       * // create /team/33/(user/11//right:chat)
       * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: 'chat'}}]);
       *
       * // remove the right secondary node
       * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: null}}]);
       *
       * // assuming the current url is `/team/33/user/11` and the route points to `user/11`
       *
       * // navigate to /team/33/user/11/details
       * router.createUrlTree(['details'], {relativeTo: route});
       *
       * // navigate to /team/33/user/22
       * router.createUrlTree(['../22'], {relativeTo: route});
       *
       * // navigate to /team/44/user/22
       * router.createUrlTree(['../../team/44/user/22'], {relativeTo: route});
       * ```
       * @param {?} commands
       * @param {?=} navigationExtras
       * @return {?}
       */
      Router.prototype.createUrlTree = function (commands, navigationExtras) {
          if (navigationExtras === void 0) { navigationExtras = {}; }
          var relativeTo = navigationExtras.relativeTo, queryParams = navigationExtras.queryParams, fragment = navigationExtras.fragment, preserveQueryParams = navigationExtras.preserveQueryParams, queryParamsHandling = navigationExtras.queryParamsHandling, preserveFragment = navigationExtras.preserveFragment;
          if (_angular_core.isDevMode() && preserveQueryParams && (console) && (console.warn)) {
              console.warn('preserveQueryParams is deprecated, use queryParamsHandling instead.');
          }
          var /** @type {?} */ a = relativeTo || this.routerState.root;
          var /** @type {?} */ f = preserveFragment ? this.currentUrlTree.fragment : fragment;
          var /** @type {?} */ q = null;
          if (queryParamsHandling) {
              switch (queryParamsHandling) {
                  case 'merge':
                      q = Object.assign({}, this.currentUrlTree.queryParams, queryParams);
                      break;
                  case 'preserve':
                      q = this.currentUrlTree.queryParams;
                      break;
                  default:
                      q = queryParams || null;
              }
          }
          else {
              q = preserveQueryParams ? this.currentUrlTree.queryParams : queryParams || null;
          }
          return createUrlTree(a, this.currentUrlTree, commands, /** @type {?} */ ((q)), /** @type {?} */ ((f)));
      };
      /**
       * Navigate based on the provided url. This navigation is always absolute.
       *
       * Returns a promise that:
       * - resolves to 'true' when navigation succeeds,
       * - resolves to 'false' when navigation fails,
       * - is rejected when an error happens.
       *
       * ### Usage
       *
       * ```
       * router.navigateByUrl("/team/33/user/11");
       *
       * // Navigate without updating the URL
       * router.navigateByUrl("/team/33/user/11", { skipLocationChange: true });
       * ```
       *
       * In opposite to `navigate`, `navigateByUrl` takes a whole URL
       * and does not apply any delta to the current one.
       * @param {?} url
       * @param {?=} extras
       * @return {?}
       */
      Router.prototype.navigateByUrl = function (url, extras) {
          if (extras === void 0) { extras = { skipLocationChange: false }; }
          var /** @type {?} */ urlTree = url instanceof UrlTree ? url : this.parseUrl(url);
          var /** @type {?} */ mergedTree = this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree);
          return this.scheduleNavigation(mergedTree, 'imperative', extras);
      };
      /**
       * Navigate based on the provided array of commands and a starting point.
       * If no starting route is provided, the navigation is absolute.
       *
       * Returns a promise that:
       * - resolves to 'true' when navigation succeeds,
       * - resolves to 'false' when navigation fails,
       * - is rejected when an error happens.
       *
       * ### Usage
       *
       * ```
       * router.navigate(['team', 33, 'user', 11], {relativeTo: route});
       *
       * // Navigate without updating the URL
       * router.navigate(['team', 33, 'user', 11], {relativeTo: route, skipLocationChange: true});
       * ```
       *
       * In opposite to `navigateByUrl`, `navigate` always takes a delta that is applied to the current
       * URL.
       * @param {?} commands
       * @param {?=} extras
       * @return {?}
       */
      Router.prototype.navigate = function (commands, extras) {
          if (extras === void 0) { extras = { skipLocationChange: false }; }
          validateCommands(commands);
          if (typeof extras.queryParams === 'object' && extras.queryParams !== null) {
              extras.queryParams = this.removeEmptyProps(extras.queryParams);
          }
          return this.navigateByUrl(this.createUrlTree(commands, extras), extras);
      };
      /**
       * Serializes a {\@link UrlTree} into a string
       * @param {?} url
       * @return {?}
       */
      Router.prototype.serializeUrl = function (url) { return this.urlSerializer.serialize(url); };
      /**
       * Parses a string into a {\@link UrlTree}
       * @param {?} url
       * @return {?}
       */
      Router.prototype.parseUrl = function (url) { return this.urlSerializer.parse(url); };
      /**
       * Returns whether the url is activated
       * @param {?} url
       * @param {?} exact
       * @return {?}
       */
      Router.prototype.isActive = function (url, exact) {
          if (url instanceof UrlTree) {
              return containsTree(this.currentUrlTree, url, exact);
          }
          var /** @type {?} */ urlTree = this.urlSerializer.parse(url);
          return containsTree(this.currentUrlTree, urlTree, exact);
      };
      /**
       * @param {?} params
       * @return {?}
       */
      Router.prototype.removeEmptyProps = function (params) {
          return Object.keys(params).reduce(function (result, key) {
              var /** @type {?} */ value = params[key];
              if (value !== null && value !== undefined) {
                  result[key] = value;
              }
              return result;
          }, {});
      };
      /**
       * @return {?}
       */
      Router.prototype.processNavigations = function () {
          var _this = this;
          rxjs_operator_concatMap.concatMap
              .call(this.navigations, function (nav) {
              if (nav) {
                  _this.executeScheduledNavigation(nav);
                  // a failed navigation should not stop the router from processing
                  // further navigations => the catch
                  return nav.promise.catch(function () { });
              }
              else {
                  return (rxjs_observable_of.of(null));
              }
          })
              .subscribe(function () { });
      };
      /**
       * @param {?} rawUrl
       * @param {?} source
       * @param {?} extras
       * @return {?}
       */
      Router.prototype.scheduleNavigation = function (rawUrl, source, extras) {
          var /** @type {?} */ lastNavigation = this.navigations.value;
          // If the user triggers a navigation imperatively (e.g., by using navigateByUrl),
          // and that navigation results in 'replaceState' that leads to the same URL,
          // we should skip those.
          if (lastNavigation && source !== 'imperative' && lastNavigation.source === 'imperative' &&
              lastNavigation.rawUrl.toString() === rawUrl.toString()) {
              return Promise.resolve(true); // return value is not used
          }
          // Because of a bug in IE and Edge, the location class fires two events (popstate and
          // hashchange) every single time. The second one should be ignored. Otherwise, the URL will
          // flicker.
          if (lastNavigation && source == 'hashchange' && lastNavigation.source === 'popstate' &&
              lastNavigation.rawUrl.toString() === rawUrl.toString()) {
              return Promise.resolve(true); // return value is not used
          }
          var /** @type {?} */ resolve = null;
          var /** @type {?} */ reject = null;
          var /** @type {?} */ promise = new Promise(function (res, rej) {
              resolve = res;
              reject = rej;
          });
          var /** @type {?} */ id = ++this.navigationId;
          this.navigations.next({ id: id, source: source, rawUrl: rawUrl, extras: extras, resolve: resolve, reject: reject, promise: promise });
          // Make sure that the error is propagated even though `processNavigations` catch
          // handler does not rethrow
          return promise.catch(function (e) { return Promise.reject(e); });
      };
      /**
       * @param {?} __0
       * @return {?}
       */
      Router.prototype.executeScheduledNavigation = function (_a) {
          var _this = this;
          var id = _a.id, rawUrl = _a.rawUrl, extras = _a.extras, resolve = _a.resolve, reject = _a.reject;
          var /** @type {?} */ url = this.urlHandlingStrategy.extract(rawUrl);
          var /** @type {?} */ urlTransition = !this.navigated || url.toString() !== this.currentUrlTree.toString();
          if (urlTransition && this.urlHandlingStrategy.shouldProcessUrl(rawUrl)) {
              this.routerEvents.next(new NavigationStart(id, this.serializeUrl(url)));
              Promise.resolve()
                  .then(function (_) { return _this.runNavigate(url, rawUrl, !!extras.skipLocationChange, !!extras.replaceUrl, id, null); })
                  .then(resolve, reject);
              // we cannot process the current URL, but we could process the previous one =>
              // we need to do some cleanup
          }
          else if (urlTransition && this.rawUrlTree &&
              this.urlHandlingStrategy.shouldProcessUrl(this.rawUrlTree)) {
              this.routerEvents.next(new NavigationStart(id, this.serializeUrl(url)));
              Promise.resolve()
                  .then(function (_) { return _this.runNavigate(url, rawUrl, false, false, id, createEmptyState(url, _this.rootComponentType).snapshot); })
                  .then(resolve, reject);
          }
          else {
              this.rawUrlTree = rawUrl;
              resolve(null);
          }
      };
      /**
       * @param {?} url
       * @param {?} rawUrl
       * @param {?} shouldPreventPushState
       * @param {?} shouldReplaceUrl
       * @param {?} id
       * @param {?} precreatedState
       * @return {?}
       */
      Router.prototype.runNavigate = function (url, rawUrl, shouldPreventPushState, shouldReplaceUrl, id, precreatedState) {
          var _this = this;
          if (id !== this.navigationId) {
              this.location.go(this.urlSerializer.serialize(this.currentUrlTree));
              this.routerEvents.next(new NavigationCancel(id, this.serializeUrl(url), "Navigation ID " + id + " is not equal to the current navigation id " + this.navigationId));
              return Promise.resolve(false);
          }
          return new Promise(function (resolvePromise, rejectPromise) {
              // create an observable of the url and route state snapshot
              // this operation do not result in any side effects
              var /** @type {?} */ urlAndSnapshot$;
              if (!precreatedState) {
                  var /** @type {?} */ moduleInjector = _this.ngModule.injector;
                  var /** @type {?} */ redirectsApplied$ = applyRedirects(moduleInjector, _this.configLoader, _this.urlSerializer, url, _this.config);
                  urlAndSnapshot$ = rxjs_operator_mergeMap.mergeMap.call(redirectsApplied$, function (appliedUrl) {
                      return rxjs_operator_map.map.call(recognize(_this.rootComponentType, _this.config, appliedUrl, _this.serializeUrl(appliedUrl)), function (snapshot) {
                          _this.routerEvents.next(new RoutesRecognized(id, _this.serializeUrl(url), _this.serializeUrl(appliedUrl), snapshot));
                          return { appliedUrl: appliedUrl, snapshot: snapshot };
                      });
                  });
              }
              else {
                  urlAndSnapshot$ = rxjs_observable_of.of({ appliedUrl: url, snapshot: precreatedState });
              }
              var /** @type {?} */ beforePreactivationDone$ = rxjs_operator_mergeMap.mergeMap.call(urlAndSnapshot$, function (p) {
                  return rxjs_operator_map.map.call(_this.hooks.beforePreactivation(p.snapshot), function () { return p; });
              });
              // run preactivation: guards and data resolvers
              var /** @type {?} */ preActivation;
              var /** @type {?} */ preactivationTraverse$ = rxjs_operator_map.map.call(beforePreactivationDone$, function (_a) {
                  var appliedUrl = _a.appliedUrl, snapshot = _a.snapshot;
                  var /** @type {?} */ moduleInjector = _this.ngModule.injector;
                  preActivation =
                      new PreActivation(snapshot, _this.currentRouterState.snapshot, moduleInjector);
                  preActivation.traverse(_this.rootContexts);
                  return { appliedUrl: appliedUrl, snapshot: snapshot };
              });
              var /** @type {?} */ preactivationCheckGuards$ = rxjs_operator_mergeMap.mergeMap.call(preactivationTraverse$, function (_a) {
                  var appliedUrl = _a.appliedUrl, snapshot = _a.snapshot;
                  if (_this.navigationId !== id)
                      return rxjs_observable_of.of(false);
                  _this.triggerEvent(new GuardsCheckStart(id, _this.serializeUrl(url), appliedUrl, snapshot));
                  return rxjs_operator_map.map.call(preActivation.checkGuards(), function (shouldActivate) {
                      _this.triggerEvent(new GuardsCheckEnd(id, _this.serializeUrl(url), appliedUrl, snapshot, shouldActivate));
                      return { appliedUrl: appliedUrl, snapshot: snapshot, shouldActivate: shouldActivate };
                  });
              });
              var /** @type {?} */ preactivationResolveData$ = rxjs_operator_mergeMap.mergeMap.call(preactivationCheckGuards$, function (p) {
                  if (_this.navigationId !== id)
                      return rxjs_observable_of.of(false);
                  if (p.shouldActivate && preActivation.isActivating()) {
                      _this.triggerEvent(new ResolveStart(id, _this.serializeUrl(url), p.appliedUrl, p.snapshot));
                      return rxjs_operator_map.map.call(preActivation.resolveData(), function () {
                          _this.triggerEvent(new ResolveEnd(id, _this.serializeUrl(url), p.appliedUrl, p.snapshot));
                          return p;
                      });
                  }
                  else {
                      return rxjs_observable_of.of(p);
                  }
              });
              var /** @type {?} */ preactivationDone$ = rxjs_operator_mergeMap.mergeMap.call(preactivationResolveData$, function (p) {
                  return rxjs_operator_map.map.call(_this.hooks.afterPreactivation(p.snapshot), function () { return p; });
              });
              // create router state
              // this operation has side effects => route state is being affected
              var /** @type {?} */ routerState$ = rxjs_operator_map.map.call(preactivationDone$, function (_a) {
                  var appliedUrl = _a.appliedUrl, snapshot = _a.snapshot, shouldActivate = _a.shouldActivate;
                  if (shouldActivate) {
                      var /** @type {?} */ state = createRouterState(_this.routeReuseStrategy, snapshot, _this.currentRouterState);
                      return { appliedUrl: appliedUrl, state: state, shouldActivate: shouldActivate };
                  }
                  else {
                      return { appliedUrl: appliedUrl, state: null, shouldActivate: shouldActivate };
                  }
              });
              // applied the new router state
              // this operation has side effects
              var /** @type {?} */ navigationIsSuccessful;
              var /** @type {?} */ storedState = _this.currentRouterState;
              var /** @type {?} */ storedUrl = _this.currentUrlTree;
              routerState$
                  .forEach(function (_a) {
                  var appliedUrl = _a.appliedUrl, state = _a.state, shouldActivate = _a.shouldActivate;
                  if (!shouldActivate || id !== _this.navigationId) {
                      navigationIsSuccessful = false;
                      return;
                  }
                  _this.currentUrlTree = appliedUrl;
                  _this.rawUrlTree = _this.urlHandlingStrategy.merge(_this.currentUrlTree, rawUrl);
                  _this.currentRouterState = state;
                  if (!shouldPreventPushState) {
                      var /** @type {?} */ path = _this.urlSerializer.serialize(_this.rawUrlTree);
                      if (_this.location.isCurrentPathEqualTo(path) || shouldReplaceUrl) {
                          _this.location.replaceState(path);
                      }
                      else {
                          _this.location.go(path);
                      }
                  }
                  new ActivateRoutes(_this.routeReuseStrategy, state, storedState)
                      .activate(_this.rootContexts);
                  navigationIsSuccessful = true;
              })
                  .then(function () {
                  if (navigationIsSuccessful) {
                      _this.navigated = true;
                      _this.routerEvents.next(new NavigationEnd(id, _this.serializeUrl(url), _this.serializeUrl(_this.currentUrlTree)));
                      resolvePromise(true);
                  }
                  else {
                      _this.resetUrlToCurrentUrlTree();
                      _this.routerEvents.next(new NavigationCancel(id, _this.serializeUrl(url), ''));
                      resolvePromise(false);
                  }
              }, function (e) {
                  if (isNavigationCancelingError(e)) {
                      _this.resetUrlToCurrentUrlTree();
                      _this.navigated = true;
                      _this.routerEvents.next(new NavigationCancel(id, _this.serializeUrl(url), e.message));
                      resolvePromise(false);
                  }
                  else {
                      _this.routerEvents.next(new NavigationError(id, _this.serializeUrl(url), e));
                      try {
                          resolvePromise(_this.errorHandler(e));
                      }
                      catch (ee) {
                          rejectPromise(ee);
                      }
                  }
                  _this.currentRouterState = storedState;
                  _this.currentUrlTree = storedUrl;
                  _this.rawUrlTree = _this.urlHandlingStrategy.merge(_this.currentUrlTree, rawUrl);
                  _this.location.replaceState(_this.serializeUrl(_this.rawUrlTree));
              });
          });
      };
      /**
       * @return {?}
       */
      Router.prototype.resetUrlToCurrentUrlTree = function () {
          var /** @type {?} */ path = this.urlSerializer.serialize(this.rawUrlTree);
          this.location.replaceState(path);
      };
      return Router;
  }());
  var CanActivate = (function () {
      /**
       * @param {?} path
       */
      function CanActivate(path) {
          this.path = path;
      }
      Object.defineProperty(CanActivate.prototype, "route", {
          /**
           * @return {?}
           */
          get: function () { return this.path[this.path.length - 1]; },
          enumerable: true,
          configurable: true
      });
      return CanActivate;
  }());
  var CanDeactivate = (function () {
      /**
       * @param {?} component
       * @param {?} route
       */
      function CanDeactivate(component, route) {
          this.component = component;
          this.route = route;
      }
      return CanDeactivate;
  }());
  var PreActivation = (function () {
      /**
       * @param {?} future
       * @param {?} curr
       * @param {?} moduleInjector
       */
      function PreActivation(future, curr, moduleInjector) {
          this.future = future;
          this.curr = curr;
          this.moduleInjector = moduleInjector;
          this.canActivateChecks = [];
          this.canDeactivateChecks = [];
      }
      /**
       * @param {?} parentContexts
       * @return {?}
       */
      PreActivation.prototype.traverse = function (parentContexts) {
          var /** @type {?} */ futureRoot = this.future._root;
          var /** @type {?} */ currRoot = this.curr ? this.curr._root : null;
          this.traverseChildRoutes(futureRoot, currRoot, parentContexts, [futureRoot.value]);
      };
      /**
       * @return {?}
       */
      PreActivation.prototype.checkGuards = function () {
          var _this = this;
          if (!this.isDeactivating() && !this.isActivating()) {
              return rxjs_observable_of.of(true);
          }
          var /** @type {?} */ canDeactivate$ = this.runCanDeactivateChecks();
          return rxjs_operator_mergeMap.mergeMap.call(canDeactivate$, function (canDeactivate) { return canDeactivate ? _this.runCanActivateChecks() : rxjs_observable_of.of(false); });
      };
      /**
       * @return {?}
       */
      PreActivation.prototype.resolveData = function () {
          var _this = this;
          if (!this.isActivating())
              return rxjs_observable_of.of(null);
          var /** @type {?} */ checks$ = rxjs_observable_from.from(this.canActivateChecks);
          var /** @type {?} */ runningChecks$ = rxjs_operator_concatMap.concatMap.call(checks$, function (check) { return _this.runResolve(check.route); });
          return rxjs_operator_reduce.reduce.call(runningChecks$, function (_, __) { return _; });
      };
      /**
       * @return {?}
       */
      PreActivation.prototype.isDeactivating = function () { return this.canDeactivateChecks.length !== 0; };
      /**
       * @return {?}
       */
      PreActivation.prototype.isActivating = function () { return this.canActivateChecks.length !== 0; };
      /**
       * @param {?} futureNode
       * @param {?} currNode
       * @param {?} contexts
       * @param {?} futurePath
       * @return {?}
       */
      PreActivation.prototype.traverseChildRoutes = function (futureNode, currNode, contexts, futurePath) {
          var _this = this;
          var /** @type {?} */ prevChildren = nodeChildrenAsMap(currNode);
          // Process the children of the future route
          futureNode.children.forEach(function (c) {
              _this.traverseRoutes(c, prevChildren[c.value.outlet], contexts, futurePath.concat([c.value]));
              delete prevChildren[c.value.outlet];
          });
          // Process any children left from the current route (not active for the future route)
          forEach(prevChildren, function (v, k) { return _this.deactivateRouteAndItsChildren(v, /** @type {?} */ ((contexts)).getContext(k)); });
      };
      /**
       * @param {?} futureNode
       * @param {?} currNode
       * @param {?} parentContexts
       * @param {?} futurePath
       * @return {?}
       */
      PreActivation.prototype.traverseRoutes = function (futureNode, currNode, parentContexts, futurePath) {
          var /** @type {?} */ future = futureNode.value;
          var /** @type {?} */ curr = currNode ? currNode.value : null;
          var /** @type {?} */ context = parentContexts ? parentContexts.getContext(futureNode.value.outlet) : null;
          // reusing the node
          if (curr && future._routeConfig === curr._routeConfig) {
              var /** @type {?} */ shouldRunGuardsAndResolvers = this.shouldRunGuardsAndResolvers(curr, future, /** @type {?} */ ((future._routeConfig)).runGuardsAndResolvers);
              if (shouldRunGuardsAndResolvers) {
                  this.canActivateChecks.push(new CanActivate(futurePath));
              }
              else {
                  // we need to set the data
                  future.data = curr.data;
                  future._resolvedData = curr._resolvedData;
              }
              // If we have a component, we need to go through an outlet.
              if (future.component) {
                  this.traverseChildRoutes(futureNode, currNode, context ? context.children : null, futurePath);
                  // if we have a componentless route, we recurse but keep the same outlet map.
              }
              else {
                  this.traverseChildRoutes(futureNode, currNode, parentContexts, futurePath);
              }
              if (shouldRunGuardsAndResolvers) {
                  var /** @type {?} */ outlet = ((((context)).outlet));
                  this.canDeactivateChecks.push(new CanDeactivate(outlet.component, curr));
              }
          }
          else {
              if (curr) {
                  this.deactivateRouteAndItsChildren(currNode, context);
              }
              this.canActivateChecks.push(new CanActivate(futurePath));
              // If we have a component, we need to go through an outlet.
              if (future.component) {
                  this.traverseChildRoutes(futureNode, null, context ? context.children : null, futurePath);
                  // if we have a componentless route, we recurse but keep the same outlet map.
              }
              else {
                  this.traverseChildRoutes(futureNode, null, parentContexts, futurePath);
              }
          }
      };
      /**
       * @param {?} curr
       * @param {?} future
       * @param {?} mode
       * @return {?}
       */
      PreActivation.prototype.shouldRunGuardsAndResolvers = function (curr, future, mode) {
          switch (mode) {
              case 'always':
                  return true;
              case 'paramsOrQueryParamsChange':
                  return !equalParamsAndUrlSegments(curr, future) ||
                      !shallowEqual(curr.queryParams, future.queryParams);
              case 'paramsChange':
              default:
                  return !equalParamsAndUrlSegments(curr, future);
          }
      };
      /**
       * @param {?} route
       * @param {?} context
       * @return {?}
       */
      PreActivation.prototype.deactivateRouteAndItsChildren = function (route, context) {
          var _this = this;
          var /** @type {?} */ children = nodeChildrenAsMap(route);
          var /** @type {?} */ r = route.value;
          forEach(children, function (node, childName) {
              if (!r.component) {
                  _this.deactivateRouteAndItsChildren(node, context);
              }
              else if (context) {
                  _this.deactivateRouteAndItsChildren(node, context.children.getContext(childName));
              }
              else {
                  _this.deactivateRouteAndItsChildren(node, null);
              }
          });
          if (!r.component) {
              this.canDeactivateChecks.push(new CanDeactivate(null, r));
          }
          else if (context && context.outlet && context.outlet.isActivated) {
              this.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, r));
          }
          else {
              this.canDeactivateChecks.push(new CanDeactivate(null, r));
          }
      };
      /**
       * @return {?}
       */
      PreActivation.prototype.runCanDeactivateChecks = function () {
          var _this = this;
          var /** @type {?} */ checks$ = rxjs_observable_from.from(this.canDeactivateChecks);
          var /** @type {?} */ runningChecks$ = rxjs_operator_mergeMap.mergeMap.call(checks$, function (check) { return _this.runCanDeactivate(check.component, check.route); });
          return rxjs_operator_every.every.call(runningChecks$, function (result) { return result === true; });
      };
      /**
       * @return {?}
       */
      PreActivation.prototype.runCanActivateChecks = function () {
          var _this = this;
          var /** @type {?} */ checks$ = rxjs_observable_from.from(this.canActivateChecks);
          var /** @type {?} */ runningChecks$ = rxjs_operator_concatMap.concatMap.call(checks$, function (check) { return andObservables(rxjs_observable_from.from([_this.runCanActivateChild(check.path), _this.runCanActivate(check.route)])); });
          return rxjs_operator_every.every.call(runningChecks$, function (result) { return result === true; });
      };
      /**
       * @param {?} future
       * @return {?}
       */
      PreActivation.prototype.runCanActivate = function (future) {
          var _this = this;
          var /** @type {?} */ canActivate = future._routeConfig ? future._routeConfig.canActivate : null;
          if (!canActivate || canActivate.length === 0)
              return rxjs_observable_of.of(true);
          var /** @type {?} */ obs = rxjs_operator_map.map.call(rxjs_observable_from.from(canActivate), function (c) {
              var /** @type {?} */ guard = _this.getToken(c, future);
              var /** @type {?} */ observable;
              if (guard.canActivate) {
                  observable = wrapIntoObservable(guard.canActivate(future, _this.future));
              }
              else {
                  observable = wrapIntoObservable(guard(future, _this.future));
              }
              return rxjs_operator_first.first.call(observable);
          });
          return andObservables(obs);
      };
      /**
       * @param {?} path
       * @return {?}
       */
      PreActivation.prototype.runCanActivateChild = function (path) {
          var _this = this;
          var /** @type {?} */ future = path[path.length - 1];
          var /** @type {?} */ canActivateChildGuards = path.slice(0, path.length - 1)
              .reverse()
              .map(function (p) { return _this.extractCanActivateChild(p); })
              .filter(function (_) { return _ !== null; });
          return andObservables(rxjs_operator_map.map.call(rxjs_observable_from.from(canActivateChildGuards), function (d) {
              var /** @type {?} */ obs = rxjs_operator_map.map.call(rxjs_observable_from.from(d.guards), function (c) {
                  var /** @type {?} */ guard = _this.getToken(c, d.node);
                  var /** @type {?} */ observable;
                  if (guard.canActivateChild) {
                      observable = wrapIntoObservable(guard.canActivateChild(future, _this.future));
                  }
                  else {
                      observable = wrapIntoObservable(guard(future, _this.future));
                  }
                  return rxjs_operator_first.first.call(observable);
              });
              return andObservables(obs);
          }));
      };
      /**
       * @param {?} p
       * @return {?}
       */
      PreActivation.prototype.extractCanActivateChild = function (p) {
          var /** @type {?} */ canActivateChild = p._routeConfig ? p._routeConfig.canActivateChild : null;
          if (!canActivateChild || canActivateChild.length === 0)
              return null;
          return { node: p, guards: canActivateChild };
      };
      /**
       * @param {?} component
       * @param {?} curr
       * @return {?}
       */
      PreActivation.prototype.runCanDeactivate = function (component, curr) {
          var _this = this;
          var /** @type {?} */ canDeactivate = curr && curr._routeConfig ? curr._routeConfig.canDeactivate : null;
          if (!canDeactivate || canDeactivate.length === 0)
              return rxjs_observable_of.of(true);
          var /** @type {?} */ canDeactivate$ = rxjs_operator_mergeMap.mergeMap.call(rxjs_observable_from.from(canDeactivate), function (c) {
              var /** @type {?} */ guard = _this.getToken(c, curr);
              var /** @type {?} */ observable;
              if (guard.canDeactivate) {
                  observable =
                      wrapIntoObservable(guard.canDeactivate(component, curr, _this.curr, _this.future));
              }
              else {
                  observable = wrapIntoObservable(guard(component, curr, _this.curr, _this.future));
              }
              return rxjs_operator_first.first.call(observable);
          });
          return rxjs_operator_every.every.call(canDeactivate$, function (result) { return result === true; });
      };
      /**
       * @param {?} future
       * @return {?}
       */
      PreActivation.prototype.runResolve = function (future) {
          var /** @type {?} */ resolve = future._resolve;
          return rxjs_operator_map.map.call(this.resolveNode(resolve, future), function (resolvedData) {
              future._resolvedData = resolvedData;
              future.data = Object.assign({}, future.data, inheritedParamsDataResolve(future).resolve);
              return null;
          });
      };
      /**
       * @param {?} resolve
       * @param {?} future
       * @return {?}
       */
      PreActivation.prototype.resolveNode = function (resolve, future) {
          var _this = this;
          var /** @type {?} */ keys = Object.keys(resolve);
          if (keys.length === 0) {
              return rxjs_observable_of.of({});
          }
          if (keys.length === 1) {
              var /** @type {?} */ key_1 = keys[0];
              return rxjs_operator_map.map.call(this.getResolver(resolve[key_1], future), function (value) {
                  return _a = {}, _a[key_1] = value, _a;
                  var _a;
              });
          }
          var /** @type {?} */ data = {};
          var /** @type {?} */ runningResolvers$ = rxjs_operator_mergeMap.mergeMap.call(rxjs_observable_from.from(keys), function (key) {
              return rxjs_operator_map.map.call(_this.getResolver(resolve[key], future), function (value) {
                  data[key] = value;
                  return value;
              });
          });
          return rxjs_operator_map.map.call(rxjs_operator_last.last.call(runningResolvers$), function () { return data; });
      };
      /**
       * @param {?} injectionToken
       * @param {?} future
       * @return {?}
       */
      PreActivation.prototype.getResolver = function (injectionToken, future) {
          var /** @type {?} */ resolver = this.getToken(injectionToken, future);
          return resolver.resolve ? wrapIntoObservable(resolver.resolve(future, this.future)) :
              wrapIntoObservable(resolver(future, this.future));
      };
      /**
       * @param {?} token
       * @param {?} snapshot
       * @return {?}
       */
      PreActivation.prototype.getToken = function (token, snapshot) {
          var /** @type {?} */ config = closestLoadedConfig(snapshot);
          var /** @type {?} */ injector = config ? config.module.injector : this.moduleInjector;
          return injector.get(token);
      };
      return PreActivation;
  }());
  var ActivateRoutes = (function () {
      /**
       * @param {?} routeReuseStrategy
       * @param {?} futureState
       * @param {?} currState
       */
      function ActivateRoutes(routeReuseStrategy, futureState, currState) {
          this.routeReuseStrategy = routeReuseStrategy;
          this.futureState = futureState;
          this.currState = currState;
      }
      /**
       * @param {?} parentContexts
       * @return {?}
       */
      ActivateRoutes.prototype.activate = function (parentContexts) {
          var /** @type {?} */ futureRoot = this.futureState._root;
          var /** @type {?} */ currRoot = this.currState ? this.currState._root : null;
          this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
          advanceActivatedRoute(this.futureState.root);
          this.activateChildRoutes(futureRoot, currRoot, parentContexts);
      };
      /**
       * @param {?} futureNode
       * @param {?} currNode
       * @param {?} contexts
       * @return {?}
       */
      ActivateRoutes.prototype.deactivateChildRoutes = function (futureNode, currNode, contexts) {
          var _this = this;
          var /** @type {?} */ children = nodeChildrenAsMap(currNode);
          // Recurse on the routes active in the future state to de-activate deeper children
          futureNode.children.forEach(function (futureChild) {
              var /** @type {?} */ childOutletName = futureChild.value.outlet;
              _this.deactivateRoutes(futureChild, children[childOutletName], contexts);
              delete children[childOutletName];
          });
          // De-activate the routes that will not be re-used
          forEach(children, function (v, childName) {
              _this.deactivateRouteAndItsChildren(v, contexts);
          });
      };
      /**
       * @param {?} futureNode
       * @param {?} currNode
       * @param {?} parentContext
       * @return {?}
       */
      ActivateRoutes.prototype.deactivateRoutes = function (futureNode, currNode, parentContext) {
          var /** @type {?} */ future = futureNode.value;
          var /** @type {?} */ curr = currNode ? currNode.value : null;
          if (future === curr) {
              // Reusing the node, check to see if the children need to be de-activated
              if (future.component) {
                  // If we have a normal route, we need to go through an outlet.
                  var /** @type {?} */ context = parentContext.getContext(future.outlet);
                  if (context) {
                      this.deactivateChildRoutes(futureNode, currNode, context.children);
                  }
              }
              else {
                  // if we have a componentless route, we recurse but keep the same outlet map.
                  this.deactivateChildRoutes(futureNode, currNode, parentContext);
              }
          }
          else {
              if (curr) {
                  // Deactivate the current route which will not be re-used
                  this.deactivateRouteAndItsChildren(currNode, parentContext);
              }
          }
      };
      /**
       * @param {?} route
       * @param {?} parentContexts
       * @return {?}
       */
      ActivateRoutes.prototype.deactivateRouteAndItsChildren = function (route, parentContexts) {
          if (this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
              this.detachAndStoreRouteSubtree(route, parentContexts);
          }
          else {
              this.deactivateRouteAndOutlet(route, parentContexts);
          }
      };
      /**
       * @param {?} route
       * @param {?} parentContexts
       * @return {?}
       */
      ActivateRoutes.prototype.detachAndStoreRouteSubtree = function (route, parentContexts) {
          var /** @type {?} */ context = parentContexts.getContext(route.value.outlet);
          if (context && context.outlet) {
              var /** @type {?} */ componentRef = context.outlet.detach();
              var /** @type {?} */ contexts = context.children.onOutletDeactivated();
              this.routeReuseStrategy.store(route.value.snapshot, { componentRef: componentRef, route: route, contexts: contexts });
          }
      };
      /**
       * @param {?} route
       * @param {?} parentContexts
       * @return {?}
       */
      ActivateRoutes.prototype.deactivateRouteAndOutlet = function (route, parentContexts) {
          var _this = this;
          var /** @type {?} */ context = parentContexts.getContext(route.value.outlet);
          if (context) {
              var /** @type {?} */ children = nodeChildrenAsMap(route);
              var /** @type {?} */ contexts_1 = route.value.component ? context.children : parentContexts;
              forEach(children, function (v, k) { return _this.deactivateRouteAndItsChildren(v, contexts_1); });
              if (context.outlet) {
                  // Destroy the component
                  context.outlet.deactivate();
                  // Destroy the contexts for all the outlets that were in the component
                  context.children.onOutletDeactivated();
              }
          }
      };
      /**
       * @param {?} futureNode
       * @param {?} currNode
       * @param {?} contexts
       * @return {?}
       */
      ActivateRoutes.prototype.activateChildRoutes = function (futureNode, currNode, contexts) {
          var _this = this;
          var /** @type {?} */ children = nodeChildrenAsMap(currNode);
          futureNode.children.forEach(function (c) { _this.activateRoutes(c, children[c.value.outlet], contexts); });
      };
      /**
       * @param {?} futureNode
       * @param {?} currNode
       * @param {?} parentContexts
       * @return {?}
       */
      ActivateRoutes.prototype.activateRoutes = function (futureNode, currNode, parentContexts) {
          var /** @type {?} */ future = futureNode.value;
          var /** @type {?} */ curr = currNode ? currNode.value : null;
          advanceActivatedRoute(future);
          // reusing the node
          if (future === curr) {
              if (future.component) {
                  // If we have a normal route, we need to go through an outlet.
                  var /** @type {?} */ context = parentContexts.getOrCreateContext(future.outlet);
                  this.activateChildRoutes(futureNode, currNode, context.children);
              }
              else {
                  // if we have a componentless route, we recurse but keep the same outlet map.
                  this.activateChildRoutes(futureNode, currNode, parentContexts);
              }
          }
          else {
              if (future.component) {
                  // if we have a normal route, we need to place the component into the outlet and recurse.
                  var /** @type {?} */ context = parentContexts.getOrCreateContext(future.outlet);
                  if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
                      var /** @type {?} */ stored = ((this.routeReuseStrategy.retrieve(future.snapshot)));
                      this.routeReuseStrategy.store(future.snapshot, null);
                      context.children.onOutletReAttached(stored.contexts);
                      context.attachRef = stored.componentRef;
                      context.route = stored.route.value;
                      if (context.outlet) {
                          // Attach right away when the outlet has already been instantiated
                          // Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
                          context.outlet.attach(stored.componentRef, stored.route.value);
                      }
                      advanceActivatedRouteNodeAndItsChildren(stored.route);
                  }
                  else {
                      var /** @type {?} */ config = parentLoadedConfig(future.snapshot);
                      var /** @type {?} */ cmpFactoryResolver = config ? config.module.componentFactoryResolver : null;
                      context.route = future;
                      context.resolver = cmpFactoryResolver;
                      if (context.outlet) {
                          // Activate the outlet when it has already been instantiated
                          // Otherwise it will get activated from its `ngOnInit` when instantiated
                          context.outlet.activateWith(future, cmpFactoryResolver);
                      }
                      this.activateChildRoutes(futureNode, null, context.children);
                  }
              }
              else {
                  // if we have a componentless route, we recurse but keep the same outlet map.
                  this.activateChildRoutes(futureNode, null, parentContexts);
              }
          }
      };
      return ActivateRoutes;
  }());
  /**
   * @param {?} node
   * @return {?}
   */
  function advanceActivatedRouteNodeAndItsChildren(node) {
      advanceActivatedRoute(node.value);
      node.children.forEach(advanceActivatedRouteNodeAndItsChildren);
  }
  /**
   * @param {?} snapshot
   * @return {?}
   */
  function parentLoadedConfig(snapshot) {
      for (var /** @type {?} */ s = snapshot.parent; s; s = s.parent) {
          var /** @type {?} */ route = s._routeConfig;
          if (route && route._loadedConfig)
              return route._loadedConfig;
          if (route && route.component)
              return null;
      }
      return null;
  }
  /**
   * @param {?} snapshot
   * @return {?}
   */
  function closestLoadedConfig(snapshot) {
      if (!snapshot)
          return null;
      for (var /** @type {?} */ s = snapshot.parent; s; s = s.parent) {
          var /** @type {?} */ route = s._routeConfig;
          if (route && route._loadedConfig)
              return route._loadedConfig;
      }
      return null;
  }
  /**
   * @template T
   * @param {?} node
   * @return {?}
   */
  function nodeChildrenAsMap(node) {
      var /** @type {?} */ map$$1 = {};
      if (node) {
          node.children.forEach(function (child) { return map$$1[child.value.outlet] = child; });
      }
      return map$$1;
  }
  /**
   * @param {?} commands
   * @return {?}
   */
  function validateCommands(commands) {
      for (var /** @type {?} */ i = 0; i < commands.length; i++) {
          var /** @type {?} */ cmd = commands[i];
          if (cmd == null) {
              throw new Error("The requested path contains " + cmd + " segment at index " + i);
          }
      }
  }
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * \@whatItDoes Lets you link to specific parts of your app.
   *
   * \@howToUse
   *
   * Consider the following route configuration:
   * `[{ path: 'user/:name', component: UserCmp }]`
   *
   * When linking to this `user/:name` route, you can write:
   * `<a routerLink='/user/bob'>link to user component</a>`
   *
   * \@description
   *
   * The RouterLink directives let you link to specific parts of your app.
   *
   * When the link is static, you can use the directive as follows:
   * `<a routerLink="/user/bob">link to user component</a>`
   *
   * If you use dynamic values to generate the link, you can pass an array of path
   * segments, followed by the params for each segment.
   *
   * For instance `['/team', teamId, 'user', userName, {details: true}]`
   * means that we want to generate a link to `/team/11/user/bob;details=true`.
   *
   * Multiple static segments can be merged into one
   * (e.g., `['/team/11/user', userName, {details: true}]`).
   *
   * The first segment name can be prepended with `/`, `./`, or `../`:
   * * If the first segment begins with `/`, the router will look up the route from the root of the
   *   app.
   * * If the first segment begins with `./`, or doesn't begin with a slash, the router will
   *   instead look in the children of the current activated route.
   * * And if the first segment begins with `../`, the router will go up one level.
   *
   * You can set query params and fragment as follows:
   *
   * ```
   * <a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" fragment="education">
   *   link to user component
   * </a>
   * ```
   * RouterLink will use these to generate this link: `/user/bob#education?debug=true`.
   *
   * (Deprecated in v4.0.0 use `queryParamsHandling` instead) You can also tell the
   * directive to preserve the current query params and fragment:
   *
   * ```
   * <a [routerLink]="['/user/bob']" preserveQueryParams preserveFragment>
   *   link to user component
   * </a>
   * ```
   *
   * You can tell the directive to how to handle queryParams, available options are:
   *  - 'merge' merge the queryParams into the current queryParams
   *  - 'preserve' preserve the current queryParams
   *  - default / '' use the queryParams only
   *  same options for {\@link NavigationExtras#queryParamsHandling}
   *
   * ```
   * <a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" queryParamsHandling="merge">
   *   link to user component
   * </a>
   * ```
   *
   * The router link directive always treats the provided input as a delta to the current url.
   *
   * For instance, if the current url is `/user/(box//aux:team)`.
   *
   * Then the following link `<a [routerLink]="['/user/jim']">Jim</a>` will generate the link
   * `/user/(jim//aux:team)`.
   *
   * \@ngModule RouterModule
   *
   * See {\@link Router#createUrlTree} for more information.
   *
   * \@stable
   */
  var RouterLink = (function () {
      /**
       * @param {?} router
       * @param {?} route
       * @param {?} tabIndex
       * @param {?} renderer
       * @param {?} el
       */
      function RouterLink(router, route, tabIndex, renderer, el) {
          this.router = router;
          this.route = route;
          this.commands = [];
          if (tabIndex == null) {
              renderer.setAttribute(el.nativeElement, 'tabindex', '0');
          }
      }
      Object.defineProperty(RouterLink.prototype, "routerLink", {
          /**
           * @param {?} commands
           * @return {?}
           */
          set: function (commands) {
              if (commands != null) {
                  this.commands = Array.isArray(commands) ? commands : [commands];
              }
              else {
                  this.commands = [];
              }
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(RouterLink.prototype, "preserveQueryParams", {
          /**
           * @deprecated 4.0.0 use `queryParamsHandling` instead.
           * @param {?} value
           * @return {?}
           */
          set: function (value) {
              if (_angular_core.isDevMode() && (console) && (console.warn)) {
                  console.warn('preserveQueryParams is deprecated!, use queryParamsHandling instead.');
              }
              this.preserve = value;
          },
          enumerable: true,
          configurable: true
      });
      /**
       * @return {?}
       */
      RouterLink.prototype.onClick = function () {
          var /** @type {?} */ extras = {
              skipLocationChange: attrBoolValue(this.skipLocationChange),
              replaceUrl: attrBoolValue(this.replaceUrl),
          };
          this.router.navigateByUrl(this.urlTree, extras);
          return true;
      };
      Object.defineProperty(RouterLink.prototype, "urlTree", {
          /**
           * @return {?}
           */
          get: function () {
              return this.router.createUrlTree(this.commands, {
                  relativeTo: this.route,
                  queryParams: this.queryParams,
                  fragment: this.fragment,
                  preserveQueryParams: attrBoolValue(this.preserve),
                  queryParamsHandling: this.queryParamsHandling,
                  preserveFragment: attrBoolValue(this.preserveFragment),
              });
          },
          enumerable: true,
          configurable: true
      });
      return RouterLink;
  }());
  RouterLink.decorators = [
      { type: _angular_core.Directive, args: [{ selector: ':not(a)[routerLink]' },] },
  ];
  /**
   * @nocollapse
   */
  RouterLink.ctorParameters = function () { return [
      { type: Router, },
      { type: ActivatedRoute, },
      { type: undefined, decorators: [{ type: _angular_core.Attribute, args: ['tabindex',] },] },
      { type: _angular_core.Renderer2, },
      { type: _angular_core.ElementRef, },
  ]; };
  RouterLink.propDecorators = {
      'queryParams': [{ type: _angular_core.Input },],
      'fragment': [{ type: _angular_core.Input },],
      'queryParamsHandling': [{ type: _angular_core.Input },],
      'preserveFragment': [{ type: _angular_core.Input },],
      'skipLocationChange': [{ type: _angular_core.Input },],
      'replaceUrl': [{ type: _angular_core.Input },],
      'routerLink': [{ type: _angular_core.Input },],
      'preserveQueryParams': [{ type: _angular_core.Input },],
      'onClick': [{ type: _angular_core.HostListener, args: ['click',] },],
  };
  /**
   * \@whatItDoes Lets you link to specific parts of your app.
   *
   * See {\@link RouterLink} for more information.
   *
   * \@ngModule RouterModule
   *
   * \@stable
   */
  var RouterLinkWithHref = (function () {
      /**
       * @param {?} router
       * @param {?} route
       * @param {?} locationStrategy
       */
      function RouterLinkWithHref(router, route, locationStrategy) {
          var _this = this;
          this.router = router;
          this.route = route;
          this.locationStrategy = locationStrategy;
          this.commands = [];
          this.subscription = router.events.subscribe(function (s) {
              if (s instanceof NavigationEnd) {
                  _this.updateTargetUrlAndHref();
              }
          });
      }
      Object.defineProperty(RouterLinkWithHref.prototype, "routerLink", {
          /**
           * @param {?} commands
           * @return {?}
           */
          set: function (commands) {
              if (commands != null) {
                  this.commands = Array.isArray(commands) ? commands : [commands];
              }
              else {
                  this.commands = [];
              }
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(RouterLinkWithHref.prototype, "preserveQueryParams", {
          /**
           * @param {?} value
           * @return {?}
           */
          set: function (value) {
              if (_angular_core.isDevMode() && (console) && (console.warn)) {
                  console.warn('preserveQueryParams is deprecated, use queryParamsHandling instead.');
              }
              this.preserve = value;
          },
          enumerable: true,
          configurable: true
      });
      /**
       * @param {?} changes
       * @return {?}
       */
      RouterLinkWithHref.prototype.ngOnChanges = function (changes) { this.updateTargetUrlAndHref(); };
      /**
       * @return {?}
       */
      RouterLinkWithHref.prototype.ngOnDestroy = function () { this.subscription.unsubscribe(); };
      /**
       * @param {?} button
       * @param {?} ctrlKey
       * @param {?} metaKey
       * @param {?} shiftKey
       * @return {?}
       */
      RouterLinkWithHref.prototype.onClick = function (button, ctrlKey, metaKey, shiftKey) {
          if (button !== 0 || ctrlKey || metaKey || shiftKey) {
              return true;
          }
          if (typeof this.target === 'string' && this.target != '_self') {
              return true;
          }
          var /** @type {?} */ extras = {
              skipLocationChange: attrBoolValue(this.skipLocationChange),
              replaceUrl: attrBoolValue(this.replaceUrl),
          };
          this.router.navigateByUrl(this.urlTree, extras);
          return false;
      };
      /**
       * @return {?}
       */
      RouterLinkWithHref.prototype.updateTargetUrlAndHref = function () {
          this.href = this.locationStrategy.prepareExternalUrl(this.router.serializeUrl(this.urlTree));
      };
      Object.defineProperty(RouterLinkWithHref.prototype, "urlTree", {
          /**
           * @return {?}
           */
          get: function () {
              return this.router.createUrlTree(this.commands, {
                  relativeTo: this.route,
                  queryParams: this.queryParams,
                  fragment: this.fragment,
                  preserveQueryParams: attrBoolValue(this.preserve),
                  queryParamsHandling: this.queryParamsHandling,
                  preserveFragment: attrBoolValue(this.preserveFragment),
              });
          },
          enumerable: true,
          configurable: true
      });
      return RouterLinkWithHref;
  }());
  RouterLinkWithHref.decorators = [
      { type: _angular_core.Directive, args: [{ selector: 'a[routerLink]' },] },
  ];
  /**
   * @nocollapse
   */
  RouterLinkWithHref.ctorParameters = function () { return [
      { type: Router, },
      { type: ActivatedRoute, },
      { type: _angular_common.LocationStrategy, },
  ]; };
  RouterLinkWithHref.propDecorators = {
      'target': [{ type: _angular_core.HostBinding, args: ['attr.target',] }, { type: _angular_core.Input },],
      'queryParams': [{ type: _angular_core.Input },],
      'fragment': [{ type: _angular_core.Input },],
      'queryParamsHandling': [{ type: _angular_core.Input },],
      'preserveFragment': [{ type: _angular_core.Input },],
      'skipLocationChange': [{ type: _angular_core.Input },],
      'replaceUrl': [{ type: _angular_core.Input },],
      'href': [{ type: _angular_core.HostBinding },],
      'routerLink': [{ type: _angular_core.Input },],
      'preserveQueryParams': [{ type: _angular_core.Input },],
      'onClick': [{ type: _angular_core.HostListener, args: ['click', ['$event.button', '$event.ctrlKey', '$event.metaKey', '$event.shiftKey'],] },],
  };
  /**
   * @param {?} s
   * @return {?}
   */
  function attrBoolValue(s) {
      return s === '' || !!s;
  }
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * \@whatItDoes Lets you add a CSS class to an element when the link's route becomes active.
   *
   * \@howToUse
   *
   * ```
   * <a routerLink="/user/bob" routerLinkActive="active-link">Bob</a>
   * ```
   *
   * \@description
   *
   * The RouterLinkActive directive lets you add a CSS class to an element when the link's route
   * becomes active.
   *
   * Consider the following example:
   *
   * ```
   * <a routerLink="/user/bob" routerLinkActive="active-link">Bob</a>
   * ```
   *
   * When the url is either '/user' or '/user/bob', the active-link class will
   * be added to the `a` tag. If the url changes, the class will be removed.
   *
   * You can set more than one class, as follows:
   *
   * ```
   * <a routerLink="/user/bob" routerLinkActive="class1 class2">Bob</a>
   * <a routerLink="/user/bob" [routerLinkActive]="['class1', 'class2']">Bob</a>
   * ```
   *
   * You can configure RouterLinkActive by passing `exact: true`. This will add the classes
   * only when the url matches the link exactly.
   *
   * ```
   * <a routerLink="/user/bob" routerLinkActive="active-link" [routerLinkActiveOptions]="{exact:
   * true}">Bob</a>
   * ```
   *
   * You can assign the RouterLinkActive instance to a template variable and directly check
   * the `isActive` status.
   * ```
   * <a routerLink="/user/bob" routerLinkActive #rla="routerLinkActive">
   *   Bob {{ rla.isActive ? '(already open)' : ''}}
   * </a>
   * ```
   *
   * Finally, you can apply the RouterLinkActive directive to an ancestor of a RouterLink.
   *
   * ```
   * <div routerLinkActive="active-link" [routerLinkActiveOptions]="{exact: true}">
   *   <a routerLink="/user/jim">Jim</a>
   *   <a routerLink="/user/bob">Bob</a>
   * </div>
   * ```
   *
   * This will set the active-link class on the div tag if the url is either '/user/jim' or
   * '/user/bob'.
   *
   * \@ngModule RouterModule
   *
   * \@stable
   */
  var RouterLinkActive = (function () {
      /**
       * @param {?} router
       * @param {?} element
       * @param {?} renderer
       * @param {?} cdr
       */
      function RouterLinkActive(router, element, renderer, cdr) {
          var _this = this;
          this.router = router;
          this.element = element;
          this.renderer = renderer;
          this.cdr = cdr;
          this.classes = [];
          this.active = false;
          this.routerLinkActiveOptions = { exact: false };
          this.subscription = router.events.subscribe(function (s) {
              if (s instanceof NavigationEnd) {
                  _this.update();
              }
          });
      }
      Object.defineProperty(RouterLinkActive.prototype, "isActive", {
          /**
           * @return {?}
           */
          get: function () { return this.active; },
          enumerable: true,
          configurable: true
      });
      /**
       * @return {?}
       */
      RouterLinkActive.prototype.ngAfterContentInit = function () {
          var _this = this;
          this.links.changes.subscribe(function (_) { return _this.update(); });
          this.linksWithHrefs.changes.subscribe(function (_) { return _this.update(); });
          this.update();
      };
      Object.defineProperty(RouterLinkActive.prototype, "routerLinkActive", {
          /**
           * @param {?} data
           * @return {?}
           */
          set: function (data) {
              var /** @type {?} */ classes = Array.isArray(data) ? data : data.split(' ');
              this.classes = classes.filter(function (c) { return !!c; });
          },
          enumerable: true,
          configurable: true
      });
      /**
       * @param {?} changes
       * @return {?}
       */
      RouterLinkActive.prototype.ngOnChanges = function (changes) { this.update(); };
      /**
       * @return {?}
       */
      RouterLinkActive.prototype.ngOnDestroy = function () { this.subscription.unsubscribe(); };
      /**
       * @return {?}
       */
      RouterLinkActive.prototype.update = function () {
          var _this = this;
          if (!this.links || !this.linksWithHrefs || !this.router.navigated)
              return;
          var /** @type {?} */ hasActiveLinks = this.hasActiveLinks();
          // react only when status has changed to prevent unnecessary dom updates
          if (this.active !== hasActiveLinks) {
              this.classes.forEach(function (c) {
                  if (hasActiveLinks) {
                      _this.renderer.addClass(_this.element.nativeElement, c);
                  }
                  else {
                      _this.renderer.removeClass(_this.element.nativeElement, c);
                  }
              });
              Promise.resolve(hasActiveLinks).then(function (active) { return _this.active = active; });
          }
      };
      /**
       * @param {?} router
       * @return {?}
       */
      RouterLinkActive.prototype.isLinkActive = function (router) {
          var _this = this;
          return function (link) { return router.isActive(link.urlTree, _this.routerLinkActiveOptions.exact); };
      };
      /**
       * @return {?}
       */
      RouterLinkActive.prototype.hasActiveLinks = function () {
          return this.links.some(this.isLinkActive(this.router)) ||
              this.linksWithHrefs.some(this.isLinkActive(this.router));
      };
      return RouterLinkActive;
  }());
  RouterLinkActive.decorators = [
      { type: _angular_core.Directive, args: [{
                  selector: '[routerLinkActive]',
                  exportAs: 'routerLinkActive',
              },] },
  ];
  /**
   * @nocollapse
   */
  RouterLinkActive.ctorParameters = function () { return [
      { type: Router, },
      { type: _angular_core.ElementRef, },
      { type: _angular_core.Renderer2, },
      { type: _angular_core.ChangeDetectorRef, },
  ]; };
  RouterLinkActive.propDecorators = {
      'links': [{ type: _angular_core.ContentChildren, args: [RouterLink, { descendants: true },] },],
      'linksWithHrefs': [{ type: _angular_core.ContentChildren, args: [RouterLinkWithHref, { descendants: true },] },],
      'routerLinkActiveOptions': [{ type: _angular_core.Input },],
      'routerLinkActive': [{ type: _angular_core.Input },],
  };
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * Store contextual information about a {\@link RouterOutlet}
   *
   * \@stable
   */
  var OutletContext = (function () {
      function OutletContext() {
          this.outlet = null;
          this.route = null;
          this.resolver = null;
          this.children = new ChildrenOutletContexts();
          this.attachRef = null;
      }
      return OutletContext;
  }());
  /**
   * Store contextual information about the children (= nested) {\@link RouterOutlet}
   *
   * \@stable
   */
  var ChildrenOutletContexts = (function () {
      function ChildrenOutletContexts() {
          this.contexts = new Map();
      }
      /**
       * Called when a `RouterOutlet` directive is instantiated
       * @param {?} childName
       * @param {?} outlet
       * @return {?}
       */
      ChildrenOutletContexts.prototype.onChildOutletCreated = function (childName, outlet) {
          var /** @type {?} */ context = this.getOrCreateContext(childName);
          context.outlet = outlet;
          this.contexts.set(childName, context);
      };
      /**
       * Called when a `RouterOutlet` directive is destroyed.
       * We need to keep the context as the outlet could be destroyed inside a NgIf and might be
       * re-created later.
       * @param {?} childName
       * @return {?}
       */
      ChildrenOutletContexts.prototype.onChildOutletDestroyed = function (childName) {
          var /** @type {?} */ context = this.getContext(childName);
          if (context) {
              context.outlet = null;
          }
      };
      /**
       * Called when the corresponding route is deactivated during navigation.
       * Because the component get destroyed, all children outlet are destroyed.
       * @return {?}
       */
      ChildrenOutletContexts.prototype.onOutletDeactivated = function () {
          var /** @type {?} */ contexts = this.contexts;
          this.contexts = new Map();
          return contexts;
      };
      /**
       * @param {?} contexts
       * @return {?}
       */
      ChildrenOutletContexts.prototype.onOutletReAttached = function (contexts) { this.contexts = contexts; };
      /**
       * @param {?} childName
       * @return {?}
       */
      ChildrenOutletContexts.prototype.getOrCreateContext = function (childName) {
          var /** @type {?} */ context = this.getContext(childName);
          if (!context) {
              context = new OutletContext();
              this.contexts.set(childName, context);
          }
          return context;
      };
      /**
       * @param {?} childName
       * @return {?}
       */
      ChildrenOutletContexts.prototype.getContext = function (childName) { return this.contexts.get(childName) || null; };
      return ChildrenOutletContexts;
  }());
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * \@whatItDoes Acts as a placeholder that Angular dynamically fills based on the current router
   * state.
   *
   * \@howToUse
   *
   * ```
   * <router-outlet></router-outlet>
   * <router-outlet name='left'></router-outlet>
   * <router-outlet name='right'></router-outlet>
   * ```
   *
   * A router outlet will emit an activate event any time a new component is being instantiated,
   * and a deactivate event when it is being destroyed.
   *
   * ```
   * <router-outlet
   *   (activate)='onActivate($event)'
   *   (deactivate)='onDeactivate($event)'></router-outlet>
   * ```
   * \@ngModule RouterModule
   *
   * \@stable
   */
  var RouterOutlet = (function () {
      /**
       * @param {?} parentContexts
       * @param {?} location
       * @param {?} resolver
       * @param {?} name
       * @param {?} changeDetector
       */
      function RouterOutlet(parentContexts, location, resolver, name, changeDetector) {
          this.parentContexts = parentContexts;
          this.location = location;
          this.resolver = resolver;
          this.changeDetector = changeDetector;
          this.activated = null;
          this._activatedRoute = null;
          this.activateEvents = new _angular_core.EventEmitter();
          this.deactivateEvents = new _angular_core.EventEmitter();
          this.name = name || PRIMARY_OUTLET;
          parentContexts.onChildOutletCreated(this.name, this);
      }
      /**
       * @return {?}
       */
      RouterOutlet.prototype.ngOnDestroy = function () { this.parentContexts.onChildOutletDestroyed(this.name); };
      /**
       * @return {?}
       */
      RouterOutlet.prototype.ngOnInit = function () {
          if (!this.activated) {
              // If the outlet was not instantiated at the time the route got activated we need to populate
              // the outlet when it is initialized (ie inside a NgIf)
              var /** @type {?} */ context = this.parentContexts.getContext(this.name);
              if (context && context.route) {
                  if (context.attachRef) {
                      // `attachRef` is populated when there is an existing component to mount
                      this.attach(context.attachRef, context.route);
                  }
                  else {
                      // otherwise the component defined in the configuration is created
                      this.activateWith(context.route, context.resolver || null);
                  }
              }
          }
      };
      Object.defineProperty(RouterOutlet.prototype, "locationInjector", {
          /**
           * @deprecated since v4 *
           * @return {?}
           */
          get: function () { return this.location.injector; },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(RouterOutlet.prototype, "locationFactoryResolver", {
          /**
           * @deprecated since v4 *
           * @return {?}
           */
          get: function () { return this.resolver; },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(RouterOutlet.prototype, "isActivated", {
          /**
           * @return {?}
           */
          get: function () { return !!this.activated; },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(RouterOutlet.prototype, "component", {
          /**
           * @return {?}
           */
          get: function () {
              if (!this.activated)
                  throw new Error('Outlet is not activated');
              return this.activated.instance;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(RouterOutlet.prototype, "activatedRoute", {
          /**
           * @return {?}
           */
          get: function () {
              if (!this.activated)
                  throw new Error('Outlet is not activated');
              return (this._activatedRoute);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(RouterOutlet.prototype, "activatedRouteData", {
          /**
           * @return {?}
           */
          get: function () {
              if (this._activatedRoute) {
                  return this._activatedRoute.snapshot.data;
              }
              return {};
          },
          enumerable: true,
          configurable: true
      });
      /**
       * Called when the `RouteReuseStrategy` instructs to detach the subtree
       * @return {?}
       */
      RouterOutlet.prototype.detach = function () {
          if (!this.activated)
              throw new Error('Outlet is not activated');
          this.location.detach();
          var /** @type {?} */ cmp = this.activated;
          this.activated = null;
          this._activatedRoute = null;
          return cmp;
      };
      /**
       * Called when the `RouteReuseStrategy` instructs to re-attach a previously detached subtree
       * @param {?} ref
       * @param {?} activatedRoute
       * @return {?}
       */
      RouterOutlet.prototype.attach = function (ref, activatedRoute) {
          this.activated = ref;
          this._activatedRoute = activatedRoute;
          this.location.insert(ref.hostView);
      };
      /**
       * @return {?}
       */
      RouterOutlet.prototype.deactivate = function () {
          if (this.activated) {
              var /** @type {?} */ c = this.component;
              this.activated.destroy();
              this.activated = null;
              this._activatedRoute = null;
              this.deactivateEvents.emit(c);
          }
      };
      /**
       * @param {?} activatedRoute
       * @param {?} resolver
       * @return {?}
       */
      RouterOutlet.prototype.activateWith = function (activatedRoute, resolver) {
          if (this.isActivated) {
              throw new Error('Cannot activate an already activated outlet');
          }
          this._activatedRoute = activatedRoute;
          var /** @type {?} */ snapshot = activatedRoute._futureSnapshot;
          var /** @type {?} */ component = (((snapshot._routeConfig)).component);
          resolver = resolver || this.resolver;
          var /** @type {?} */ factory = resolver.resolveComponentFactory(component);
          var /** @type {?} */ childContexts = this.parentContexts.getOrCreateContext(this.name).children;
          var /** @type {?} */ injector = new OutletInjector(activatedRoute, childContexts, this.location.injector);
          this.activated = this.location.createComponent(factory, this.location.length, injector);
          // Calling `markForCheck` to make sure we will run the change detection when the
          // `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
          this.changeDetector.markForCheck();
          this.activateEvents.emit(this.activated.instance);
      };
      return RouterOutlet;
  }());
  RouterOutlet.decorators = [
      { type: _angular_core.Directive, args: [{ selector: 'router-outlet', exportAs: 'outlet' },] },
  ];
  /**
   * @nocollapse
   */
  RouterOutlet.ctorParameters = function () { return [
      { type: ChildrenOutletContexts, },
      { type: _angular_core.ViewContainerRef, },
      { type: _angular_core.ComponentFactoryResolver, },
      { type: undefined, decorators: [{ type: _angular_core.Attribute, args: ['name',] },] },
      { type: _angular_core.ChangeDetectorRef, },
  ]; };
  RouterOutlet.propDecorators = {
      'activateEvents': [{ type: _angular_core.Output, args: ['activate',] },],
      'deactivateEvents': [{ type: _angular_core.Output, args: ['deactivate',] },],
  };
  var OutletInjector = (function () {
      /**
       * @param {?} route
       * @param {?} childContexts
       * @param {?} parent
       */
      function OutletInjector(route, childContexts, parent) {
          this.route = route;
          this.childContexts = childContexts;
          this.parent = parent;
      }
      /**
       * @param {?} token
       * @param {?=} notFoundValue
       * @return {?}
       */
      OutletInjector.prototype.get = function (token, notFoundValue) {
          if (token === ActivatedRoute) {
              return this.route;
          }
          if (token === ChildrenOutletContexts) {
              return this.childContexts;
          }
          return this.parent.get(token, notFoundValue);
      };
      return OutletInjector;
  }());
  /**
  *@license
  *Copyright Google Inc. All Rights Reserved.
  *
  *Use of this source code is governed by an MIT-style license that can be
  *found in the LICENSE file at https://angular.io/license
  */
  /**
   * \@whatItDoes Provides a preloading strategy.
   *
   * \@experimental
   * @abstract
   */
  var PreloadingStrategy = (function () {
      function PreloadingStrategy() {
      }
      /**
       * @abstract
       * @param {?} route
       * @param {?} fn
       * @return {?}
       */
      PreloadingStrategy.prototype.preload = function (route, fn) { };
      return PreloadingStrategy;
  }());
  /**
   * \@whatItDoes Provides a preloading strategy that preloads all modules as quickly as possible.
   *
   * \@howToUse
   *
   * ```
   * RouteModule.forRoot(ROUTES, {preloadingStrategy: PreloadAllModules})
   * ```
   *
   * \@experimental
   */
  var PreloadAllModules = (function () {
      function PreloadAllModules() {
      }
      /**
       * @param {?} route
       * @param {?} fn
       * @return {?}
       */
      PreloadAllModules.prototype.preload = function (route, fn) {
          return rxjs_operator_catch._catch.call(fn(), function () { return rxjs_observable_of.of(null); });
      };
      return PreloadAllModules;
  }());
  /**
   * \@whatItDoes Provides a preloading strategy that does not preload any modules.
   *
   * \@description
   *
   * This strategy is enabled by default.
   *
   * \@experimental
   */
  var NoPreloading = (function () {
      function NoPreloading() {
      }
      /**
       * @param {?} route
       * @param {?} fn
       * @return {?}
       */
      NoPreloading.prototype.preload = function (route, fn) { return rxjs_observable_of.of(null); };
      return NoPreloading;
  }());
  /**
   * The preloader optimistically loads all router configurations to
   * make navigations into lazily-loaded sections of the application faster.
   *
   * The preloader runs in the background. When the router bootstraps, the preloader
   * starts listening to all navigation events. After every such event, the preloader
   * will check if any configurations can be loaded lazily.
   *
   * If a route is protected by `canLoad` guards, the preloaded will not load it.
   *
   * \@stable
   */
  var RouterPreloader = (function () {
      /**
       * @param {?} router
       * @param {?} moduleLoader
       * @param {?} compiler
       * @param {?} injector
       * @param {?} preloadingStrategy
       */
      function RouterPreloader(router, moduleLoader, compiler, injector, preloadingStrategy) {
          this.router = router;
          this.injector = injector;
          this.preloadingStrategy = preloadingStrategy;
          var onStartLoad = function (r) { return router.triggerEvent(new RouteConfigLoadStart(r)); };
          var onEndLoad = function (r) { return router.triggerEvent(new RouteConfigLoadEnd(r)); };
          this.loader = new RouterConfigLoader(moduleLoader, compiler, onStartLoad, onEndLoad);
      }
      
      /**
       * @return {?}
       */
      RouterPreloader.prototype.setUpPreloading = function () {
          var _this = this;
          var /** @type {?} */ navigations$ = rxjs_operator_filter.filter.call(this.router.events, function (e) { return e instanceof NavigationEnd; });
          this.subscription = rxjs_operator_concatMap.concatMap.call(navigations$, function () { return _this.preload(); }).subscribe(function () { });
      };
      /**
       * @return {?}
       */
      RouterPreloader.prototype.preload = function () {
          var /** @type {?} */ ngModule = this.injector.get(_angular_core.NgModuleRef);
          return this.processRoutes(ngModule, this.router.config);
      };
      /**
       * @return {?}
       */
      RouterPreloader.prototype.ngOnDestroy = function () { this.subscription.unsubscribe(); };
      /**
       * @param {?} ngModule
       * @param {?} routes
       * @return {?}
       */
      RouterPreloader.prototype.processRoutes = function (ngModule, routes) {
          var /** @type {?} */ res = [];
          for (var _i = 0, routes_5 = routes; _i < routes_5.length; _i++) {
              var route = routes_5[_i];
              // we already have the config loaded, just recurse
              if (route.loadChildren && !route.canLoad && route._loadedConfig) {
                  var /** @type {?} */ childConfig = route._loadedConfig;
                  res.push(this.processRoutes(childConfig.module, childConfig.routes));
                  // no config loaded, fetch the config
              }
              else if (route.loadChildren && !route.canLoad) {
                  res.push(this.preloadConfig(ngModule, route));
                  // recurse into children
              }
              else if (route.children) {
                  res.push(this.processRoutes(ngModule, route.children));
              }
          }
          return rxjs_operator_mergeAll.mergeAll.call(rxjs_observable_from.from(res));
      };
      /**
       * @param {?} ngModule
       * @param {?} route
       * @return {?}
       */
      RouterPreloader.prototype.preloadConfig = function (ngModule, route) {
          var _this = this;
          return this.preloadingStrategy.preload(route, function () {
              var /** @type {?} */ loaded$ = _this.loader.load(ngModule.injector, route);
              return rxjs_operator_mergeMap.mergeMap.call(loaded$, function (config) {
                  route._loadedConfig = config;
                  return _this.processRoutes(config.module, config.routes);
              });
          });
      };
      return RouterPreloader;
  }());
  RouterPreloader.decorators = [
      { type: _angular_core.Injectable },
  ];
  /**
   * @nocollapse
   */
  RouterPreloader.ctorParameters = function () { return [
      { type: Router, },
      { type: _angular_core.NgModuleFactoryLoader, },
      { type: _angular_core.Compiler, },
      { type: _angular_core.Injector, },
      { type: PreloadingStrategy, },
  ]; };
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * \@whatItDoes Contains a list of directives
   * \@stable
   */
  var ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive];
  /**
   * \@whatItDoes Is used in DI to configure the router.
   * \@stable
   */
  var ROUTER_CONFIGURATION = new _angular_core.InjectionToken('ROUTER_CONFIGURATION');
  /**
   * \@docsNotRequired
   */
  var ROUTER_FORROOT_GUARD = new _angular_core.InjectionToken('ROUTER_FORROOT_GUARD');
  var ROUTER_PROVIDERS = [
      _angular_common.Location,
      { provide: UrlSerializer, useClass: DefaultUrlSerializer },
      {
          provide: Router,
          useFactory: setupRouter,
          deps: [
              _angular_core.ApplicationRef, UrlSerializer, ChildrenOutletContexts, _angular_common.Location, _angular_core.Injector,
              _angular_core.NgModuleFactoryLoader, _angular_core.Compiler, ROUTES, ROUTER_CONFIGURATION,
              [UrlHandlingStrategy, new _angular_core.Optional()], [RouteReuseStrategy, new _angular_core.Optional()]
          ]
      },
      ChildrenOutletContexts,
      { provide: ActivatedRoute, useFactory: rootRoute, deps: [Router] },
      { provide: _angular_core.NgModuleFactoryLoader, useClass: _angular_core.SystemJsNgModuleLoader },
      RouterPreloader,
      NoPreloading,
      PreloadAllModules,
      { provide: ROUTER_CONFIGURATION, useValue: { enableTracing: false } },
  ];
  /**
   * @return {?}
   */
  function routerNgProbeToken() {
      return new _angular_core.NgProbeToken('Router', Router);
  }
  /**
   * \@whatItDoes Adds router directives and providers.
   *
   * \@howToUse
   *
   * RouterModule can be imported multiple times: once per lazily-loaded bundle.
   * Since the router deals with a global shared resource--location, we cannot have
   * more than one router service active.
   *
   * That is why there are two ways to create the module: `RouterModule.forRoot` and
   * `RouterModule.forChild`.
   *
   * * `forRoot` creates a module that contains all the directives, the given routes, and the router
   *   service itself.
   * * `forChild` creates a module that contains all the directives and the given routes, but does not
   *   include the router service.
   *
   * When registered at the root, the module should be used as follows
   *
   * ```
   * \@NgModule({
   *   imports: [RouterModule.forRoot(ROUTES)]
   * })
   * class MyNgModule {}
   * ```
   *
   * For submodules and lazy loaded submodules the module should be used as follows:
   *
   * ```
   * \@NgModule({
   *   imports: [RouterModule.forChild(ROUTES)]
   * })
   * class MyNgModule {}
   * ```
   *
   * \@description
   *
   * Managing state transitions is one of the hardest parts of building applications. This is
   * especially true on the web, where you also need to ensure that the state is reflected in the URL.
   * In addition, we often want to split applications into multiple bundles and load them on demand.
   * Doing this transparently is not trivial.
   *
   * The Angular router solves these problems. Using the router, you can declaratively specify
   * application states, manage state transitions while taking care of the URL, and load bundles on
   * demand.
   *
   * [Read this developer guide](https://angular.io/docs/ts/latest/guide/router.html) to get an
   * overview of how the router should be used.
   *
   * \@stable
   */
  var RouterModule = (function () {
      /**
       * @param {?} guard
       * @param {?} router
       */
      function RouterModule(guard, router) {
      }
      /**
       * Creates a module with all the router providers and directives. It also optionally sets up an
       * application listener to perform an initial navigation.
       *
       * Options:
       * * `enableTracing` makes the router log all its internal events to the console.
       * * `useHash` enables the location strategy that uses the URL fragment instead of the history
       * API.
       * * `initialNavigation` disables the initial navigation.
       * * `errorHandler` provides a custom error handler.
       * @param {?} routes
       * @param {?=} config
       * @return {?}
       */
      RouterModule.forRoot = function (routes, config) {
          return {
              ngModule: RouterModule,
              providers: [
                  ROUTER_PROVIDERS,
                  provideRoutes(routes),
                  {
                      provide: ROUTER_FORROOT_GUARD,
                      useFactory: provideForRootGuard,
                      deps: [[Router, new _angular_core.Optional(), new _angular_core.SkipSelf()]]
                  },
                  { provide: ROUTER_CONFIGURATION, useValue: config ? config : {} },
                  {
                      provide: _angular_common.LocationStrategy,
                      useFactory: provideLocationStrategy,
                      deps: [
                          _angular_common.PlatformLocation, [new _angular_core.Inject(_angular_common.APP_BASE_HREF), new _angular_core.Optional()], ROUTER_CONFIGURATION
                      ]
                  },
                  {
                      provide: PreloadingStrategy,
                      useExisting: config && config.preloadingStrategy ? config.preloadingStrategy :
                          NoPreloading
                  },
                  { provide: _angular_core.NgProbeToken, multi: true, useFactory: routerNgProbeToken },
                  provideRouterInitializer(),
              ],
          };
      };
      /**
       * Creates a module with all the router directives and a provider registering routes.
       * @param {?} routes
       * @return {?}
       */
      RouterModule.forChild = function (routes) {
          return { ngModule: RouterModule, providers: [provideRoutes(routes)] };
      };
      return RouterModule;
  }());
  RouterModule.decorators = [
      { type: _angular_core.NgModule, args: [{ declarations: ROUTER_DIRECTIVES, exports: ROUTER_DIRECTIVES },] },
  ];
  /**
   * @nocollapse
   */
  RouterModule.ctorParameters = function () { return [
      { type: undefined, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Inject, args: [ROUTER_FORROOT_GUARD,] },] },
      { type: Router, decorators: [{ type: _angular_core.Optional },] },
  ]; };
  /**
   * @param {?} platformLocationStrategy
   * @param {?} baseHref
   * @param {?=} options
   * @return {?}
   */
  function provideLocationStrategy(platformLocationStrategy, baseHref, options) {
      if (options === void 0) { options = {}; }
      return options.useHash ? new _angular_common.HashLocationStrategy(platformLocationStrategy, baseHref) :
          new _angular_common.PathLocationStrategy(platformLocationStrategy, baseHref);
  }
  /**
   * @param {?} router
   * @return {?}
   */
  function provideForRootGuard(router) {
      if (router) {
          throw new Error("RouterModule.forRoot() called twice. Lazy loaded modules should use RouterModule.forChild() instead.");
      }
      return 'guarded';
  }
  /**
   * \@whatItDoes Registers routes.
   *
   * \@howToUse
   *
   * ```
   * \@NgModule({
   *   imports: [RouterModule.forChild(ROUTES)],
   *   providers: [provideRoutes(EXTRA_ROUTES)]
   * })
   * class MyNgModule {}
   * ```
   *
   * \@stable
   * @param {?} routes
   * @return {?}
   */
  function provideRoutes(routes) {
      return [
          { provide: _angular_core.ANALYZE_FOR_ENTRY_COMPONENTS, multi: true, useValue: routes },
          { provide: ROUTES, multi: true, useValue: routes },
      ];
  }
  /**
   * @param {?} ref
   * @param {?} urlSerializer
   * @param {?} contexts
   * @param {?} location
   * @param {?} injector
   * @param {?} loader
   * @param {?} compiler
   * @param {?} config
   * @param {?=} opts
   * @param {?=} urlHandlingStrategy
   * @param {?=} routeReuseStrategy
   * @return {?}
   */
  function setupRouter(ref, urlSerializer, contexts, location, injector, loader, compiler, config, opts, urlHandlingStrategy, routeReuseStrategy) {
      if (opts === void 0) { opts = {}; }
      var /** @type {?} */ router = new Router(null, urlSerializer, contexts, location, injector, loader, compiler, flatten(config));
      if (urlHandlingStrategy) {
          router.urlHandlingStrategy = urlHandlingStrategy;
      }
      if (routeReuseStrategy) {
          router.routeReuseStrategy = routeReuseStrategy;
      }
      if (opts.errorHandler) {
          router.errorHandler = opts.errorHandler;
      }
      if (opts.enableTracing) {
          var /** @type {?} */ dom_1 = _angular_platformBrowser.ɵgetDOM();
          router.events.subscribe(function (e) {
              dom_1.logGroup("Router Event: " + ((e.constructor)).name);
              dom_1.log(e.toString());
              dom_1.log(e);
              dom_1.logGroupEnd();
          });
      }
      return router;
  }
  /**
   * @param {?} router
   * @return {?}
   */
  function rootRoute(router) {
      return router.routerState.root;
  }
  /**
   * To initialize the router properly we need to do in two steps:
   *
   * We need to start the navigation in a APP_INITIALIZER to block the bootstrap if
   * a resolver or a guards executes asynchronously. Second, we need to actually run
   * activation in a BOOTSTRAP_LISTENER. We utilize the afterPreactivation
   * hook provided by the router to do that.
   *
   * The router navigation starts, reaches the point when preactivation is done, and then
   * pauses. It waits for the hook to be resolved. We then resolve it only in a bootstrap listener.
   */
  var RouterInitializer = (function () {
      /**
       * @param {?} injector
       */
      function RouterInitializer(injector) {
          this.injector = injector;
          this.initNavigation = false;
          this.resultOfPreactivationDone = new rxjs_Subject.Subject();
      }
      /**
       * @return {?}
       */
      RouterInitializer.prototype.appInitializer = function () {
          var _this = this;
          var /** @type {?} */ p = this.injector.get(_angular_common.LOCATION_INITIALIZED, Promise.resolve(null));
          return p.then(function () {
              var /** @type {?} */ resolve = ((null));
              var /** @type {?} */ res = new Promise(function (r) { return resolve = r; });
              var /** @type {?} */ router = _this.injector.get(Router);
              var /** @type {?} */ opts = _this.injector.get(ROUTER_CONFIGURATION);
              if (_this.isLegacyDisabled(opts) || _this.isLegacyEnabled(opts)) {
                  resolve(true);
              }
              else if (opts.initialNavigation === 'disabled') {
                  router.setUpLocationChangeListener();
                  resolve(true);
              }
              else if (opts.initialNavigation === 'enabled') {
                  router.hooks.afterPreactivation = function () {
                      // only the initial navigation should be delayed
                      if (!_this.initNavigation) {
                          _this.initNavigation = true;
                          resolve(true);
                          return _this.resultOfPreactivationDone;
                          // subsequent navigations should not be delayed
                      }
                      else {
                          return (rxjs_observable_of.of(null));
                      }
                  };
                  router.initialNavigation();
              }
              else {
                  throw new Error("Invalid initialNavigation options: '" + opts.initialNavigation + "'");
              }
              return res;
          });
      };
      /**
       * @param {?} bootstrappedComponentRef
       * @return {?}
       */
      RouterInitializer.prototype.bootstrapListener = function (bootstrappedComponentRef) {
          var /** @type {?} */ opts = this.injector.get(ROUTER_CONFIGURATION);
          var /** @type {?} */ preloader = this.injector.get(RouterPreloader);
          var /** @type {?} */ router = this.injector.get(Router);
          var /** @type {?} */ ref = this.injector.get(_angular_core.ApplicationRef);
          if (bootstrappedComponentRef !== ref.components[0]) {
              return;
          }
          if (this.isLegacyEnabled(opts)) {
              router.initialNavigation();
          }
          else if (this.isLegacyDisabled(opts)) {
              router.setUpLocationChangeListener();
          }
          preloader.setUpPreloading();
          router.resetRootComponentType(ref.componentTypes[0]);
          this.resultOfPreactivationDone.next(/** @type {?} */ ((null)));
          this.resultOfPreactivationDone.complete();
      };
      /**
       * @param {?} opts
       * @return {?}
       */
      RouterInitializer.prototype.isLegacyEnabled = function (opts) {
          return opts.initialNavigation === 'legacy_enabled' || opts.initialNavigation === true ||
              opts.initialNavigation === undefined;
      };
      /**
       * @param {?} opts
       * @return {?}
       */
      RouterInitializer.prototype.isLegacyDisabled = function (opts) {
          return opts.initialNavigation === 'legacy_disabled' || opts.initialNavigation === false;
      };
      return RouterInitializer;
  }());
  RouterInitializer.decorators = [
      { type: _angular_core.Injectable },
  ];
  /**
   * @nocollapse
   */
  RouterInitializer.ctorParameters = function () { return [
      { type: _angular_core.Injector, },
  ]; };
  /**
   * @param {?} r
   * @return {?}
   */
  function getAppInitializer(r) {
      return r.appInitializer.bind(r);
  }
  /**
   * @param {?} r
   * @return {?}
   */
  function getBootstrapListener(r) {
      return r.bootstrapListener.bind(r);
  }
  /**
   * A token for the router initializer that will be called after the app is bootstrapped.
   *
   * \@experimental
   */
  var ROUTER_INITIALIZER = new _angular_core.InjectionToken('Router Initializer');
  /**
   * @return {?}
   */
  function provideRouterInitializer() {
      return [
          RouterInitializer,
          {
              provide: _angular_core.APP_INITIALIZER,
              multi: true,
              useFactory: getAppInitializer,
              deps: [RouterInitializer]
          },
          { provide: ROUTER_INITIALIZER, useFactory: getBootstrapListener, deps: [RouterInitializer] },
          { provide: _angular_core.APP_BOOTSTRAP_LISTENER, multi: true, useExisting: ROUTER_INITIALIZER },
      ];
  }
  /**
   * @license
   * Copyright Google Inc. All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  /**
   * @module
   * @description
   * Entry point for all public APIs of the common package.
   */
  /**
   * \@stable
   */
  var VERSION = new _angular_core.Version('4.3.4');
  
  exports.RouterLink = RouterLink;
  exports.RouterLinkWithHref = RouterLinkWithHref;
  exports.RouterLinkActive = RouterLinkActive;
  exports.RouterOutlet = RouterOutlet;
  exports.GuardsCheckEnd = GuardsCheckEnd;
  exports.GuardsCheckStart = GuardsCheckStart;
  exports.NavigationCancel = NavigationCancel;
  exports.NavigationEnd = NavigationEnd;
  exports.NavigationError = NavigationError;
  exports.NavigationStart = NavigationStart;
  exports.ResolveEnd = ResolveEnd;
  exports.ResolveStart = ResolveStart;
  exports.RouteConfigLoadEnd = RouteConfigLoadEnd;
  exports.RouteConfigLoadStart = RouteConfigLoadStart;
  exports.RoutesRecognized = RoutesRecognized;
  exports.RouteReuseStrategy = RouteReuseStrategy;
  exports.Router = Router;
  exports.ROUTES = ROUTES;
  exports.ROUTER_CONFIGURATION = ROUTER_CONFIGURATION;
  exports.ROUTER_INITIALIZER = ROUTER_INITIALIZER;
  exports.RouterModule = RouterModule;
  exports.provideRoutes = provideRoutes;
  exports.ChildrenOutletContexts = ChildrenOutletContexts;
  exports.OutletContext = OutletContext;
  exports.NoPreloading = NoPreloading;
  exports.PreloadAllModules = PreloadAllModules;
  exports.PreloadingStrategy = PreloadingStrategy;
  exports.RouterPreloader = RouterPreloader;
  exports.ActivatedRoute = ActivatedRoute;
  exports.ActivatedRouteSnapshot = ActivatedRouteSnapshot;
  exports.RouterState = RouterState;
  exports.RouterStateSnapshot = RouterStateSnapshot;
  exports.PRIMARY_OUTLET = PRIMARY_OUTLET;
  exports.convertToParamMap = convertToParamMap;
  exports.UrlHandlingStrategy = UrlHandlingStrategy;
  exports.DefaultUrlSerializer = DefaultUrlSerializer;
  exports.UrlSegment = UrlSegment;
  exports.UrlSegmentGroup = UrlSegmentGroup;
  exports.UrlSerializer = UrlSerializer;
  exports.UrlTree = UrlTree;
  exports.VERSION = VERSION;
  exports.ɵROUTER_PROVIDERS = ROUTER_PROVIDERS;
  exports.ɵflatten = flatten;
  exports.ɵa = ROUTER_FORROOT_GUARD;
  exports.ɵg = RouterInitializer;
  exports.ɵh = getAppInitializer;
  exports.ɵi = getBootstrapListener;
  exports.ɵd = provideForRootGuard;
  exports.ɵc = provideLocationStrategy;
  exports.ɵj = provideRouterInitializer;
  exports.ɵf = rootRoute;
  exports.ɵb = routerNgProbeToken;
  exports.ɵe = setupRouter;
  exports.ɵk = Tree;
  exports.ɵl = TreeNode;
  
  Object.defineProperty(exports, '__esModule', { value: true });
  
  })));
  //# sourceMappingURL=router.umd.js.map
  