/**
   * Stuck here for now ... don't want to introduce dependency on ProfilesMatcher into
   * AnnotatedProperties ...
   */
  public static AnnotatedProperties applyProfiles(
      AnnotatedProperties properties, Set activeProfiles) {
    AnnotatedProperties applied = new AnnotatedProperties();

    for (Iterator i = properties.entrySet().iterator(); i.hasNext(); ) {
      Map.Entry entry = (Map.Entry) i.next();
      String key = (String) entry.getKey();
      String value = (String) entry.getValue();
      Annotations annotations = properties.getAnnotation(key);

      if (key.startsWith("[")) {
        int index = key.indexOf("]");

        if (index != -1) {
          Set profiles = new HashSet(Strings.commaSepList(key.substring(1, index)));
          ProfilesMatcher profilesMatcher = new ProfilesMatcher();

          if (profilesMatcher.matches(profiles, activeProfiles)) {
            applied.setProperty(key.substring(index + 1), value, annotations);
          }
        }
      } else {
        applied.setProperty(key, value, annotations);
      }
    }

    return applied;
  }
  private void resolveProperties(AnnotatedProperties properties, DependencySet dependencySet) {
    for (Iterator i = dependencySet.getSubsets().iterator(); i.hasNext(); ) {
      resolveProperties(properties, (DependencySet) i.next());
    }

    if (dependencySet.getProperties() != null) {
      properties.putAll(
          applyProfiles(dependencySet.getProperties(), project.getActiveProfiles().getElements()));
    }
  }
  private AnnotatedProperties expandPrefix(final String prefix, AnnotatedProperties properties) {
    return properties.replaceReferences(
        new PropertyProvider() {
          public String getProperty(String key) {
            int index = key.startsWith("[") ? (key.indexOf("]") + 1) : 0;
            String prefixMarker = "prefix.";

            if (key.indexOf(prefixMarker, index) != -1) {
              key =
                  (index == 0)
                      ? (prefix + "." + key.substring(prefixMarker.length()))
                      : (key.substring(0, index)
                          + prefix
                          + "."
                          + key.substring(index + prefixMarker.length()));
            }

            return key;
          }
        });
  }
  /**
   * Returns a set of properties for the project. The precedence is: quokka.properties
   * quokka.properties of inherited projects plugin.properties No expansion or ordering of
   * properties is done
   */
  public AnnotatedProperties getProperties() {
    AnnotatedProperties resolvedProperties = new AnnotatedProperties();

    // Add the global defaults
    resolvedProperties.put("quokka.project.targetDir", "${basedir}/target");
    resolvedProperties.put("quokka.project.sourceDir", "${basedir}/src");
    resolvedProperties.put("quokka.project.resourcesDir", "${basedir}/resources");

    // Add artifact related properties
    if (project.getArtifacts().size() > 0) {
      // Add properties common to all (group & version)
      RepoArtifactId artifactId =
          ((Artifact) getProject().getArtifacts().iterator().next()).getId();
      resolvedProperties.put("quokka.project.artifact.group", artifactId.getGroup());
      resolvedProperties.put("quokka.project.artifact.version", artifactId.getVersion().toString());

      // Build up a list of names by type
      Map namesByType = new HashMap();

      for (Iterator i = project.getArtifacts().iterator(); i.hasNext(); ) {
        Artifact artifact = (Artifact) i.next();
        artifactId = artifact.getId();

        List names = (List) namesByType.get(artifactId.getType());

        if (names == null) {
          names = new ArrayList();
          namesByType.put(artifactId.getType(), names);
        }

        names.add(artifactId.getName());
      }

      // Output the names
      for (Iterator i = namesByType.entrySet().iterator(); i.hasNext(); ) {
        Map.Entry entry = (Map.Entry) i.next();
        List names = (List) entry.getValue();
        resolvedProperties.put(
            "quokka.project.artifact.name[" + entry.getKey() + "]",
            Strings.join(names.iterator(), ","));
      }
    }

    // Put the plugin properties in first. Order is not important as plugin properties should be
    // unique to their plugin
    for (Iterator i = resolvedTargets.values().iterator(); i.hasNext(); ) {
      Target target = (Target) i.next();
      AnnotatedProperties targetProperties = target.getDefaultProperties();
      resolvedProperties.putAll(
          applyProfiles(targetProperties, project.getActiveProfiles().getElements()));
    }

    // Put in any properties defined in dependency sets (processed in reverse to ensure high levels
    // override low levels)
    resolveProperties(resolvedProperties, project.getDependencySet());

    resolvedProperties.putAll(
        applyProfiles(project.getProperties(), project.getActiveProfiles().getElements()));

    // Put the project paths as properties
    for (Iterator i = resolvedPaths.entrySet().iterator(); i.hasNext(); ) {
      Map.Entry entry = (Map.Entry) i.next();
      resolvedProperties.put(
          "quokka.project.path." + entry.getKey(),
          toAntPath(getProjectPath((String) entry.getKey(), false, true)).toString());
    }

    return resolvedProperties;
  }