resolve method

Resolves a typed destination without using a route-name string.

Implementation

ResolvedNavigationTarget resolve(final NavigationTarget<Object?> target) {
  target.presentation?.validate();
  final List<ResolvedNavigationTarget> candidates =
      <ResolvedNavigationTarget>[];
  for (final NavigationMount candidateMount in mounts) {
    if (!candidateMount.enabled ||
        (target.mountId != null && candidateMount.id != target.mountId)) {
      continue;
    }
    if (target.mountId == null &&
        target.scopeId != null &&
        candidateMount.scopeId != target.scopeId) {
      continue;
    }
    final NavigationModule candidateModule = module(candidateMount.moduleId);
    for (final NavigationRouteDefinitionBase definition
        in candidateModule.routes) {
      if (!definition.accepts(target.destination)) {
        continue;
      }
      final NavigationScopeId scopeId =
          target.scopeId ?? candidateMount.scopeId;
      scope(scopeId);
      final Uri? relative = definition.encode(target.destination);
      candidates.add(
        ResolvedNavigationTarget(
          target: NavigationTarget<Object?>(
            destination: target.destination,
            mountId: candidateMount.id,
            scopeId: scopeId,
            presentation: target.presentation,
          ),
          definition: definition,
          module: candidateModule,
          mount: candidateMount,
          scopeId: scopeId,
          uri: relative == null
              ? null
              : NavigationUris.mount(candidateMount.pathPrefix, relative),
        ),
      );
    }
  }
  if (candidates.isEmpty) {
    throw StateError(
      'No enabled navigation route accepts '
      '${target.destination.runtimeType}.',
    );
  }
  if (candidates.length > 1) {
    throw StateError(
      '${target.destination.runtimeType} resolves to multiple mounts. '
      'Provide an exact NavigationMountId.',
    );
  }
  return candidates.single;
}