// clean
  protected RepositoryListResourceResponse listRepositories(
      Request request, boolean allReposes, boolean includeGroups) throws ResourceException {
    RepositoryListResourceResponse result = new RepositoryListResourceResponse();

    RepositoryListResource repoRes;

    Collection<Repository> repositories = getRepositoryRegistry().getRepositories();

    for (Repository repository : repositories) {
      // To save UI changes at the moment, not including groups in repo call
      if ((allReposes || repository.isUserManaged())
          && (includeGroups
              || !repository.getRepositoryKind().isFacetAvailable(GroupRepository.class))) {
        repoRes = new RepositoryListResource();

        repoRes.setResourceURI(createRepositoryReference(request, repository.getId()).toString());

        repoRes.setContentResourceURI(
            repositoryURLBuilder.getExposedRepositoryContentUrl(repository));

        repoRes.setRepoType(getRestRepoType(repository));

        repoRes.setProvider(NexusCompat.getRepositoryProviderHint(repository));

        repoRes.setProviderRole(NexusCompat.getRepositoryProviderRole(repository));

        repoRes.setFormat(repository.getRepositoryContentClass().getId());

        repoRes.setId(repository.getId());

        repoRes.setName(repository.getName());

        repoRes.setUserManaged(repository.isUserManaged());

        repoRes.setExposed(repository.isExposed());

        repoRes.setEffectiveLocalStorageUrl(repository.getLocalUrl());

        if (repository.getRepositoryKind().isFacetAvailable(MavenRepository.class)) {
          repoRes.setRepoPolicy(
              repository.adaptToFacet(MavenRepository.class).getRepositoryPolicy().toString());
        }

        if (repository.getRepositoryKind().isFacetAvailable(ProxyRepository.class)) {
          repoRes.setRemoteUri(repository.adaptToFacet(ProxyRepository.class).getRemoteUrl());
        }

        result.addData(repoRes);
      }
    }

    return result;
  }
  protected Collection<StorageItem> listVirtualPath(
      ResourceStoreRequest request, RequestRoute route) throws ItemNotFoundException {
    if (route.getRequestDepth() == 0) {
      // 1st level
      ArrayList<StorageItem> result = new ArrayList<StorageItem>();

      for (RepositoryTypeDescriptor rtd :
          repositoryTypeRegistry.getRegisteredRepositoryTypeDescriptors()) {
        // check is there any repo registered
        if (!repositoryRegistry.getRepositoriesWithFacet(rtd.getRole()).isEmpty()) {
          ResourceStoreRequest req =
              new ResourceStoreRequest(
                  ItemPathUtils.concatPaths(request.getRequestPath(), rtd.getPrefix()));

          DefaultStorageCollectionItem repositories =
              new DefaultStorageCollectionItem(this, req, true, false);

          repositories.getItemContext().putAll(request.getRequestContext());

          result.add(repositories);
        }
      }

      return result;
    } else if (route.getRequestDepth() == 1) {
      // 2nd level
      List<? extends Repository> repositories = null;

      Class<? extends Repository> kind = null;

      for (RepositoryTypeDescriptor rtd :
          repositoryTypeRegistry.getRegisteredRepositoryTypeDescriptors()) {
        if (route.getStrippedPrefix().startsWith("/" + rtd.getPrefix())) {
          kind = rtd.getRole();

          repositories = repositoryRegistry.getRepositoriesWithFacet(kind);

          break;
        }
      }

      // if no prefix matched, Item not found
      if (repositories == null || repositories.isEmpty()) {
        throw new ItemNotFoundException(request);
      }

      // filter access to the repositories
      // NOTE: do this AFTER the null/empty check so we return an empty list vs. an ItemNotFound
      repositories = filterAccessToRepositories(repositories);

      ArrayList<StorageItem> result = new ArrayList<StorageItem>(repositories.size());

      for (Repository repository : repositories) {
        if (repository.isExposed() && repository.isBrowseable()) {
          DefaultStorageCollectionItem repoItem = null;

          ResourceStoreRequest req = null;

          if (Repository.class.equals(kind)) {
            req =
                new ResourceStoreRequest(
                    ItemPathUtils.concatPaths(request.getRequestPath(), repository.getId()));
          } else {
            req =
                new ResourceStoreRequest(
                    ItemPathUtils.concatPaths(
                        request.getRequestPath(), repository.getPathPrefix()));
          }

          repoItem = new DefaultStorageCollectionItem(this, req, true, false);

          repoItem.getItemContext().putAll(request.getRequestContext());

          result.add(repoItem);
        }
      }

      return result;
    } else {
      throw new ItemNotFoundException(request);
    }
  }
  // XXX: a todo here is to make the "aliases" ("groups" for GroupRepository.class) dynamic,
  // and even think about new layout: every kind should have it's own "folder", you don't want to
  // see
  // maven2 and P2 repositories along each other...
  public RequestRoute getRequestRouteForRequest(ResourceStoreRequest request)
      throws ItemNotFoundException {
    RequestRoute result = new RequestRoute();

    result.setOriginalRequestPath(request.getRequestPath());

    result.setResourceStoreRequest(request);

    String correctedPath =
        request.getRequestPath().startsWith(RepositoryItemUid.PATH_SEPARATOR)
            ? request.getRequestPath().substring(1, request.getRequestPath().length())
            : request.getRequestPath();

    String[] explodedPath = null;

    if (StringUtils.isEmpty(correctedPath)) {
      explodedPath = new String[0];
    } else {
      explodedPath = correctedPath.split(RepositoryItemUid.PATH_SEPARATOR);
    }

    Class<? extends Repository> kind = null;

    result.setRequestDepth(explodedPath.length);

    if (explodedPath.length >= 1) {
      // we have kind information ("repositories" vs "groups" etc)
      for (RepositoryTypeDescriptor rtd :
          repositoryTypeRegistry.getRegisteredRepositoryTypeDescriptors()) {
        if (rtd.getPrefix().equals(explodedPath[0])) {
          kind = rtd.getRole();

          break;
        }
      }

      if (kind == null) {
        // unknown explodedPath[0]
        throw new ItemNotFoundException(request);
      }

      result.setStrippedPrefix(ItemPathUtils.concatPaths(explodedPath[0]));
    }

    if (explodedPath.length >= 2) {
      // we have repoId information in path
      Repository repository = null;

      try {
        repository = getRepositoryForPathPrefixOrId(explodedPath[1], kind);
        // explodedPath[1] is not _always_ ID anymore! It is PathPrefix _or_ ID! NEXUS-1710
        // repository = repositoryRegistry.getRepositoryWithFacet( explodedPath[1], kind );

        if (!repository.isExposed()) {
          // this is not the main facet or the repo is not exposed
          throw new ItemNotFoundException(request);
        }
      } catch (NoSuchRepositoryException e) {
        // obviously, the repoId (explodedPath[1]) points to some nonexistent repoID
        throw new ItemNotFoundException(request, e);
      }

      result.setStrippedPrefix(ItemPathUtils.concatPaths(explodedPath[0], explodedPath[1]));

      result.setTargetedRepository(repository);

      String repoPath = "";

      for (int i = 2; i < explodedPath.length; i++) {
        repoPath = ItemPathUtils.concatPaths(repoPath, explodedPath[i]);
      }

      if (result.getOriginalRequestPath().endsWith(RepositoryItemUid.PATH_SEPARATOR)) {
        repoPath = repoPath + RepositoryItemUid.PATH_SEPARATOR;
      }

      result.setRepositoryPath(repoPath);
    }

    return result;
  }
  /** Converting App model to REST DTO. */
  public RepositoryBaseResource getRepositoryRestModel(Request request, Repository repository) {
    RepositoryResource resource = null;

    if (repository.getRepositoryKind().isFacetAvailable(ProxyRepository.class)) {
      resource = getRepositoryProxyRestModel(repository.adaptToFacet(ProxyRepository.class));
    } else if (repository.getRepositoryKind().isFacetAvailable(ShadowRepository.class)) {
      return getRepositoryShadowRestModel(request, repository.adaptToFacet(ShadowRepository.class));
    } else {
      resource = new RepositoryResource();
    }

    resource.setContentResourceURI(repositoryURLBuilder.getExposedRepositoryContentUrl(repository));

    resource.setProvider(NexusCompat.getRepositoryProviderHint(repository));

    resource.setProviderRole(NexusCompat.getRepositoryProviderRole(repository));

    resource.setFormat(repository.getRepositoryContentClass().getId());

    resource.setRepoType(getRestRepoType(repository));

    resource.setId(repository.getId());

    resource.setName(repository.getName());

    resource.setWritePolicy(repository.getWritePolicy().name());

    resource.setBrowseable(repository.isBrowseable());

    resource.setIndexable(repository.isSearchable());

    resource.setExposed(repository.isExposed());

    resource.setNotFoundCacheTTL(repository.getNotFoundCacheTimeToLive());

    // TODO: remove the default local storage, this is a work around for NEXUS-1994
    // the new 1.4 API doesn't store the default URL, well, it is part of the CRepo, but it is not
    // exposed.
    // so we can figure it out again, I think the default local Storage should be removed from the
    // REST message
    // which is part of the reason for not exposing it. The other part is it is not used anywhere
    // except to set
    // the localUrl if not already set.

    // apples to apples here, man i hate this section of code!!!!
    // always set to default (see AbstractRepositoryConfigurator)
    String defaultLocalStorageUrl =
        ((CRepositoryCoreConfiguration) repository.getCurrentCoreConfiguration())
            .getConfiguration(false)
            .defaultLocalStorageUrl;
    resource.setDefaultLocalStorageUrl(defaultLocalStorageUrl);

    // if not user set (but using default), this is null, otherwise it contains user-set value
    String overrideLocalStorageUrl =
        ((CRepositoryCoreConfiguration) repository.getCurrentCoreConfiguration())
            .getConfiguration(false)
            .getLocalStorage()
            .getUrl();
    if (StringUtils.isNotBlank(overrideLocalStorageUrl)) {
      resource.setOverrideLocalStorageUrl(overrideLocalStorageUrl);
    }

    if (repository.getRepositoryKind().isFacetAvailable(MavenRepository.class)) {
      resource.setRepoPolicy(
          repository.adaptToFacet(MavenRepository.class).getRepositoryPolicy().toString());

      if (repository.getRepositoryKind().isFacetAvailable(MavenProxyRepository.class)) {
        resource.setChecksumPolicy(
            repository.adaptToFacet(MavenProxyRepository.class).getChecksumPolicy().toString());

        resource.setDownloadRemoteIndexes(
            repository.adaptToFacet(MavenProxyRepository.class).isDownloadRemoteIndexes());
      }
    }
    // as this is a required field on ui, we need this to be set for non-maven type repos
    else {
      resource.setRepoPolicy(RepositoryPolicy.MIXED.name());
      resource.setChecksumPolicy(ChecksumPolicy.IGNORE.name());
      resource.setDownloadRemoteIndexes(false);
    }

    return resource;
  }