/**
  * @param patternMatcher matches a set of elements
  * @param extension the extension to match
  * @return true if one of the element is matched
  */
 public static boolean matches(Pattern patternMatcher, Extension extension) {
   return matches(
       patternMatcher,
       extension.getId().getId(),
       extension.getDescription(),
       extension.getSummary(),
       extension.getName(),
       extension.getFeatures());
 }
  /**
   * Matches an extension in a case insensitive way.
   *
   * @param patternMatcher the pattern to match
   * @param filters the filters
   * @param extension the extension to match
   * @return true if one of the element is matched
   * @since 7.0M2
   */
  public static boolean matches(
      Pattern patternMatcher, Collection<Filter> filters, Extension extension) {
    if (matches(
        patternMatcher,
        extension.getId().getId(),
        extension.getDescription(),
        extension.getSummary(),
        extension.getName(),
        extension.getFeatures())) {
      for (Filter filter : filters) {
        if (!matches(filter, extension)) {
          return false;
        }
      }

      return true;
    }

    return false;
  }
  /**
   * @param previousExtension the previous installed version of the extension to install
   * @param extension the new extension to install
   * @param dependency indicate if the extension is installed as a dependency
   * @param namespace the namespace where to install the extension
   * @return the install plan node for the provided extension
   * @param initialDependency the initial dependency used to resolve the extension
   * @throws InstallException error when trying to install provided extension
   */
  private ModifableExtensionPlanNode installExtension(
      InstalledExtension previousExtension,
      Extension extension,
      boolean dependency,
      String namespace,
      ExtensionDependency initialDependency)
      throws InstallException, ResolveException {
    // Is feature core extension
    for (String feature : extension.getFeatures()) {
      if (this.coreExtensionRepository.exists(feature)) {
        throw new InstallException(
            String.format("There is already a core extension with the id [%s]", feature));
      }
    }

    // Find all previous version of the extension
    Set<InstalledExtension> previousExtensions = new LinkedHashSet<InstalledExtension>();
    if (previousExtension != null) {
      previousExtensions.add(previousExtension);
    }
    if (!extension.getFeatures().isEmpty()) {
      for (String feature : extension.getFeatures()) {
        InstalledExtension installedExtension =
            checkAlreadyInstalledExtension(feature, extension.getId().getVersion(), namespace);
        if (installedExtension != null) {
          previousExtensions.add(installedExtension);
        }
      }
    }

    ExtensionHandler extensionHandler;

    // Is type supported ?
    try {
      extensionHandler =
          this.componentManager.getInstance(ExtensionHandler.class, extension.getType());
    } catch (ComponentLookupException e) {
      throw new InstallException(String.format("Unsupported type [%s]", extension.getType()), e);
    }

    // Is installing the extension allowed ?
    extensionHandler.checkInstall(extension, namespace, getRequest());

    // Check dependencies
    Collection<? extends ExtensionDependency> dependencies = extension.getDependencies();

    notifyPushLevelProgress(dependencies.size() + 1);

    try {
      List<ModifableExtensionPlanNode> children = null;
      if (!dependencies.isEmpty()) {
        children = new ArrayList<ModifableExtensionPlanNode>();
        for (ExtensionDependency dependencyDependency : extension.getDependencies()) {
          installExtensionDependency(dependencyDependency, namespace, children);

          notifyStepPropress();
        }
      }

      ModifableExtensionPlanNode node =
          initialDependency != null
              ? new ModifableExtensionPlanNode(
                  initialDependency, initialDependency.getVersionConstraint())
              : new ModifableExtensionPlanNode();

      node.setChildren(children);

      Action action;
      if (!previousExtensions.isEmpty()) {
        if (previousExtensions
                .iterator()
                .next()
                .getId()
                .getVersion()
                .compareTo(extension.getId().getVersion())
            > 0) {
          action = Action.DOWNGRADE;
        } else {
          action = Action.UPGRADE;
        }
      } else {
        action = Action.INSTALL;
      }

      node.setAction(
          new DefaultExtensionPlanAction(
              extension, previousExtensions, action, namespace, dependency));

      return node;
    } finally {
      notifyPopLevelProgress();
    }
  }