You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sl...@apache.org on 2021/01/23 00:47:17 UTC

[maven-common-artifact-filters] branch speed created (now c042ee5)

This is an automated email from the ASF dual-hosted git repository.

slachiewicz pushed a change to branch speed
in repository https://gitbox.apache.org/repos/asf/maven-common-artifact-filters.git.


      at c042ee5  Add some comments and rename

This branch includes the following new commits:

     new 0776e38  Big speed improvements for patterns that do not contain any wildcard
     new c55e2ca  Add missed patterns report for simple patterns
     new 830b27b  Broaden the scope of the optimizations
     new c042ee5  Add some comments and rename

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[maven-common-artifact-filters] 04/04: Add some comments and rename

Posted by sl...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

slachiewicz pushed a commit to branch speed
in repository https://gitbox.apache.org/repos/asf/maven-common-artifact-filters.git

commit c042ee5c67a273cc5cb71c8a5281a5624d6b259c
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Fri Nov 20 18:35:45 2020 +0100

    Add some comments and rename
---
 .../filter/PatternIncludesArtifactFilter.java      | 74 ++++++++++++++++++----
 1 file changed, 60 insertions(+), 14 deletions(-)

diff --git a/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java b/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
index bf5138a..97db048 100644
--- a/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
+++ b/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
@@ -148,13 +148,13 @@ public class PatternIncludesArtifactFilter
     protected boolean patternMatches( final Artifact artifact )
     {
         // Check if the main artifact matches
-        char[][] tokens = new char[][] {
+        char[][] artifactGatvCharArray = new char[][] {
                             emptyOrChars( artifact.getGroupId() ),
                             emptyOrChars( artifact.getArtifactId() ),
                             emptyOrChars( artifact.getType() ),
                             emptyOrChars( artifact.getBaseVersion() )
                     };
-        Boolean match = match( tokens );
+        Boolean match = match( artifactGatvCharArray );
         if ( match != null )
         {
             return match;
@@ -168,8 +168,8 @@ public class PatternIncludesArtifactFilter
             {
                 for ( String trailItem : depTrail )
                 {
-                    char[][] depTokens = tokenizeAndSplit( trailItem );
-                    match = match( depTokens );
+                    char[][] depGatvCharArray = tokenizeAndSplit( trailItem );
+                    match = match( depGatvCharArray );
                     if ( match != null)
                     {
                         return match;
@@ -181,7 +181,7 @@ public class PatternIncludesArtifactFilter
         return false;
     }
 
-    private Boolean match( char[][] tokens )
+    private Boolean match( char[][] gatvCharArray )
     {
         if ( simplePatterns != null && simplePatterns.size() > 0 )
         {
@@ -193,7 +193,7 @@ public class PatternIncludesArtifactFilter
                 {
                     sb.append( ":" );
                 }
-                sb.append( tokens[i] );
+                sb.append( gatvCharArray[i] );
                 Map<String, Pattern> map = simplePatterns.get( i );
                 if ( map != null )
                 {
@@ -210,7 +210,7 @@ public class PatternIncludesArtifactFilter
         // Check all other patterns
         for ( Pattern pattern : patterns )
         {
-            if ( pattern.matches( tokens ) )
+            if ( pattern.matches( gatvCharArray ) )
             {
                 patternsTriggered.add( pattern );
                 return !(pattern instanceof NegativePattern);
@@ -671,16 +671,19 @@ public class PatternIncludesArtifactFilter
         }
     }
 
+    /** Creates a positional matching pattern */
     private static Pattern match( String pattern, char[] token, int posVal )
     {
         return match( pattern, token, posVal, posVal );
     }
 
+    /** Creates a positional matching pattern */
     private static Pattern match( char[] token, int posVal )
     {
         return match( "", token, posVal, posVal );
     }
 
+    /** Creates a positional matching pattern */
     private static Pattern match( String pattern, char[] token, int posMin, int posMax )
     {
         boolean hasWildcard = false;
@@ -702,36 +705,45 @@ public class PatternIncludesArtifactFilter
         }
     }
 
+    /** Creates a positional matching pattern */
     private static Pattern match( char[] token, int posMin, int posMax )
     {
         return new PosPattern( "", token, posMin, posMax );
     }
 
+    /** Creates an AND pattern */
     private static Pattern and( String pattern, Pattern... patterns )
     {
         return new AndPattern( pattern, patterns );
     }
 
+    /** Creates an AND pattern */
     private static Pattern and( Pattern... patterns )
     {
         return and( "", patterns );
     }
 
+    /** Creates an OR pattern */
     private static Pattern or( String pattern, Pattern... patterns )
     {
         return new OrPattern( pattern, patterns );
     }
 
+    /** Creates an OR pattern */
     private static Pattern or( Pattern... patterns )
     {
         return or( "", patterns );
     }
 
+    /** Creates a match-all pattern */
     private static Pattern all( String pattern )
     {
         return new MatchAllPattern( pattern );
     }
 
+    /**
+     * Abstract class for patterns
+     */
     static abstract class Pattern
     {
         private final String pattern;
@@ -743,12 +755,19 @@ public class PatternIncludesArtifactFilter
 
         public abstract boolean matches( char[][] parts );
 
+        /**
+         * Returns a string containing a fixed artifact gatv coordinates
+         * or null if the pattern can not be translated.
+         */
         public String translateEquals()
         {
             return null;
         }
 
-        public String translateEquals( int pos )
+        /**
+         * Check if the this pattern is a fixed pattern on the specified pos.
+         */
+        protected String translateEquals( int pos )
         {
             return null;
         }
@@ -759,6 +778,9 @@ public class PatternIncludesArtifactFilter
         }
     }
 
+    /**
+     * Simple pattern which performs a logical AND between one or more patterns.
+     */
     static class AndPattern extends Pattern
     {
         private final Pattern[] patterns;
@@ -807,6 +829,9 @@ public class PatternIncludesArtifactFilter
         }
     }
 
+    /**
+     * Simple pattern which performs a logical OR between one or more patterns.
+     */
     static class OrPattern extends Pattern
     {
         private final Pattern[] patterns;
@@ -831,16 +856,21 @@ public class PatternIncludesArtifactFilter
         }
     }
 
+    /**
+     * A positional matching pattern, to check if a token in the gatv coordinates
+     * having a position between posMin and posMax (both inclusives) can match
+     * the pattern.
+     */
     static class PosPattern extends Pattern
     {
-        private final char[] token;
+        private final char[] patternCharArray;
         private final int posMin;
         private final int posMax;
 
-        public PosPattern( String pattern, char[] token, int posMin, int posMax )
+        public PosPattern( String pattern, char[] patternCharArray, int posMin, int posMax )
         {
             super( pattern );
-            this.token = token;
+            this.patternCharArray = patternCharArray;
             this.posMin = posMin;
             this.posMax = posMax;
         }
@@ -850,7 +880,7 @@ public class PatternIncludesArtifactFilter
         {
             for ( int i = posMin; i <= posMax; i++ )
             {
-                if ( match( token, parts[i], i == 3 ) )
+                if ( match( patternCharArray, parts[i], i == 3 ) )
                 {
                     return true;
                 }
@@ -859,16 +889,20 @@ public class PatternIncludesArtifactFilter
         }
     }
 
+    /**
+     * Looks for an exact match in the gatv coordinates between
+     * posMin and posMax (both inclusives)
+     */
     static class EqPattern extends Pattern
     {
         private final char[] token;
         private final int posMin;
         private final int posMax;
 
-        public EqPattern( String pattern, char[] token, int posMin, int posMax )
+        public EqPattern( String pattern, char[] patternCharArray, int posMin, int posMax )
         {
             super( pattern );
-            this.token = token;
+            this.token = patternCharArray;
             this.posMin = posMin;
             this.posMax = posMax;
         }
@@ -886,6 +920,12 @@ public class PatternIncludesArtifactFilter
             return false;
         }
 
+        @Override
+        public String translateEquals()
+        {
+            return translateEquals( 0 );
+        }
+
         public String translateEquals( int pos )
         {
             return posMin == pos && posMax == pos
@@ -895,6 +935,9 @@ public class PatternIncludesArtifactFilter
 
     }
 
+    /**
+     * Matches all input
+     */
     static class MatchAllPattern extends Pattern
     {
         public MatchAllPattern( String pattern )
@@ -909,6 +952,9 @@ public class PatternIncludesArtifactFilter
         }
     }
 
+    /**
+     * Negative pattern
+     */
     static class NegativePattern extends Pattern
     {
         private final Pattern inner;


[maven-common-artifact-filters] 01/04: Big speed improvements for patterns that do not contain any wildcard

Posted by sl...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

slachiewicz pushed a commit to branch speed
in repository https://gitbox.apache.org/repos/asf/maven-common-artifact-filters.git

commit 0776e38f9b1ba30ffcfef9ff5d7d799ee8ff9c00
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Wed Nov 18 20:52:42 2020 +0100

    Big speed improvements for patterns that do not contain any wildcard
    
    This can be a huge boost for dependency sets that contains lots of artifact ids such as https://github.com/apache/camel/blob/2870bb9e619b4e18bfe8de11b449be9cd67d1f3c/apache-camel/src/main/descriptors/common-bin.xml
---
 .../filter/PatternIncludesArtifactFilter.java      | 79 +++++++++++++++++++---
 1 file changed, 71 insertions(+), 8 deletions(-)

diff --git a/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java b/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
index c9aad45..d221eff 100644
--- a/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
+++ b/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
@@ -22,6 +22,7 @@ package org.apache.maven.shared.artifact.filter;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -42,9 +43,13 @@ import org.codehaus.plexus.logging.Logger;
 public class PatternIncludesArtifactFilter
     implements ArtifactFilter, StatisticsReportingArtifactFilter
 {
-    private final List<String> positivePatterns;
+    private final Set<String> simplePositivePatterns;
 
-    private final List<String> negativePatterns;
+    private final Set<String> positivePatterns;
+
+    private final Set<String> simpleNegativePatterns;
+
+    private final Set<String> negativePatterns;
 
     private final boolean actTransitively;
 
@@ -67,25 +72,43 @@ public class PatternIncludesArtifactFilter
     public PatternIncludesArtifactFilter( final Collection<String> patterns, final boolean actTransitively )
     {
         this.actTransitively = actTransitively;
-        final List<String> pos = new ArrayList<>();
-        final List<String> neg = new ArrayList<>();
+        final Set<String> pos = new LinkedHashSet<>();
+        final Set<String> spos = new LinkedHashSet<>();
+        final Set<String> neg = new LinkedHashSet<>();
+        final Set<String> sneg = new LinkedHashSet<>();
         if ( patterns != null && !patterns.isEmpty() )
         {
             for ( String pattern : patterns )
             {
                 if ( pattern.startsWith( "!" ) )
                 {
-                    neg.add( pattern.substring( 1 ) );
+                    if ( pattern.contains( "*" ) )
+                    {
+                        neg.add( pattern.substring( 1 ) );
+                    }
+                    else
+                    {
+                        sneg.add( pattern.substring( 1 ) );
+                    }
                 }
                 else
                 {
-                    pos.add( pattern );
+                    if ( pattern.contains( "*" ) )
+                    {
+                        pos.add( pattern );
+                    }
+                    else
+                    {
+                        spos.add( pattern );
+                    }
                 }
             }
         }
 
         positivePatterns = pos;
+        simplePositivePatterns = spos;
         negativePatterns = neg;
+        simpleNegativePatterns = sneg;
     }
 
     /** {@inheritDoc} */
@@ -120,6 +143,13 @@ public class PatternIncludesArtifactFilter
 
     private Boolean negativeMatch( final Artifact artifact )
     {
+        if ( simpleNegativePatterns != null && !simpleNegativePatterns.isEmpty() )
+        {
+            if ( simpleMatch( artifact, simpleNegativePatterns ) )
+            {
+                return true;
+            }
+        }
         if ( negativePatterns == null || negativePatterns.isEmpty() )
         {
             return null;
@@ -136,6 +166,13 @@ public class PatternIncludesArtifactFilter
      */
     protected Boolean positiveMatch( final Artifact artifact )
     {
+        if ( simplePositivePatterns != null && !simplePositivePatterns.isEmpty() )
+        {
+            if ( simpleMatch( artifact, simplePositivePatterns ) )
+            {
+                return true;
+            }
+        }
         if ( positivePatterns == null || positivePatterns.isEmpty() )
         {
             return null;
@@ -146,7 +183,33 @@ public class PatternIncludesArtifactFilter
         }
     }
 
-    private boolean match( final Artifact artifact, final List<String> patterns )
+    private boolean simpleMatch( final Artifact artifact, final Set<String> patterns )
+    {
+        final String shortId = ArtifactUtils.versionlessKey( artifact );
+        if ( patterns.contains( shortId ) )
+        {
+            patternsTriggered.add( shortId );
+            return true;
+        }
+
+        final String id = artifact.getDependencyConflictId();
+        if ( patterns.contains( id ) )
+        {
+            patternsTriggered.add( id );
+            return true;
+        }
+
+        final String wholeId = artifact.getId();
+        if ( patterns.contains( wholeId ) )
+        {
+            patternsTriggered.add( wholeId );
+            return true;
+        }
+
+        return false;
+    }
+
+    private boolean match( final Artifact artifact, final Iterable<String> patterns )
     {
         final String shortId = ArtifactUtils.versionlessKey( artifact );
         final String id = artifact.getDependencyConflictId();
@@ -186,7 +249,7 @@ public class PatternIncludesArtifactFilter
         return false;
     }
 
-    private boolean matchAgainst( final String value, final List<String> patterns, final boolean regionMatch )
+    private boolean matchAgainst( final String value, final Iterable<String> patterns, final boolean regionMatch )
     {
         final String[] tokens = value.split( ":" );
         for ( String pattern : patterns )


[maven-common-artifact-filters] 02/04: Add missed patterns report for simple patterns

Posted by sl...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

slachiewicz pushed a commit to branch speed
in repository https://gitbox.apache.org/repos/asf/maven-common-artifact-filters.git

commit c55e2ca67f118f6ad10fab8d5380431dadc95c19
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Wed Nov 18 21:21:56 2020 +0100

    Add missed patterns report for simple patterns
---
 .../shared/artifact/filter/PatternIncludesArtifactFilter.java    | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java b/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
index d221eff..8d01c71 100644
--- a/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
+++ b/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
@@ -397,11 +397,14 @@ public class PatternIncludesArtifactFilter
     public void reportMissedCriteria( final Logger logger )
     {
         // if there are no patterns, there is nothing to report.
-        if ( !positivePatterns.isEmpty() || !negativePatterns.isEmpty() )
+        if ( !positivePatterns.isEmpty() || !negativePatterns.isEmpty()
+                || !simplePositivePatterns.isEmpty() || !simpleNegativePatterns.isEmpty() )
         {
             final List<String> missed = new ArrayList<>();
             missed.addAll( positivePatterns );
+            missed.addAll( simplePositivePatterns );
             missed.addAll( negativePatterns );
+            missed.addAll( simpleNegativePatterns );
 
             missed.removeAll( patternsTriggered );
 
@@ -437,6 +440,10 @@ public class PatternIncludesArtifactFilter
     protected String getPatternsAsString()
     {
         final StringBuilder buffer = new StringBuilder();
+        for ( String pattern : simplePositivePatterns )
+        {
+            buffer.append( "\no '" ).append( pattern ).append( "'" );
+        }
         for ( String pattern : positivePatterns )
         {
             buffer.append( "\no '" ).append( pattern ).append( "'" );


[maven-common-artifact-filters] 03/04: Broaden the scope of the optimizations

Posted by sl...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

slachiewicz pushed a commit to branch speed
in repository https://gitbox.apache.org/repos/asf/maven-common-artifact-filters.git

commit 830b27b5a5aca5f8506b653dc987d893390321cf
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Fri Nov 20 00:08:33 2020 +0100

    Broaden the scope of the optimizations
---
 pom.xml                                            |  12 +
 .../filter/PatternExcludesArtifactFilter.java      |   2 +-
 .../filter/PatternIncludesArtifactFilter.java      | 937 +++++++++++++++------
 .../filter/AbstractPatternArtifactFilterTest.java  | 105 ++-
 .../filter/OldPatternIncludesArtifactFilter.java}  | 106 +--
 .../artifact/filter/PatternFilterPerfTest.java     | 122 +++
 6 files changed, 903 insertions(+), 381 deletions(-)

diff --git a/pom.xml b/pom.xml
index b39ffd3..28c3e23 100644
--- a/pom.xml
+++ b/pom.xml
@@ -160,5 +160,17 @@
       </exclusions>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.openjdk.jmh</groupId>
+      <artifactId>jmh-core</artifactId>
+      <version>1.26</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.openjdk.jmh</groupId>
+      <artifactId>jmh-generator-annprocess</artifactId>
+      <version>1.26</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
diff --git a/src/main/java/org/apache/maven/shared/artifact/filter/PatternExcludesArtifactFilter.java b/src/main/java/org/apache/maven/shared/artifact/filter/PatternExcludesArtifactFilter.java
index b0d7a1e..7b7b267 100644
--- a/src/main/java/org/apache/maven/shared/artifact/filter/PatternExcludesArtifactFilter.java
+++ b/src/main/java/org/apache/maven/shared/artifact/filter/PatternExcludesArtifactFilter.java
@@ -56,7 +56,7 @@ public class PatternExcludesArtifactFilter
 
         if ( !shouldInclude )
         {
-            addFilteredArtifactId( artifact.getId() );
+            addFilteredArtifactId( artifact );
         }
 
         return shouldInclude;
diff --git a/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java b/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
index 8d01c71..bf5138a 100644
--- a/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
+++ b/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
@@ -20,14 +20,18 @@ package org.apache.maven.shared.artifact.filter;
  */
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 
 import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.ArtifactUtils;
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
@@ -43,19 +47,20 @@ import org.codehaus.plexus.logging.Logger;
 public class PatternIncludesArtifactFilter
     implements ArtifactFilter, StatisticsReportingArtifactFilter
 {
-    private final Set<String> simplePositivePatterns;
+    /** Holds the set of compiled patterns */
+    private final Set<Pattern> patterns;
 
-    private final Set<String> positivePatterns;
-
-    private final Set<String> simpleNegativePatterns;
-
-    private final Set<String> negativePatterns;
+    /** Holds simple patterns: those that can use direct matching */
+    private final Map<Integer, Map<String, Pattern>> simplePatterns;
 
+    /** Wether the dependency trail should be checked */
     private final boolean actTransitively;
 
-    private final Set<String> patternsTriggered = new HashSet<>();
+    /** Set of patterns that have been triggered */
+    private final Set<Pattern> patternsTriggered = new HashSet<>();
 
-    private final List<String> filteredArtifactIds = new ArrayList<>();
+    /** Set of artifacts that have been filtered out */
+    private final List<Artifact> filteredArtifact = new ArrayList<>();
 
     /**
      * @param patterns The pattern to be used.
@@ -72,43 +77,55 @@ public class PatternIncludesArtifactFilter
     public PatternIncludesArtifactFilter( final Collection<String> patterns, final boolean actTransitively )
     {
         this.actTransitively = actTransitively;
-        final Set<String> pos = new LinkedHashSet<>();
-        final Set<String> spos = new LinkedHashSet<>();
-        final Set<String> neg = new LinkedHashSet<>();
-        final Set<String> sneg = new LinkedHashSet<>();
+        final Set<Pattern> pat = new LinkedHashSet<>();
+        Map<Integer, Map<String, Pattern>> simplePat = null;
+        boolean allPos = true;
         if ( patterns != null && !patterns.isEmpty() )
         {
             for ( String pattern : patterns )
             {
-                if ( pattern.startsWith( "!" ) )
+
+                Pattern p = compile( pattern );
+                allPos &= !( p instanceof NegativePattern );
+                pat.add( p );
+            }
+        }
+        // If all patterns are positive, we can check for simple patterns
+        // Simple patterns will match the first tokens and contain no wildcards,
+        // so we can put them in a map and check them using a simple map lookup.
+        if ( allPos )
+        {
+            for ( Iterator<Pattern> it = pat.iterator(); it.hasNext(); )
+            {
+                Pattern p = it.next();
+                String peq = p.translateEquals();
+                if ( peq != null )
                 {
-                    if ( pattern.contains( "*" ) )
+                    int nb = 0;
+                    for ( char ch : peq.toCharArray() )
                     {
-                        neg.add( pattern.substring( 1 ) );
+                        if ( ch == ':' )
+                        {
+                            nb++;
+                        }
                     }
-                    else
+                    if ( simplePat == null )
                     {
-                        sneg.add( pattern.substring( 1 ) );
+                        simplePat = new HashMap<>();
                     }
-                }
-                else
-                {
-                    if ( pattern.contains( "*" ) )
+                    Map<String, Pattern> peqm = simplePat.get( nb );
+                    if ( peqm == null )
                     {
-                        pos.add( pattern );
-                    }
-                    else
-                    {
-                        spos.add( pattern );
+                        peqm = new HashMap<>();
+                        simplePat.put( nb, peqm );
                     }
+                    peqm.put( peq, p );
+                    it.remove();
                 }
             }
         }
-
-        positivePatterns = pos;
-        simplePositivePatterns = spos;
-        negativePatterns = neg;
-        simpleNegativePatterns = sneg;
+        this.simplePatterns = simplePat;
+        this.patterns = pat;
     }
 
     /** {@inheritDoc} */
@@ -118,7 +135,7 @@ public class PatternIncludesArtifactFilter
 
         if ( !shouldInclude )
         {
-            addFilteredArtifactId( artifact.getId() );
+            addFilteredArtifactId( artifact );
         }
 
         return shouldInclude;
@@ -130,369 +147,783 @@ public class PatternIncludesArtifactFilter
      */
     protected boolean patternMatches( final Artifact artifact )
     {
-        return positiveMatch( artifact ) == Boolean.TRUE || negativeMatch( artifact ) == Boolean.FALSE;
+        // Check if the main artifact matches
+        char[][] tokens = new char[][] {
+                            emptyOrChars( artifact.getGroupId() ),
+                            emptyOrChars( artifact.getArtifactId() ),
+                            emptyOrChars( artifact.getType() ),
+                            emptyOrChars( artifact.getBaseVersion() )
+                    };
+        Boolean match = match( tokens );
+        if ( match != null )
+        {
+            return match;
+        }
+
+        if ( actTransitively )
+        {
+            final List<String> depTrail = artifact.getDependencyTrail();
+
+            if ( depTrail != null && depTrail.size() > 1 )
+            {
+                for ( String trailItem : depTrail )
+                {
+                    char[][] depTokens = tokenizeAndSplit( trailItem );
+                    match = match( depTokens );
+                    if ( match != null)
+                    {
+                        return match;
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
+    private Boolean match( char[][] tokens )
+    {
+        if ( simplePatterns != null && simplePatterns.size() > 0 )
+        {
+            // We add the parts one by one to the builder
+            StringBuilder sb = new StringBuilder();
+            for ( int i = 0; i < 4; i++ )
+            {
+                if ( i > 0 )
+                {
+                    sb.append( ":" );
+                }
+                sb.append( tokens[i] );
+                Map<String, Pattern> map = simplePatterns.get( i );
+                if ( map != null )
+                {
+                    // Check if one of the pattern matches
+                    Pattern p = map.get( sb.toString() );
+                    if ( p != null )
+                    {
+                        patternsTriggered.add( p );
+                        return true;
+                    }
+                }
+            }
+        }
+        // Check all other patterns
+        for ( Pattern pattern : patterns )
+        {
+            if ( pattern.matches( tokens ) )
+            {
+                patternsTriggered.add( pattern );
+                return !(pattern instanceof NegativePattern);
+            }
+        }
+
+        return null;
     }
 
     /**
-     * @param artifactId add artifact to the filtered artifacts list.
+     * @param artifact add artifact to the filtered artifacts list.
      */
-    protected void addFilteredArtifactId( final String artifactId )
+    protected void addFilteredArtifactId( final Artifact artifact )
     {
-        filteredArtifactIds.add( artifactId );
+        filteredArtifact.add( artifact );
     }
 
-    private Boolean negativeMatch( final Artifact artifact )
+    /** {@inheritDoc} */
+    public void reportMissedCriteria( final Logger logger )
     {
-        if ( simpleNegativePatterns != null && !simpleNegativePatterns.isEmpty() )
+        // if there are no patterns, there is nothing to report.
+        if ( !patterns.isEmpty() )
         {
-            if ( simpleMatch( artifact, simpleNegativePatterns ) )
+            final List<Pattern> missed = new ArrayList<>( patterns );
+            missed.removeAll( patternsTriggered );
+
+            if ( !missed.isEmpty() && logger.isWarnEnabled() )
             {
-                return true;
+                final StringBuilder buffer = new StringBuilder();
+
+                buffer.append( "The following patterns were never triggered in this " );
+                buffer.append( getFilterDescription() );
+                buffer.append( ':' );
+
+                for ( Pattern pattern : missed )
+                {
+                    buffer.append( "\no  '" ).append( pattern ).append( "'" );
+                }
+
+                buffer.append( "\n" );
+
+                logger.warn( buffer.toString() );
             }
         }
-        if ( negativePatterns == null || negativePatterns.isEmpty() )
-        {
-            return null;
-        }
-        else
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Includes filter:" + getPatternsAsString();
+    }
+
+    /**
+     * @return pattern as a string.
+     */
+    protected String getPatternsAsString()
+    {
+        final StringBuilder buffer = new StringBuilder();
+        for ( Pattern pattern : patterns )
         {
-            return match( artifact, negativePatterns );
+            buffer.append( "\no '" ).append( pattern ).append( "'" );
         }
+
+        return buffer.toString();
     }
 
     /**
-     * @param artifact check for positive match.
-     * @return true/false.
+     * @return description.
      */
-    protected Boolean positiveMatch( final Artifact artifact )
+    protected String getFilterDescription()
     {
-        if ( simplePositivePatterns != null && !simplePositivePatterns.isEmpty() )
+        return "artifact inclusion filter";
+    }
+
+    /** {@inheritDoc} */
+    public void reportFilteredArtifacts( final Logger logger )
+    {
+        if ( !filteredArtifact.isEmpty() && logger.isDebugEnabled() )
         {
-            if ( simpleMatch( artifact, simplePositivePatterns ) )
+            final StringBuilder buffer =
+                new StringBuilder( "The following artifacts were removed by this " + getFilterDescription() + ": " );
+
+            for ( Artifact artifactId : filteredArtifact )
             {
-                return true;
+                buffer.append( '\n' ).append( artifactId.getId() );
             }
+
+            logger.debug( buffer.toString() );
         }
-        if ( positivePatterns == null || positivePatterns.isEmpty() )
+    }
+
+    /** {@inheritDoc} */
+    public boolean hasMissedCriteria()
+    {
+        // if there are no patterns, there is nothing to report.
+        if ( !patterns.isEmpty() )
         {
-            return null;
+            final List<Pattern> missed = new ArrayList<>( patterns );
+            missed.removeAll( patternsTriggered );
+
+            return !missed.isEmpty();
         }
-        else
+
+        return false;
+    }
+
+    private static final char[] EMPTY = new char[0];
+
+    private static final char[] ANY = new char[] { '*' };
+
+    static char[] emptyOrChars( String str )
+    {
+        return str != null && str.length() > 0 ? str.toCharArray() : EMPTY;
+    }
+
+    static char[] anyOrChars( char[] str )
+    {
+        return str.length > 1 || ( str.length == 1 && str[0] != '*' ) ? str : ANY;
+    }
+
+    static char[][] tokenizeAndSplit( String pattern )
+    {
+        String[] stokens = pattern.split( ":" );
+        char[][] tokens = new char[ stokens.length ][];
+        for ( int i = 0; i < stokens.length; i++ )
         {
-            return match( artifact, positivePatterns );
+            tokens[i] = emptyOrChars( stokens[i] );
         }
+        return tokens;
     }
 
-    private boolean simpleMatch( final Artifact artifact, final Set<String> patterns )
+    static boolean match( char[] patArr, char[] strArr, boolean isVersion )
     {
-        final String shortId = ArtifactUtils.versionlessKey( artifact );
-        if ( patterns.contains( shortId ) )
+        int patIdxStart = 0;
+        int patIdxEnd = patArr.length - 1;
+        int strIdxStart = 0;
+        int strIdxEnd = strArr.length - 1;
+        char ch;
+
+        boolean containsStar = false;
+        for ( char aPatArr : patArr )
         {
-            patternsTriggered.add( shortId );
-            return true;
+            if ( aPatArr == '*' )
+            {
+                containsStar = true;
+                break;
+            }
         }
 
-        final String id = artifact.getDependencyConflictId();
-        if ( patterns.contains( id ) )
+        if ( !containsStar )
         {
-            patternsTriggered.add( id );
-            return true;
+            if ( isVersion && ( patArr[0] == '[' || patArr[0] == '(' ) )
+            {
+                return isVersionIncludedInRange( String.valueOf( strArr ), String.valueOf( patArr ) );
+            }
+            // No '*'s, so we make a shortcut
+            if ( patIdxEnd != strIdxEnd )
+            {
+                return false; // Pattern and string do not have the same size
+            }
+            for ( int i = 0; i <= patIdxEnd; i++ )
+            {
+                ch = patArr[i];
+                if ( ch != '?' && ch != strArr[i] )
+                {
+                    return false; // Character mismatch
+                }
+            }
+            return true; // String matches against pattern
         }
 
-        final String wholeId = artifact.getId();
-        if ( patterns.contains( wholeId ) )
+        if ( patIdxEnd == 0 )
         {
-            patternsTriggered.add( wholeId );
-            return true;
+            return true; // Pattern contains only '*', which matches anything
         }
 
-        return false;
-    }
-
-    private boolean match( final Artifact artifact, final Iterable<String> patterns )
-    {
-        final String shortId = ArtifactUtils.versionlessKey( artifact );
-        final String id = artifact.getDependencyConflictId();
-        final String wholeId = artifact.getId();
-
-        if ( matchAgainst( wholeId, patterns, false ) )
+        // Process characters before first star
+        while ( ( ch = patArr[patIdxStart] ) != '*' && strIdxStart <= strIdxEnd )
         {
-            return true;
+            if ( ch != '?' && ch != strArr[strIdxStart] )
+            {
+                return false; // Character mismatch
+            }
+            patIdxStart++;
+            strIdxStart++;
         }
-
-        if ( matchAgainst( id, patterns, false ) )
+        if ( strIdxStart > strIdxEnd )
         {
+            // All characters in the string are used. Check if only '*'s are
+            // left in the pattern. If so, we succeeded. Otherwise failure.
+            for ( int i = patIdxStart; i <= patIdxEnd; i++ )
+            {
+                if ( patArr[i] != '*' )
+                {
+                    return false;
+                }
+            }
             return true;
         }
 
-        if ( matchAgainst( shortId, patterns, false ) )
+        // Process characters after last star
+        while ( ( ch = patArr[patIdxEnd] ) != '*' && strIdxStart <= strIdxEnd )
         {
+            if ( ch != '?' && ch != strArr[strIdxEnd] )
+            {
+                return false; // Character mismatch
+            }
+            patIdxEnd--;
+            strIdxEnd--;
+        }
+        if ( strIdxStart > strIdxEnd )
+        {
+            // All characters in the string are used. Check if only '*'s are
+            // left in the pattern. If so, we succeeded. Otherwise failure.
+            for ( int i = patIdxStart; i <= patIdxEnd; i++ )
+            {
+                if ( patArr[i] != '*' )
+                {
+                    return false;
+                }
+            }
             return true;
         }
 
-        if ( actTransitively )
+        // process pattern between stars. padIdxStart and patIdxEnd point
+        // always to a '*'.
+        while ( patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd )
         {
-            final List<String> depTrail = artifact.getDependencyTrail();
-
-            if ( depTrail != null && depTrail.size() > 1 )
+            int patIdxTmp = -1;
+            for ( int i = patIdxStart + 1; i <= patIdxEnd; i++ )
             {
-                for ( String trailItem : depTrail )
+                if ( patArr[i] == '*' )
                 {
-                    if ( matchAgainst( trailItem, patterns, true ) )
+                    patIdxTmp = i;
+                    break;
+                }
+            }
+            if ( patIdxTmp == patIdxStart + 1 )
+            {
+                // Two stars next to each other, skip the first one.
+                patIdxStart++;
+                continue;
+            }
+            // Find the pattern between padIdxStart & padIdxTmp in str between
+            // strIdxStart & strIdxEnd
+            int patLength = ( patIdxTmp - patIdxStart - 1 );
+            int strLength = ( strIdxEnd - strIdxStart + 1 );
+            int foundIdx = -1;
+            strLoop: for ( int i = 0; i <= strLength - patLength; i++ )
+            {
+                for ( int j = 0; j < patLength; j++ )
+                {
+                    ch = patArr[patIdxStart + j + 1];
+                    if ( ch != '?' && ch != strArr[strIdxStart + i + j] )
                     {
-                        return true;
+                        continue strLoop;
                     }
                 }
+
+                foundIdx = strIdxStart + i;
+                break;
+            }
+
+            if ( foundIdx == -1 )
+            {
+                return false;
             }
+
+            patIdxStart = patIdxTmp;
+            strIdxStart = foundIdx + patLength;
         }
 
-        return false;
+        // All characters in the string are used. Check if only '*'s are left
+        // in the pattern. If so, we succeeded. Otherwise failure.
+        for ( int i = patIdxStart; i <= patIdxEnd; i++ )
+        {
+            if ( patArr[i] != '*' )
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    static boolean isVersionIncludedInRange( final String version, final String range )
+    {
+        try
+        {
+            return VersionRange.createFromVersionSpec( range ).containsVersion( new DefaultArtifactVersion( version ) );
+        }
+        catch ( final InvalidVersionSpecificationException e )
+        {
+            return false;
+        }
     }
 
-    private boolean matchAgainst( final String value, final Iterable<String> patterns, final boolean regionMatch )
+    static Pattern compile( String pattern )
     {
-        final String[] tokens = value.split( ":" );
-        for ( String pattern : patterns )
+        if ( pattern.startsWith( "!" ) )
+        {
+            return new NegativePattern( pattern, compile( pattern.substring( 1 ) ) );
+        }
+        else
         {
-            String[] patternTokens = pattern.split( ":" );
-            
-            if ( patternTokens.length == 5 && tokens.length < 5 )
+            char[][] stokens = tokenizeAndSplit( pattern );
+            char[][] tokens = new char[ stokens.length ][];
+            for ( int i = 0; i < stokens.length; i++ )
             {
-                // 4th element is the classifier
-                if ( !"*".equals( patternTokens[3] ) )
+                tokens[i] = anyOrChars( stokens[i] );
+            }
+            if ( tokens.length > 5 )
+            {
+                throw new IllegalArgumentException( "Invalid pattern: " + pattern );
+            }
+            // we only accept 5 tokens if the classifier = '*'
+            if ( tokens.length == 5 )
+            {
+                if ( tokens[3] != ANY )
                 {
-                    // classifier required, cannot be a match
-                    return false;
+                    throw new IllegalArgumentException( "Invalid pattern: " + pattern );
                 }
-                patternTokens = new String[] { patternTokens[0], patternTokens[1], patternTokens[2], patternTokens[4] };
+                tokens = new char[][] { tokens[0], tokens[1], tokens[2], tokens[4] };
             }
-
-            // fail immediately if pattern tokens outnumber tokens to match
-            boolean matched = patternTokens.length <= tokens.length;
-
-            for ( int i = 0; matched && i < patternTokens.length; i++ )
+            //
+            // Check the 4 tokens and build an appropriate Pattern
+            // Special care needs to be taken if the first or the last part is '*'
+            // because this allows the '*' to match multiple tokens
+            //
+            if ( tokens.length == 1 )
             {
-                matched = matches( tokens[i], patternTokens[i] );
+                if ( tokens[0] == ANY )
+                {
+                    // *
+                    return all( pattern );
+                }
+                else
+                {
+                    // [pat0]
+                    return match( pattern, tokens[0], 0 );
+                }
             }
-
-            // case of starting '*' like '*:jar:*'
-            // This really only matches from the end instead.....
-            if ( !matched && patternTokens.length < tokens.length && isFirstPatternWildcard( patternTokens ) )
+            if ( tokens.length == 2 )
             {
-                matched = true;
-                int tokenOffset = tokens.length - patternTokens.length;
-                for ( int i = 0; matched && i < patternTokens.length; i++ )
+                if ( tokens[0] == ANY )
+                {
+                    if ( tokens[1] == ANY )
+                    {
+                        // *:*
+                        return all( pattern );
+                    }
+                    else
+                    {
+                        // *:[pat1]
+                        return match( pattern, tokens[1], 0, 3 );
+                    }
+                }
+                else
                 {
-                    matched = matches( tokens[i + tokenOffset], patternTokens[i] );
+                    if ( tokens[1] == ANY )
+                    {
+                        // [pat0]:*
+                        return match( pattern, tokens[0], 0 );
+                    }
+                    else
+                    {
+                        // [pat0]:[pat1]
+                        Pattern m00 = match( tokens[0], 0 );
+                        Pattern m11 = match( tokens[1], 1 );
+                        return and( pattern, m00, m11 );
+                    }
                 }
             }
-
-            if ( matched )
+            if ( tokens.length == 3 )
             {
-                patternsTriggered.add( pattern );
-                return true;
+                if ( tokens[0] == ANY )
+                {
+                    if ( tokens[1] == ANY )
+                    {
+                        if ( tokens[2] == ANY )
+                        {
+                            // *:*:*
+                            return all( pattern );
+                        }
+                        else
+                        {
+                            // *:*:[pat2]
+                            return match( pattern, tokens[2], 2, 3 );
+                        }
+                    }
+                    else
+                    {
+                        if ( tokens[2] == ANY )
+                        {
+                            // *:[pat1]:*
+                            return match( pattern, tokens[1], 1, 2 );
+                        }
+                        else
+                        {
+                            // *:[pat1]:[pat2]
+                            Pattern m11 = match( tokens[1], 1 );
+                            Pattern m12 = match( tokens[1], 2 );
+                            Pattern m22 = match( tokens[2], 2 );
+                            Pattern m23 = match( tokens[2], 3 );
+                            return or( pattern, and( m11, m22 ), and( m12, m23 ) );
+                        }
+                    }
+                }
+                else
+                {
+                    if ( tokens[1] == ANY )
+                    {
+                        if ( tokens[2] == ANY )
+                        {
+                            // [pat0]:*:*
+                            return match( pattern, tokens[0], 0, 1 );
+                        }
+                        else
+                        {
+                            // [pat0]:*:[pat2]
+                            Pattern m00 = match( tokens[0], 0 );
+                            Pattern m223 = match( tokens[2], 2, 3 );
+                            return and( pattern, m00, m223 );
+                        }
+                    }
+                    else
+                    {
+                        if ( tokens[2] == ANY )
+                        {
+                            // [pat0]:[pat1]:*
+                            Pattern m00 = match( tokens[0], 0 );
+                            Pattern m11 = match( tokens[1], 1 );
+                            return and( pattern, m00, m11 );
+                        }
+                        else
+                        {
+                            // [pat0]:[pat1]:[pat2]
+                            Pattern m00 = match( tokens[0], 0 );
+                            Pattern m11 = match( tokens[1], 1 );
+                            Pattern m22 = match( tokens[2], 2 );
+                            return and( pattern, m00, m11, m22 );
+                        }
+                    }
+                }
             }
-
-            if ( regionMatch && value.contains( pattern ) )
+            if ( tokens.length == 4 )
             {
-                patternsTriggered.add( pattern );
-                return true;
+                List<Pattern> patterns = new ArrayList<>();
+                for ( int i = 0; i < 4; i++ )
+                {
+                    if ( tokens[i] != ANY )
+                    {
+                        patterns.add( match( tokens[i], i ) );
+                    }
+                }
+                return and( pattern, patterns.toArray( new Pattern[0] ) );
             }
-
+            throw new IllegalStateException();
         }
-        return false;
-
     }
 
-    private boolean isFirstPatternWildcard( String[] patternTokens )
+    private static Pattern match( String pattern, char[] token, int posVal )
     {
-        return patternTokens.length > 0 && "*".equals( patternTokens[0] );
+        return match( pattern, token, posVal, posVal );
     }
 
-    /**
-     * Gets whether the specified token matches the specified pattern segment.
-     * 
-     * @param token the token to check
-     * @param pattern the pattern segment to match, as defined above
-     * @return <code>true</code> if the specified token is matched by the specified pattern segment
-     */
-    private boolean matches( final String token, final String pattern )
+    private static Pattern match( char[] token, int posVal )
     {
-        boolean matches;
+        return match( "", token, posVal, posVal );
+    }
 
-        // support full wildcard and implied wildcard
-        if ( "*".equals( pattern ) || pattern.length() == 0 )
+    private static Pattern match( String pattern, char[] token, int posMin, int posMax )
+    {
+        boolean hasWildcard = false;
+        for ( char ch : token )
         {
-            matches = true;
+            if ( ch == '*' || ch == '?' )
+            {
+                hasWildcard = true;
+                break;
+            }
         }
-        // support contains wildcard
-        else if ( pattern.startsWith( "*" ) && pattern.endsWith( "*" ) )
+        if ( hasWildcard || posMax == 3 )
         {
-            final String contains = pattern.substring( 1, pattern.length() - 1 );
-
-            matches = token.contains( contains );
+            return new PosPattern( pattern, token, posMin, posMax );
         }
-        // support leading wildcard
-        else if ( pattern.startsWith( "*" ) )
+        else
         {
-            final String suffix = pattern.substring( 1 );
-
-            matches = token.endsWith( suffix );
+            return new EqPattern( pattern, token, posMin, posMax );
         }
-        // support trailing wildcard
-        else if ( pattern.endsWith( "*" ) )
-        {
-            final String prefix = pattern.substring( 0, pattern.length() - 1 );
+    }
 
-            matches = token.startsWith( prefix );
-        }
-        // support wildcards in the middle of a pattern segment
-        else if ( pattern.indexOf( '*' ) > -1 )
-        {
-            String[] parts = pattern.split( "\\*" );
-            int lastPartEnd = -1;
-            boolean match = true;
+    private static Pattern match( char[] token, int posMin, int posMax )
+    {
+        return new PosPattern( "", token, posMin, posMax );
+    }
 
-            for ( String part : parts )
-            {
-                int idx = token.indexOf( part );
-                if ( idx <= lastPartEnd )
-                {
-                    match = false;
-                    break;
-                }
+    private static Pattern and( String pattern, Pattern... patterns )
+    {
+        return new AndPattern( pattern, patterns );
+    }
 
-                lastPartEnd = idx + part.length();
-            }
+    private static Pattern and( Pattern... patterns )
+    {
+        return and( "", patterns );
+    }
 
-            matches = match;
+    private static Pattern or( String pattern, Pattern... patterns )
+    {
+        return new OrPattern( pattern, patterns );
+    }
+
+    private static Pattern or( Pattern... patterns )
+    {
+        return or( "", patterns );
+    }
+
+    private static Pattern all( String pattern )
+    {
+        return new MatchAllPattern( pattern );
+    }
+
+    static abstract class Pattern
+    {
+        private final String pattern;
+
+        public Pattern( String pattern )
+        {
+            this.pattern = Objects.requireNonNull( pattern );
         }
-        // support versions range
-        else if ( pattern.startsWith( "[" ) || pattern.startsWith( "(" ) )
+
+        public abstract boolean matches( char[][] parts );
+
+        public String translateEquals()
         {
-            matches = isVersionIncludedInRange( token, pattern );
+            return null;
         }
-        // support exact match
-        else
+
+        public String translateEquals( int pos )
         {
-            matches = token.equals( pattern );
+            return null;
         }
 
-        return matches;
+        @Override
+        public String toString() {
+            return pattern;
+        }
     }
 
-    private boolean isVersionIncludedInRange( final String version, final String range )
+    static class AndPattern extends Pattern
     {
-        try
+        private final Pattern[] patterns;
+
+        public AndPattern( String pattern, Pattern[] patterns )
         {
-            return VersionRange.createFromVersionSpec( range ).containsVersion( new DefaultArtifactVersion( version ) );
+            super( pattern );
+            this.patterns = patterns;
         }
-        catch ( final InvalidVersionSpecificationException e )
+
+        @Override
+        public boolean matches( char[][] parts )
         {
-            return false;
+            for ( Pattern pattern : patterns )
+            {
+                if ( !pattern.matches( parts ) )
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        @Override
+        public String translateEquals()
+        {
+            String[] strings = new String[ patterns.length ];
+            for ( int i = 0; i < patterns.length; i++ )
+            {
+                strings[i] = patterns[i].translateEquals( i );
+                if ( strings[i] == null )
+                {
+                    return null;
+                }
+            }
+            StringBuilder sb = new StringBuilder();
+            for ( int i = 0; i < strings.length; i++ )
+            {
+                if ( i > 0 )
+                {
+                    sb.append( ":" );
+                }
+                sb.append( strings[i] );
+            }
+            return sb.toString();
         }
     }
 
-    /** {@inheritDoc} */
-    public void reportMissedCriteria( final Logger logger )
+    static class OrPattern extends Pattern
     {
-        // if there are no patterns, there is nothing to report.
-        if ( !positivePatterns.isEmpty() || !negativePatterns.isEmpty()
-                || !simplePositivePatterns.isEmpty() || !simpleNegativePatterns.isEmpty() )
-        {
-            final List<String> missed = new ArrayList<>();
-            missed.addAll( positivePatterns );
-            missed.addAll( simplePositivePatterns );
-            missed.addAll( negativePatterns );
-            missed.addAll( simpleNegativePatterns );
+        private final Pattern[] patterns;
 
-            missed.removeAll( patternsTriggered );
+        public OrPattern( String pattern, Pattern[] patterns )
+        {
+            super( pattern );
+            this.patterns = patterns;
+        }
 
-            if ( !missed.isEmpty() && logger.isWarnEnabled() )
+        @Override
+        public boolean matches( char[][] parts )
+        {
+            for ( Pattern pattern : patterns )
             {
-                final StringBuilder buffer = new StringBuilder();
-
-                buffer.append( "The following patterns were never triggered in this " );
-                buffer.append( getFilterDescription() );
-                buffer.append( ':' );
-
-                for ( String pattern : missed )
+                if ( pattern.matches( parts ) )
                 {
-                    buffer.append( "\no  '" ).append( pattern ).append( "'" );
+                    return true;
                 }
-
-                buffer.append( "\n" );
-
-                logger.warn( buffer.toString() );
             }
+            return false;
         }
     }
 
-    @Override
-    public String toString()
+    static class PosPattern extends Pattern
     {
-        return "Includes filter:" + getPatternsAsString();
-    }
+        private final char[] token;
+        private final int posMin;
+        private final int posMax;
 
-    /**
-     * @return pattern as a string.
-     */
-    protected String getPatternsAsString()
-    {
-        final StringBuilder buffer = new StringBuilder();
-        for ( String pattern : simplePositivePatterns )
+        public PosPattern( String pattern, char[] token, int posMin, int posMax )
         {
-            buffer.append( "\no '" ).append( pattern ).append( "'" );
+            super( pattern );
+            this.token = token;
+            this.posMin = posMin;
+            this.posMax = posMax;
         }
-        for ( String pattern : positivePatterns )
+
+        @Override
+        public boolean matches( char[][] parts )
         {
-            buffer.append( "\no '" ).append( pattern ).append( "'" );
+            for ( int i = posMin; i <= posMax; i++ )
+            {
+                if ( match( token, parts[i], i == 3 ) )
+                {
+                    return true;
+                }
+            }
+            return false;
         }
-
-        return buffer.toString();
     }
 
-    /**
-     * @return description.
-     */
-    protected String getFilterDescription()
+    static class EqPattern extends Pattern
     {
-        return "artifact inclusion filter";
-    }
+        private final char[] token;
+        private final int posMin;
+        private final int posMax;
 
-    /** {@inheritDoc} */
-    public void reportFilteredArtifacts( final Logger logger )
-    {
-        if ( !filteredArtifactIds.isEmpty() && logger.isDebugEnabled() )
+        public EqPattern( String pattern, char[] token, int posMin, int posMax )
         {
-            final StringBuilder buffer =
-                new StringBuilder( "The following artifacts were removed by this " + getFilterDescription() + ": " );
+            super( pattern );
+            this.token = token;
+            this.posMin = posMin;
+            this.posMax = posMax;
+        }
 
-            for ( String artifactId : filteredArtifactIds )
+        @Override
+        public boolean matches( char[][] parts )
+        {
+            for ( int i = posMin; i <= posMax; i++ )
             {
-                buffer.append( '\n' ).append( artifactId );
+                if (Arrays.equals( token, parts[i] ) )
+                {
+                    return true;
+                }
             }
+            return false;
+        }
 
-            logger.debug( buffer.toString() );
+        public String translateEquals( int pos )
+        {
+            return posMin == pos && posMax == pos
+                && ( pos < 3 || ( token[0] != '[' && token[0] != '(' ) )
+                    ? String.valueOf( token ) : null;
         }
+
     }
 
-    /** {@inheritDoc} */
-    public boolean hasMissedCriteria()
+    static class MatchAllPattern extends Pattern
     {
-        // if there are no patterns, there is nothing to report.
-        if ( !positivePatterns.isEmpty() || !negativePatterns.isEmpty() )
+        public MatchAllPattern( String pattern )
+        {
+            super( pattern );
+        }
+
+        @Override
+        public boolean matches( char[][] parts )
         {
-            final List<String> missed = new ArrayList<>();
-            missed.addAll( positivePatterns );
-            missed.addAll( negativePatterns );
+            return true;
+        }
+    }
 
-            missed.removeAll( patternsTriggered );
+    static class NegativePattern extends Pattern
+    {
+        private final Pattern inner;
 
-            return !missed.isEmpty();
+        NegativePattern( String pattern, Pattern inner )
+        {
+            super( pattern );
+            this.inner = inner;
         }
 
-        return false;
+        @Override
+        public boolean matches( char[][] parts )
+        {
+            return inner.matches( parts );
+        }
     }
 
 }
diff --git a/src/test/java/org/apache/maven/shared/artifact/filter/AbstractPatternArtifactFilterTest.java b/src/test/java/org/apache/maven/shared/artifact/filter/AbstractPatternArtifactFilterTest.java
index bbd46f0..cb4ad8d 100644
--- a/src/test/java/org/apache/maven/shared/artifact/filter/AbstractPatternArtifactFilterTest.java
+++ b/src/test/java/org/apache/maven/shared/artifact/filter/AbstractPatternArtifactFilterTest.java
@@ -52,16 +52,16 @@ public abstract class AbstractPatternArtifactFilterTest
         final String artifactId2 = "artifact2";
 
         Artifact artifact1 = mock( Artifact.class );
-        when( artifact1.getDependencyConflictId() ).thenReturn( groupId1 + ":" + artifactId1 + ":jar" );
         when( artifact1.getGroupId() ).thenReturn( groupId1 );
         when( artifact1.getArtifactId() ).thenReturn( artifactId1 );
-        when( artifact1.getId() ).thenReturn( groupId1 + ":" + artifactId1 + ":jar:version" );
+        when( artifact1.getType() ).thenReturn( "jar" );
+        when( artifact1.getBaseVersion() ).thenReturn( "version" );
         
         Artifact artifact2 = mock( Artifact.class );
-        when( artifact2.getDependencyConflictId() ).thenReturn( groupId2 + ":" + artifactId2 + ":jar" );
         when( artifact2.getGroupId() ).thenReturn( groupId2 );
         when( artifact2.getArtifactId() ).thenReturn( artifactId2 );
-        when( artifact2.getId() ).thenReturn( groupId2 + ":" + artifactId2 + ":jar:version" );
+        when( artifact2.getType() ).thenReturn( "jar" );
+        when( artifact2.getBaseVersion() ).thenReturn( "version" );
 
         final List<String> patterns = new ArrayList<>();
         patterns.add( groupId1 + ":" + artifactId1 + ":*" );
@@ -91,16 +91,16 @@ public abstract class AbstractPatternArtifactFilterTest
         final String artifactId2 = "artifact2";
 
         Artifact artifact1 = mock( Artifact.class );
-        when( artifact1.getDependencyConflictId() ).thenReturn( groupId1 + ":" + artifactId1 + ":jar" );
         when( artifact1.getGroupId() ).thenReturn( groupId1 );
         when( artifact1.getArtifactId() ).thenReturn( artifactId1 );
-        when( artifact1.getId() ).thenReturn( groupId1 + ":" + artifactId1 + ":jar:version" );
+        when( artifact1.getType() ).thenReturn( "jar" );
+        when( artifact1.getBaseVersion() ).thenReturn( "version" );
 
         Artifact artifact2 = mock( Artifact.class );
-        when( artifact2.getDependencyConflictId() ).thenReturn( groupId2 + ":" + artifactId2 + ":jar" );
         when( artifact2.getGroupId() ).thenReturn( groupId2 );
         when( artifact2.getArtifactId() ).thenReturn( artifactId2 );
-        when( artifact2.getId() ).thenReturn( groupId2 + ":" + artifactId2 + ":jar:version" );
+        when( artifact2.getType() ).thenReturn( "jar" );
+        when( artifact2.getBaseVersion() ).thenReturn( "version" );
 
         final List<String> patterns = new ArrayList<>();
         patterns.add( groupId1 + "*" );
@@ -127,10 +127,10 @@ public abstract class AbstractPatternArtifactFilterTest
         final String artifactId = "artifact";
 
         Artifact artifact = mock( Artifact.class );
-        when( artifact.getDependencyConflictId() ).thenReturn( groupId + ":" + artifactId + ":jar" );
         when( artifact.getGroupId() ).thenReturn( groupId );
         when( artifact.getArtifactId() ).thenReturn( artifactId );
-        when( artifact.getId() ).thenReturn( groupId + ":" + artifactId + ":jar:version" );
+        when( artifact.getType() ).thenReturn( "jar" );
+        when( artifact.getBaseVersion() ).thenReturn( "version" );
 
         final ArtifactFilter filter = createFilter( Collections.singletonList( groupId + ":" + artifactId ) );
 
@@ -151,10 +151,10 @@ public abstract class AbstractPatternArtifactFilterTest
         final String artifactId = "artifact";
 
         Artifact artifact = mock( Artifact.class );
-        when( artifact.getDependencyConflictId() ).thenReturn( groupId + ":" + artifactId + ":jar" );
         when( artifact.getGroupId() ).thenReturn( groupId );
         when( artifact.getArtifactId() ).thenReturn( artifactId );
-        when( artifact.getId() ).thenReturn( groupId + ":" + artifactId + ":jar:version" );
+        when( artifact.getType() ).thenReturn( "jar" );
+        when( artifact.getBaseVersion() ).thenReturn( "version" );
 
         final ArtifactFilter filter = createFilter( Collections.singletonList( groupId + ":" + artifactId + ":jar" ) );
 
@@ -175,10 +175,10 @@ public abstract class AbstractPatternArtifactFilterTest
         final String artifactId = "artifact";
 
         Artifact artifact = mock( Artifact.class );
-        when( artifact.getDependencyConflictId() ).thenReturn( groupId + ":" + artifactId + ":jar" );
         when( artifact.getGroupId() ).thenReturn( groupId );
         when( artifact.getArtifactId() ).thenReturn( artifactId );
-        when( artifact.getId() ).thenReturn( groupId + ":" + artifactId + ":jar:version" );
+        when( artifact.getType() ).thenReturn( "jar" );
+        when( artifact.getBaseVersion() ).thenReturn( "version" );
 
         final List<String> patterns = new ArrayList<>();
         patterns.add( "otherGroup:" + artifactId + ":jar" );
@@ -203,10 +203,10 @@ public abstract class AbstractPatternArtifactFilterTest
         final String artifactId = "artifact";
 
         Artifact artifact = mock( Artifact.class );
-        when( artifact.getDependencyConflictId() ).thenReturn( groupId + ":" + artifactId + ":jar" );
         when( artifact.getGroupId() ).thenReturn( groupId );
         when( artifact.getArtifactId() ).thenReturn( artifactId );
-        when( artifact.getId() ).thenReturn( groupId + ":" + artifactId + ":jar:version" );
+        when( artifact.getType() ).thenReturn( "jar" );
+        when( artifact.getBaseVersion() ).thenReturn( "version" );
 
         final List<String> patterns = new ArrayList<>();
         patterns.add( groupId + "otherArtifact:jar" );
@@ -231,10 +231,10 @@ public abstract class AbstractPatternArtifactFilterTest
         final String artifactId = "artifact";
 
         Artifact artifact = mock( Artifact.class );
-        when( artifact.getDependencyConflictId() ).thenReturn( groupId + ":" + artifactId + ":jar" );
         when( artifact.getGroupId() ).thenReturn( groupId );
         when( artifact.getArtifactId() ).thenReturn( artifactId );
-        when( artifact.getId() ).thenReturn( groupId + ":" + artifactId + ":jar:version" );
+        when( artifact.getType() ).thenReturn( "jar" );
+        when( artifact.getBaseVersion() ).thenReturn( "version" );
 
         final List<String> patterns = new ArrayList<>();
         patterns.add( "otherGroup:otherArtifact:jar" );
@@ -265,10 +265,10 @@ public abstract class AbstractPatternArtifactFilterTest
         final List<String> patterns = Collections.singletonList( depTrailItem );
 
         Artifact artifact = mock( Artifact.class );
-        when( artifact.getDependencyConflictId() ).thenReturn( groupId + ":" + artifactId + ":jar" );
         when( artifact.getGroupId() ).thenReturn( groupId );
         when( artifact.getArtifactId() ).thenReturn( artifactId );
-        when( artifact.getId() ).thenReturn( groupId + ":" + artifactId + ":jar:version" );
+        when( artifact.getType() ).thenReturn( "jar" );
+        when( artifact.getBaseVersion() ).thenReturn( "version" );
         when( artifact.getDependencyTrail() ).thenReturn( depTrail );
 
         final ArtifactFilter filter = createFilter( patterns, true );
@@ -296,10 +296,10 @@ public abstract class AbstractPatternArtifactFilterTest
         final List<String> patterns = Collections.singletonList( "otherGroup*" );
 
         Artifact artifact = mock( Artifact.class );
-        when( artifact.getDependencyConflictId() ).thenReturn( groupId + ":" + artifactId + ":jar" );
         when( artifact.getGroupId() ).thenReturn( groupId );
         when( artifact.getArtifactId() ).thenReturn( artifactId );
-        when( artifact.getId() ).thenReturn( groupId + ":" + artifactId + ":jar:version" );
+        when( artifact.getType() ).thenReturn( "jar" );
+        when( artifact.getBaseVersion() ).thenReturn( "version" );
         when( artifact.getDependencyTrail() ).thenReturn( depTrail );
 
         final ArtifactFilter filter = createFilter( patterns, true );
@@ -321,10 +321,10 @@ public abstract class AbstractPatternArtifactFilterTest
         final String artifactId = "artifact";
 
         Artifact artifact = mock( Artifact.class );
-        when( artifact.getDependencyConflictId() ).thenReturn( groupId + ":" + artifactId + ":jar" );
         when( artifact.getGroupId() ).thenReturn( groupId );
         when( artifact.getArtifactId() ).thenReturn( artifactId );
-        when( artifact.getId() ).thenReturn( groupId + ":" + artifactId + ":jar:version" );
+        when( artifact.getType() ).thenReturn( "jar" );
+        when( artifact.getBaseVersion() ).thenReturn( "version" );
 
         final List<String> patterns = new ArrayList<>();
         patterns.add( "!group:artifact:jar" );
@@ -348,10 +348,10 @@ public abstract class AbstractPatternArtifactFilterTest
         final String artifactId = "artifact";
 
         Artifact artifact = mock( Artifact.class );
-        when( artifact.getDependencyConflictId() ).thenReturn( groupId + ":" + artifactId + ":jar" );
         when( artifact.getGroupId() ).thenReturn( groupId );
         when( artifact.getArtifactId() ).thenReturn( artifactId );
-        when( artifact.getId() ).thenReturn( groupId + ":" + artifactId + ":jar:version" );
+        when( artifact.getType() ).thenReturn( "jar" );
+        when( artifact.getBaseVersion() ).thenReturn( "version" );
 
         final List<String> patterns = new ArrayList<>();
         patterns.add( "group:*:jar" );
@@ -376,10 +376,10 @@ public abstract class AbstractPatternArtifactFilterTest
 
         Artifact artifact = mock( Artifact.class );
 
-        when( artifact.getDependencyConflictId() ).thenReturn( groupId + ":" + artifactId + ":jar" );
         when( artifact.getGroupId() ).thenReturn( groupId );
         when( artifact.getArtifactId() ).thenReturn( artifactId );
-        when( artifact.getId() ).thenReturn( groupId + ":" + artifactId + ":jar:version" );
+        when( artifact.getType() ).thenReturn( "jar" );
+        when( artifact.getBaseVersion() ).thenReturn( "version" );
 
         final List<String> patterns = new ArrayList<>();
         patterns.add( "*:artifact:*" );
@@ -404,10 +404,10 @@ public abstract class AbstractPatternArtifactFilterTest
 
         Artifact artifact = mock( Artifact.class );
 
-        when( artifact.getDependencyConflictId() ).thenReturn( groupId + ":" + artifactId + ":jar" );
         when( artifact.getGroupId() ).thenReturn( groupId );
         when( artifact.getArtifactId() ).thenReturn( artifactId );
-        when( artifact.getId() ).thenReturn( groupId + ":" + artifactId + ":jar:version" );
+        when( artifact.getType() ).thenReturn( "jar" );
+        when( artifact.getBaseVersion() ).thenReturn( "version" );
 
         final List<String> patterns = new ArrayList<>();
         patterns.add( "group:some-*-id" );
@@ -432,10 +432,10 @@ public abstract class AbstractPatternArtifactFilterTest
 
         Artifact artifact = mock( Artifact.class );
 
-        when( artifact.getDependencyConflictId() ).thenReturn( groupId + ":" + artifactId + ":jar" );
         when( artifact.getGroupId() ).thenReturn( groupId );
         when( artifact.getArtifactId() ).thenReturn( artifactId );
-        when( artifact.getId() ).thenReturn( groupId + ":" + artifactId + ":jar:version" );
+        when( artifact.getType() ).thenReturn( "jar" );
+        when( artifact.getBaseVersion() ).thenReturn( "version" );
 
         final List<String> patterns = new ArrayList<>();
         patterns.add( "some.group*" );
@@ -465,16 +465,16 @@ public abstract class AbstractPatternArtifactFilterTest
         final List<String> patterns = Collections.singletonList( "*:jar:*" );
 
         Artifact artifact1 = mock( Artifact.class );
-        when( artifact1.getDependencyConflictId() ).thenReturn( groupId + ":" + artifactId + ":jar" );
         when( artifact1.getGroupId() ).thenReturn( groupId );
         when( artifact1.getArtifactId() ).thenReturn( artifactId );
-        when( artifact1.getId() ).thenReturn( groupId + ":" + artifactId + ":jar:version" );
-        
+        when( artifact1.getType() ).thenReturn( "jar" );
+        when( artifact1.getBaseVersion() ).thenReturn( "version" );
+
         Artifact artifact2 = mock( Artifact.class );
-        when( artifact2.getDependencyConflictId() ).thenReturn( otherGroup + ":" + otherArtifact + ":" + otherType );
         when( artifact2.getGroupId() ).thenReturn( otherGroup );
         when( artifact2.getArtifactId() ).thenReturn( otherArtifact );
-        when( artifact2.getId() ).thenReturn( otherGroup + ":" + otherArtifact + ":" + otherType + ":version" );
+        when( artifact2.getType() ).thenReturn( otherType );
+        when( artifact2.getBaseVersion() ).thenReturn( "version" );
         when( artifact2.getDependencyTrail() ).thenReturn( Collections.<String> emptyList() );
 
         final ArtifactFilter filter = createFilter( patterns, true );
@@ -498,10 +498,10 @@ public abstract class AbstractPatternArtifactFilterTest
         final String artifactId = "some-artifact-id";
 
         Artifact artifact = mock( Artifact.class );
-        when( artifact.getDependencyConflictId() ).thenReturn( groupId + ":" + artifactId + ":jar" );
         when( artifact.getGroupId() ).thenReturn( groupId );
         when( artifact.getArtifactId() ).thenReturn( artifactId );
-        when( artifact.getId() ).thenReturn( groupId + ":" + artifactId + ":jar:version" );
+        when( artifact.getType() ).thenReturn( "jar" );
+        when( artifact.getBaseVersion() ).thenReturn( "version" );
 
         final List<String> patterns = new ArrayList<>();
         patterns.add( "com.mycompany.*:*:jar:*:*" );
@@ -517,4 +517,31 @@ public abstract class AbstractPatternArtifactFilterTest
             assertTrue( filter.include( artifact ) );
         }
     }
+
+    @Test
+    public void testWithVersionRange()
+    {
+        final String groupId = "com.mycompany.myproject";
+        final String artifactId = "some-artifact-id";
+
+        Artifact artifact = mock( Artifact.class );
+        when( artifact.getGroupId() ).thenReturn( groupId );
+        when( artifact.getArtifactId() ).thenReturn( artifactId );
+        when( artifact.getType() ).thenReturn( "jar" );
+        when( artifact.getBaseVersion() ).thenReturn( "1.1" );
+
+        final List<String> patterns = new ArrayList<>();
+        patterns.add( "com.mycompany.myproject:some-artifact-id:jar:*:[1.0,2.0)" );
+
+        final ArtifactFilter filter = createFilter( patterns );
+
+        if ( isInclusionNotExpected() )
+        {
+            assertFalse( filter.include( artifact ) );
+        }
+        else
+        {
+            assertTrue( filter.include( artifact ) );
+        }
+    }
 }
diff --git a/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java b/src/test/java/org/apache/maven/shared/artifact/filter/OldPatternIncludesArtifactFilter.java
similarity index 78%
copy from src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
copy to src/test/java/org/apache/maven/shared/artifact/filter/OldPatternIncludesArtifactFilter.java
index 8d01c71..df492bb 100644
--- a/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
+++ b/src/test/java/org/apache/maven/shared/artifact/filter/OldPatternIncludesArtifactFilter.java
@@ -22,7 +22,6 @@ package org.apache.maven.shared.artifact.filter;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -36,20 +35,16 @@ import org.codehaus.plexus.logging.Logger;
 
 /**
  * TODO: include in maven-artifact in future
- * 
+ *
  * @author <a href="mailto:brett@apache.org">Brett Porter</a>
  * @see StrictPatternIncludesArtifactFilter
  */
-public class PatternIncludesArtifactFilter
-    implements ArtifactFilter, StatisticsReportingArtifactFilter
+public class OldPatternIncludesArtifactFilter
+        implements ArtifactFilter, StatisticsReportingArtifactFilter
 {
-    private final Set<String> simplePositivePatterns;
-
-    private final Set<String> positivePatterns;
-
-    private final Set<String> simpleNegativePatterns;
+    private final List<String> positivePatterns;
 
-    private final Set<String> negativePatterns;
+    private final List<String> negativePatterns;
 
     private final boolean actTransitively;
 
@@ -60,7 +55,7 @@ public class PatternIncludesArtifactFilter
     /**
      * @param patterns The pattern to be used.
      */
-    public PatternIncludesArtifactFilter( final Collection<String> patterns )
+    public OldPatternIncludesArtifactFilter( final Collection<String> patterns )
     {
         this( patterns, false );
     }
@@ -69,46 +64,28 @@ public class PatternIncludesArtifactFilter
      * @param patterns The pattern to be used.
      * @param actTransitively transitive yes/no.
      */
-    public PatternIncludesArtifactFilter( final Collection<String> patterns, final boolean actTransitively )
+    public OldPatternIncludesArtifactFilter( final Collection<String> patterns, final boolean actTransitively )
     {
         this.actTransitively = actTransitively;
-        final Set<String> pos = new LinkedHashSet<>();
-        final Set<String> spos = new LinkedHashSet<>();
-        final Set<String> neg = new LinkedHashSet<>();
-        final Set<String> sneg = new LinkedHashSet<>();
+        final List<String> pos = new ArrayList<>();
+        final List<String> neg = new ArrayList<>();
         if ( patterns != null && !patterns.isEmpty() )
         {
             for ( String pattern : patterns )
             {
                 if ( pattern.startsWith( "!" ) )
                 {
-                    if ( pattern.contains( "*" ) )
-                    {
-                        neg.add( pattern.substring( 1 ) );
-                    }
-                    else
-                    {
-                        sneg.add( pattern.substring( 1 ) );
-                    }
+                    neg.add( pattern.substring( 1 ) );
                 }
                 else
                 {
-                    if ( pattern.contains( "*" ) )
-                    {
-                        pos.add( pattern );
-                    }
-                    else
-                    {
-                        spos.add( pattern );
-                    }
+                    pos.add( pattern );
                 }
             }
         }
 
         positivePatterns = pos;
-        simplePositivePatterns = spos;
         negativePatterns = neg;
-        simpleNegativePatterns = sneg;
     }
 
     /** {@inheritDoc} */
@@ -143,13 +120,6 @@ public class PatternIncludesArtifactFilter
 
     private Boolean negativeMatch( final Artifact artifact )
     {
-        if ( simpleNegativePatterns != null && !simpleNegativePatterns.isEmpty() )
-        {
-            if ( simpleMatch( artifact, simpleNegativePatterns ) )
-            {
-                return true;
-            }
-        }
         if ( negativePatterns == null || negativePatterns.isEmpty() )
         {
             return null;
@@ -166,13 +136,6 @@ public class PatternIncludesArtifactFilter
      */
     protected Boolean positiveMatch( final Artifact artifact )
     {
-        if ( simplePositivePatterns != null && !simplePositivePatterns.isEmpty() )
-        {
-            if ( simpleMatch( artifact, simplePositivePatterns ) )
-            {
-                return true;
-            }
-        }
         if ( positivePatterns == null || positivePatterns.isEmpty() )
         {
             return null;
@@ -183,33 +146,7 @@ public class PatternIncludesArtifactFilter
         }
     }
 
-    private boolean simpleMatch( final Artifact artifact, final Set<String> patterns )
-    {
-        final String shortId = ArtifactUtils.versionlessKey( artifact );
-        if ( patterns.contains( shortId ) )
-        {
-            patternsTriggered.add( shortId );
-            return true;
-        }
-
-        final String id = artifact.getDependencyConflictId();
-        if ( patterns.contains( id ) )
-        {
-            patternsTriggered.add( id );
-            return true;
-        }
-
-        final String wholeId = artifact.getId();
-        if ( patterns.contains( wholeId ) )
-        {
-            patternsTriggered.add( wholeId );
-            return true;
-        }
-
-        return false;
-    }
-
-    private boolean match( final Artifact artifact, final Iterable<String> patterns )
+    private boolean match( final Artifact artifact, final List<String> patterns )
     {
         final String shortId = ArtifactUtils.versionlessKey( artifact );
         final String id = artifact.getDependencyConflictId();
@@ -249,13 +186,13 @@ public class PatternIncludesArtifactFilter
         return false;
     }
 
-    private boolean matchAgainst( final String value, final Iterable<String> patterns, final boolean regionMatch )
+    private boolean matchAgainst( final String value, final List<String> patterns, final boolean regionMatch )
     {
         final String[] tokens = value.split( ":" );
         for ( String pattern : patterns )
         {
             String[] patternTokens = pattern.split( ":" );
-            
+
             if ( patternTokens.length == 5 && tokens.length < 5 )
             {
                 // 4th element is the classifier
@@ -311,7 +248,7 @@ public class PatternIncludesArtifactFilter
 
     /**
      * Gets whether the specified token matches the specified pattern segment.
-     * 
+     *
      * @param token the token to check
      * @param pattern the pattern segment to match, as defined above
      * @return <code>true</code> if the specified token is matched by the specified pattern segment
@@ -397,14 +334,11 @@ public class PatternIncludesArtifactFilter
     public void reportMissedCriteria( final Logger logger )
     {
         // if there are no patterns, there is nothing to report.
-        if ( !positivePatterns.isEmpty() || !negativePatterns.isEmpty()
-                || !simplePositivePatterns.isEmpty() || !simpleNegativePatterns.isEmpty() )
+        if ( !positivePatterns.isEmpty() || !negativePatterns.isEmpty() )
         {
             final List<String> missed = new ArrayList<>();
             missed.addAll( positivePatterns );
-            missed.addAll( simplePositivePatterns );
             missed.addAll( negativePatterns );
-            missed.addAll( simpleNegativePatterns );
 
             missed.removeAll( patternsTriggered );
 
@@ -440,10 +374,6 @@ public class PatternIncludesArtifactFilter
     protected String getPatternsAsString()
     {
         final StringBuilder buffer = new StringBuilder();
-        for ( String pattern : simplePositivePatterns )
-        {
-            buffer.append( "\no '" ).append( pattern ).append( "'" );
-        }
         for ( String pattern : positivePatterns )
         {
             buffer.append( "\no '" ).append( pattern ).append( "'" );
@@ -466,7 +396,7 @@ public class PatternIncludesArtifactFilter
         if ( !filteredArtifactIds.isEmpty() && logger.isDebugEnabled() )
         {
             final StringBuilder buffer =
-                new StringBuilder( "The following artifacts were removed by this " + getFilterDescription() + ": " );
+                    new StringBuilder( "The following artifacts were removed by this " + getFilterDescription() + ": " );
 
             for ( String artifactId : filteredArtifactIds )
             {
@@ -495,4 +425,4 @@ public class PatternIncludesArtifactFilter
         return false;
     }
 
-}
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/maven/shared/artifact/filter/PatternFilterPerfTest.java b/src/test/java/org/apache/maven/shared/artifact/filter/PatternFilterPerfTest.java
new file mode 100644
index 0000000..159d979
--- /dev/null
+++ b/src/test/java/org/apache/maven/shared/artifact/filter/PatternFilterPerfTest.java
@@ -0,0 +1,122 @@
+package org.apache.maven.shared.artifact.filter;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DefaultArtifact;
+import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+import org.openjdk.jmh.runner.options.TimeValue;
+
+@BenchmarkMode(Mode.Throughput)
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+@Warmup(iterations = 3, time = 3, timeUnit = TimeUnit.SECONDS)
+public class PatternFilterPerfTest {
+
+    @State(Scope.Benchmark)
+    static public class OldPatternState {
+
+        @Param({
+                "groupId:artifact-00,groupId:artifact-01,groupId:artifact-02,groupId:artifact-03,groupId:artifact-04,groupId:artifact-05,groupId:artifact-06,groupId:artifact-07,groupId:artifact-08,groupId:artifact-09",
+                "groupId:artifact-99",
+                "groupId:artifact-*",
+                "*:artifact-99",
+                "*:artifact-*",
+                "*:artifact-*:*",
+                "*:artifact-99:*",
+        })
+        public String patterns;
+
+        ArtifactFilter filter;
+        Artifact artifact;
+
+        @Setup(Level.Invocation)
+        public void setup()
+        {
+            filter = new OldPatternIncludesArtifactFilter( Arrays.asList( patterns.split( "," ) ) );
+            artifact = new DefaultArtifact(
+                    "groupId", "artifact-99", "1.0", "runtime",
+                    "jar", "", null
+            );
+        }
+
+    }
+
+    @State(Scope.Benchmark)
+    static public class NewPatternState {
+
+        @Param({
+                "groupId:artifact-00,groupId:artifact-01,groupId:artifact-02,groupId:artifact-03,groupId:artifact-04,groupId:artifact-05,groupId:artifact-06,groupId:artifact-07,groupId:artifact-08,groupId:artifact-09",
+                "groupId:artifact-99",
+                "groupId:artifact-*",
+                "*:artifact-99",
+                "*:artifact-*",
+                "*:artifact-*:*",
+                "*:artifact-99:*",
+        })
+        public String patterns;
+
+        ArtifactFilter filter;
+        Artifact artifact;
+
+        @Setup(Level.Invocation)
+        public void setup()
+        {
+            filter = new PatternIncludesArtifactFilter( Arrays.asList( patterns.split( "," ) ) );
+            artifact = new DefaultArtifact(
+                    "groupId", "artifact-99", "1.0", "runtime",
+                    "jar", "", null
+            );
+        }
+
+    }
+
+
+    @Benchmark
+    public boolean newPatternTest(NewPatternState state )
+    {
+        return state.filter.include( state.artifact );
+    }
+
+    @Benchmark
+    public boolean oldPatternTest(OldPatternState state )
+    {
+        return state.filter.include( state.artifact );
+    }
+
+    public static void main( String... args )
+            throws RunnerException
+    {
+        Options opts = new OptionsBuilder()
+                .measurementIterations( 3 )
+                .measurementTime( TimeValue.milliseconds( 3000 ) )
+                .forks( 1 )
+                .include( "org.apache.maven.shared.artifact.filter.PatternFilterPerfTest" )
+                .build();
+        new Runner( opts ).run();
+    }
+}