[MCHANGELOG-134] ChangeLog: added include/exclude support to filter uninteresting files
Submitted by Johannes Utzig

git-svn-id: https://svn.apache.org/repos/asf/maven/plugins/trunk@1467631 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/maven/plugin/changelog/ChangeLogReport.java b/src/main/java/org/apache/maven/plugin/changelog/ChangeLogReport.java
index cb27756..352c6b2 100644
--- a/src/main/java/org/apache/maven/plugin/changelog/ChangeLogReport.java
+++ b/src/main/java/org/apache/maven/plugin/changelog/ChangeLogReport.java
@@ -239,6 +239,21 @@
     protected boolean encodeFileUri;
 
     /**
+     * List of files to include. Specified as fileset patterns of files to include in the report
+     * @since 2.3
+     */
+    @Parameter
+    private String[] includes;
+
+    /**
+     *  List of files to include. Specified as fileset patterns of files to omit in the report
+     *  @since 2.3
+     */
+    @Parameter
+    private String[] excludes;
+
+
+    /**
      * The Maven Project Object
      */
     @Component
@@ -700,8 +715,9 @@
             {
                 throw new MavenReportException( "The type '" + type + "' isn't supported." );
             }
-
+            filter(changeSets);
             return changeSets;
+
         }
         catch ( ScmException e )
         {
@@ -714,6 +730,89 @@
     }
 
     /**
+     * filters out unwanted files from the changesets
+     */
+    private void filter(List<ChangeLogSet> changeSets)
+    {
+        List<Pattern> include = compilePatterns(includes);
+        List<Pattern> exclude = compilePatterns(excludes);
+        if(includes==null && excludes==null)
+            return;
+        for (ChangeLogSet changeLogSet : changeSets)
+        {
+            List<ChangeSet> set = changeLogSet.getChangeSets();
+            filter(set, include, exclude);
+        }
+
+    }
+
+    private List<Pattern> compilePatterns(String[] patternArray)
+    {
+        if(patternArray==null)
+            return new ArrayList<Pattern>();
+        List<Pattern> patterns = new ArrayList<Pattern>(patternArray.length);
+        for (String string : patternArray)
+        {
+            //replaces * with [/\]* (everything but file seperators)
+            //replaces ** with .*
+            //quotes the rest of the string
+            string = "\\Q" + string + "\\E";
+            string = string.replace("**", "\\E.?REPLACEMENT?\\Q");
+            string = string.replace("*", "\\E[^/\\\\]?REPLACEMENT?\\Q");
+            string = string.replace("?REPLACEMENT?", "*");
+            string = string.replace("\\Q\\E", "");
+            patterns.add(Pattern.compile(string));
+        }
+        return patterns;
+    }
+
+    private void filter(List<ChangeSet> sets, List<Pattern> includes, List<Pattern> excludes)
+    {
+        Iterator<ChangeSet> it = sets.iterator();
+        while (it.hasNext())
+        {
+            ChangeSet changeSet = it.next();
+            List<ChangeFile> files = changeSet.getFiles();
+            Iterator<ChangeFile> iterator = files.iterator();
+            while (iterator.hasNext())
+            {
+                ChangeFile changeFile = (ChangeFile)iterator.next();
+                String name = changeFile.getName();
+                if(!isIncluded(includes,name) || isExcluded(excludes, name))
+                {
+                    iterator.remove();
+                }
+            }
+            if(files.isEmpty())
+                it.remove();
+        }
+    }
+
+    private boolean isExcluded(List<Pattern> excludes, String name)
+    {
+        if(excludes==null || excludes.isEmpty())
+            return false;
+        for (Pattern pattern : excludes)
+        {
+            if(pattern.matcher(name).matches())
+                return true;
+        }
+        return false;
+    }
+
+    private boolean isIncluded(List<Pattern> includes, String name)
+    {
+        if(includes==null || includes.isEmpty())
+            return true;
+        for (Pattern pattern : includes)
+        {
+            if(pattern.matcher(name).matches())
+                return true;
+        }
+        return false;
+    }
+
+    /**
      * Converts the localized date string pattern to date object.
      *
      * @return A date