
org.refcodes.matcher.impls.PathMatcherImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of refcodes-matcher Show documentation
Show all versions of refcodes-matcher Show documentation
Artifact for matcher frameworks and matching issues.
// /////////////////////////////////////////////////////////////////////////////
// REFCODES.ORG
// =============================================================================
// This code is copyright (c) by Siegfried Steiner, Munich, Germany and licensed
// under the following (see "http://en.wikipedia.org/wiki/Multi-licensing")
// licenses:
// =============================================================================
// GNU General Public License, v3.0 ("http://www.gnu.org/licenses/gpl-3.0.html")
// together with the GPL linking exception applied; as being applied by the GNU
// Classpath ("http://www.gnu.org/software/classpath/license.html")
// =============================================================================
// Apache License, v2.0 ("http://www.apache.org/licenses/LICENSE-2.0")
// =============================================================================
// Please contact the copyright holding author(s) of the software artifacts in
// question for licensing issues not being covered by the above listed licenses,
// also regarding commercial licensing models or regarding the compatibility
// with other open source licenses.
// /////////////////////////////////////////////////////////////////////////////
package org.refcodes.matcher.impls;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.refcodes.data.Delimiter;
import org.refcodes.matcher.Matcher;
import org.refcodes.matcher.PathMatcher;
import org.refcodes.matcher.WildcardSubstitutes;
/**
* Implements the {@link PathMatcher} interface.
*/
public class PathMatcherImpl implements PathMatcher {
// /////////////////////////////////////////////////////////////////////////
// CONSTANTS:
// /////////////////////////////////////////////////////////////////////////
private static final String WILDCARD_NAME_PATTERN = "(?<=\\$\\{).*?(?=\\}\\=)"; // ${name}=
private static final int WILDCARD_NAME_PREFIX_LENGTH = 2; // "${"
private static final int WILDCARD_NAME_SUFFIX_LENGTH = 2; // "}="
private static final String WILDCARD_ASTERISK = "([^\\/]*)";
private static final String WILDCARD_DOUBOLE_ASTERISK = "(.*)";
private static final String WILDCARD_QUESTION_MARK = "(\\\\w)";
private static final String REGEX_SAFE_SLASH = "\\/";
private static final String REGEX_SAFE_DOT = "\\.";
// /////////////////////////////////////////////////////////////////////////
// VARIABLES:
// /////////////////////////////////////////////////////////////////////////
private Pattern _matchee;
private String _pathPattern = null;
private String[] _wildcardNames = null;
// /////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS:
// /////////////////////////////////////////////////////////////////////////
/**
* Constructs an ANT Path {@link Matcher}, matching its ANT path pattern
* against the path provided to the {@link #isMatching(String)} method.
*
* The {@link Delimiter#PATH_DELIMITER} is used as default path delimiter.
*
* The {@link PathMatcherImpl} applies the following rules from the ANT path
* pattern to the path provided via {@link #isMatching(String)} method:
*
* A single asterisk ("*") matches zero or more characters within a path
* name. A double asterisk ("**") matches zero or more characters across
* directory levels. A question mark ("?") matches exactly one character
* within a path name.
*
* @param aPathPattern The pattern to be used when matching a path via
* {@link #isMatching(String)}.
*/
public PathMatcherImpl( String aPathPattern ) {
assert (aPathPattern != null);
_pathPattern = aPathPattern;
// Convert the wildcards into regex pattern groups -->
String theRegex = aPathPattern;
theRegex = aPathPattern.replaceAll( "/", REGEX_SAFE_SLASH );
theRegex = theRegex.replaceAll( "\\.", REGEX_SAFE_DOT );
theRegex = theRegex.replaceAll( "(?
Pattern theJokerPattern = Pattern.compile( WILDCARD_NAME_PATTERN );
java.util.regex.Matcher eJokerMatcher = theJokerPattern.matcher( theRegex );
String eTruncated, eName, eHead, eTail;
String theAsterisk = WILDCARD_ASTERISK.replaceAll( "\\\\", "" );
String theDoubleAsterisk = WILDCARD_DOUBOLE_ASTERISK.replaceAll( "(\\\\)\\\\", "$1" );
String theQuestionMark = WILDCARD_QUESTION_MARK.replaceAll( "(\\\\)\\\\", "$1" );
List theWildcardNames = new ArrayList<>();
while ( eJokerMatcher.find() ) {
eTruncated = theRegex.substring( eJokerMatcher.end() + WILDCARD_NAME_SUFFIX_LENGTH );
if ( !eTruncated.startsWith( theAsterisk ) && !eTruncated.startsWith( theDoubleAsterisk ) && !eTruncated.startsWith( theQuestionMark ) ) { throw new IllegalArgumentException( "Your wildcard name (such as \"" + theRegex.substring( eJokerMatcher.start(), eJokerMatcher.start() ) + "\") in pattern <" + aPathPattern + "> must prefix a wildcard such as \"" + theAsterisk + "\" or \"" + theDoubleAsterisk + "\" or \"" + theQuestionMark + "!" ); }
eName = theRegex.substring( eJokerMatcher.start(), eJokerMatcher.end() );
theWildcardNames.add( eName );
eHead = theRegex.substring( 0, eJokerMatcher.start() - WILDCARD_NAME_PREFIX_LENGTH );
eTail = theRegex.substring( eJokerMatcher.end() + WILDCARD_NAME_SUFFIX_LENGTH );
eTail = eTail.substring( 0, 1 ) + "?<" + eName + ">" + eTail.substring( 1 );
theRegex = eHead + eTail;
eJokerMatcher = theJokerPattern.matcher( theRegex );
}
if ( theWildcardNames.size() != 0 ) {
_wildcardNames = theWildcardNames.toArray( new String[theWildcardNames.size()] );
}
// <-- Convert the wildcard names into regex pattern group names
_matchee = Pattern.compile( theRegex );
}
// /////////////////////////////////////////////////////////////////////////
// METHODS:
// /////////////////////////////////////////////////////////////////////////
@Override
public String[] getWildcardNames() {
return _wildcardNames;
}
@Override
public String getPathPattern() {
return _pathPattern;
}
@Override
public boolean isMatching( String aPath ) {
return _matchee.matcher( aPath ).matches();
}
@Override
public WildcardSubstitutes toWildcardSubstitutes( String aPath ) {
java.util.regex.Matcher theMatcher = _matchee.matcher( aPath );
if ( !theMatcher.matches() ) return null;
// Unnamed substitutes -->
List theWildcardSubstitutes = new ArrayList<>();
for ( int i = 0; i < theMatcher.groupCount(); i++ ) {
theWildcardSubstitutes.add( theMatcher.group( i + 1 ) );
}
String[] theWildcardReplacements = theWildcardSubstitutes.toArray( new String[theWildcardSubstitutes.size()] );
// <-- Unnamed substitutes
// Named substitutes -->
Map theNamedWildcardSubstitutes = null;
if ( _wildcardNames != null ) {
theNamedWildcardSubstitutes = new HashMap<>();
for ( String eName : _wildcardNames ) {
theNamedWildcardSubstitutes.put( eName, theMatcher.group( eName ) );
}
}
// <-- Named substitutes
return new WildcardSubstitutesImpl( theWildcardReplacements, theNamedWildcardSubstitutes );
}
@Override
public String[] toWildcardReplacements( String aPath ) {
java.util.regex.Matcher theMatcher = _matchee.matcher( aPath );
if ( !theMatcher.matches() ) return null;
List theWildcardSubstitutes = new ArrayList<>();
for ( int i = 0; i < theMatcher.groupCount(); i++ ) {
theWildcardSubstitutes.add( theMatcher.group( i + 1 ) );
}
return theWildcardSubstitutes.toArray( new String[theWildcardSubstitutes.size()] );
}
@Override
public String toWildcardReplacementAt( String aPath, int aIndex ) {
java.util.regex.Matcher theMatcher = _matchee.matcher( aPath );
if ( !theMatcher.matches() ) return null;
if ( aIndex < theMatcher.groupCount() ) return theMatcher.group( aIndex + 1 );
throw new IllegalArgumentException( "Your provided index <" + aIndex + "> exceeds the number if wildcards <" + theMatcher.groupCount() + "> defined in your pattern \"" + getPathPattern() + "\" for current path \"" + aPath + "\"." );
}
@Override
public String[] toWildcardReplacementsAt( String aPath, int... aIndexes ) {
java.util.regex.Matcher theMatcher = _matchee.matcher( aPath );
if ( !theMatcher.matches() ) return null;
if ( aIndexes == null || aIndexes.length == 0 ) return new String[] {};
List theWildcardSubstitutes = new ArrayList<>();
for ( int i : aIndexes ) {
if ( i >= theMatcher.groupCount() ) { throw new IllegalArgumentException( "Your provided index <" + i + "> exceeds the number of wildcards <" + theMatcher.groupCount() + "> defined in your pattern \"" + getPathPattern() + "\" for current path \"" + aPath + "\"." ); }
theWildcardSubstitutes.add( theMatcher.group( i + 1 ) );
}
return theWildcardSubstitutes.toArray( new String[theWildcardSubstitutes.size()] );
}
@Override
public String toWildcardReplacement( String aPath, String aWildcardName ) {
java.util.regex.Matcher theMatcher = _matchee.matcher( aPath );
if ( !theMatcher.matches() ) return null;
try {
return theMatcher.group( aWildcardName );
}
catch ( IllegalArgumentException e ) {
throw new IllegalArgumentException( "Your provided name <" + aWildcardName + "> is not defined in your pattern \"" + getPathPattern() + "\" for current path \"" + aPath + "\".", e );
}
}
@Override
public String[] toWildcardReplacements( String aPath, String... aWildcardNames ) {
java.util.regex.Matcher theMatcher = _matchee.matcher( aPath );
if ( !theMatcher.matches() ) return null;
if ( aWildcardNames == null || aWildcardNames.length == 0 ) return new String[] {};
List theWildcardSubstitutes = new ArrayList<>();
for ( String eWildcardName : aWildcardNames ) {
try {
theWildcardSubstitutes.add( theMatcher.group( eWildcardName ) );
}
catch ( IllegalArgumentException e ) {
throw new IllegalArgumentException( "Your provided name <" + eWildcardName + "> is not defined in your pattern \"" + getPathPattern() + "\" for current path \"" + aPath + "\".", e );
}
}
return theWildcardSubstitutes.toArray( new String[theWildcardSubstitutes.size()] );
}
/**
* For debugging purposes, retrieve the regex pattern created from the ANT
* path pattern.
*
* @return Returns the regex created from the ANT path pattern.
*/
public String toPattern() {
return _matchee.pattern();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((_matchee == null) ? 0 : _matchee.hashCode());
return result;
}
@Override
public boolean equals( Object obj ) {
if ( this == obj ) return true;
if ( obj == null ) return false;
if ( getClass() != obj.getClass() ) return false;
PathMatcherImpl other = (PathMatcherImpl) obj;
if ( _matchee == null ) {
if ( other._matchee != null ) return false;
}
else if ( !_matchee.equals( other._matchee ) ) return false;
return true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy