README
The
REFCODES.ORG
codes represent a group of artifacts consolidating parts of my work in the past years. Several topics are covered which I consider useful for you, programmers, developers and software engineers.
What is this repository for?
This artifact allows the construction of matchers for building arbitrary complex matching functionality. It is used to test whether matchee instances match certain criteria. Matcher
instances may get nested in a hierarchy (using e.g. the OrMatcher
, the AndMatcher
or the NotMatcher
types), having different matchers in combination will do custom matching. Some examples for Matcher
implementations are the EqualWithMatcher
, the PathMatcher
,the LessThanMatcher
or the RegExpMatcher
. Use the MatcherSugar
syntactic sugar mixin for expressively building your matchers.
How do I get set up?
To get up and running, include the following dependency (without the three dots “…”) in your pom.xml
:
1
2
3
4
5
6
7
8
9
<dependencies>
...
<dependency>
<artifactId>refcodes-matcher</artifactId>
<groupId>org.refcodes</groupId>
<version>3.3.8</version>
</dependency>
...
</dependencies>
The artifact is hosted directly at Maven Central. Jump straight to the source codes at Bitbucket. Read the artifact’s javadoc at javadoc.io.
Snippets of interest
Below find some code snippets which demonstrate the various aspects of using the refcodes-matcher
artifact (and , if applicable, its offsprings). See also the example source codes of this artifact for further information on the usage of this artifact.
Syntactic sugar
The below snippets make use of the MatcherSugar
class which’s methods are imported statically:
1
2
3
...
import static org.refcodes.matcher.MatcherSugar.*;
...
Match x₁ ≤ x ≤ x₂
The code snippet below test whether a number x
is between the range x₁ ≤ x ≤ x₂
with x₁
= -10
(included) and x₂
= 10
(included):
1
2
3
4
5
6
...
Matcher<Integer> theMatcher = and( greaterOrEqualThan( -10 ), lessOrEqualThan( 10 ) ); // "-10 ≤ x ≤ 10
for ( int i = -12; i <= 12; i++ ) {
System.out.println( "-10 ≤ " + i + " ≤ 10 --> " + theMatcher.isMatching( i ) );
}
...
Note that we combine a GreaterOrEqualThanMatcher
instance and a LessOrEqualThanMatcher
instance within a AndMatcher
instance (further nesting is possible, only limited by your ideas).
Match x₁ < x < x₂
The code snippet below test whether a number x
is between (excluding) the range x₁ ≤ x ≤ x₂
with x₁
= -10
(excluded) and x₂
= 10
(excluded):
1
2
3
4
5
6
...
Matcher<Integer> theMatcher = and( greaterThan( -10 ), lessThan( 10 ) ); // -10 < x < 10
for ( int i = -12; i <= 12; i++ ) {
System.out.println( "-10 ≤ " + i + " ≤ 10 --> " + theMatcher.isMatching( i ) );
}
...
Note that we combine a GreaterOrEqualThanMatcher
instance and a LessThanMatcher
instance within a AndMatcher
instance (further nesting is possible, only limited by your ideas).
Match x ≤ x₁ or x ≥ x₂
The code snippet below test whether a number x
is outside the range x₁ ≤ x ≤ x₂
with x₁
= -10
(included) and x₂
= 10
(included):
1
2
3
4
5
6
...
Matcher<Integer> theMatcher = or( lessOrEqualThan( -10 ), greaterOrEqualThan( 10 ) ); // -10 ≰ x ≰ 10
for ( int i = -12; i <= 12; i++ ) {
System.out.println( "-10 ≤ " + i + " ≤ 10 --> " + theMatcher.isMatching( i ) );
}
...
Note that we combine a GreaterOrEqualThanMatcher
instance and a LessOrEqualThanMatcher
instance within a OrMatcher
instance (further nesting is possible, only limited by your ideas).
Match x < x₁ or x > x₂
The code snippet below test whether a number x
is outside the range x₁ < x < x₂
with x₁
= -10
(excluded) and x₂
= 10
(excluded):
1
2
3
4
5
6
...
Matcher<Integer> theMatcher = or( lessThan( -10 ), greaterThan( 10 ) ); // -10 ≮ x ≮ 10
for ( int i = -12; i <= 12; i++ ) {
System.out.println( "-10 ≤ " + i + " ≤ 10 --> " + theMatcher.isMatching( i ) );
}
...
Note that we combine a GreaterThanMatcher
instance and a LessThanMatcher
instance within a OrMatcher
instance (further nesting is possible, only limited by your ideas).
Match a path with *
and **
The code snippet below test whether path matches the pattern “/*/acme/**
” where *
is a wildcard for one path element and **
is a wildcard for multiple path elements:
1
2
3
4
5
6
7
8
9
...
Matcher<String> theMatcher = new PathMatcher( "/*/acme/**" );
String thePath = "/foo/acme/atari/bar";
System.out.println( "\"" + thePath + "\" -?-> \"/*/acme/**\" --> " + theMatcher.isMatching( thePath ) );
thePath = "/bar/acme/commodore/bar";
System.out.println( "\"" + thePath + "\" -?-> \"/*/acme/**\" --> " + theMatcher.isMatching( thePath ) );
thePath = "/foo/evil/bad/bar";
System.out.println( "\"" + thePath + "\" -?-> \"/*/acme/**\" --> " + theMatcher.isMatching( thePath ) );
...
Note that we directly use a PathMatcher
instance (further nesting is possible, only limited by your ideas).
Get path variables with ${...}
The code snippet below matches the pattern “/acme/**/${tail}
” against a path where ${tail}
is a path variable which we want to determine:
1
2
3
4
5
6
7
8
9
10
11
12
13
PathMatcher theMatcher = new PathMatcher( "/acme/**/${tail}" );
String thePath = "/acme/foo/atari";
String theVar = theMatcher.toWildcardReplacement( thePath, "tail" );
System.out.println( "\"" + thePath + "\" -?-> \"/acme/**/${tail}\" --> " + theVar );
thePath = "/acme/foo/commodore";
theVar = theMatcher.toWildcardReplacement( thePath, "tail" );
System.out.println( "\"" + thePath + "\" -?-> \"/acme/**/${tail}\" --> " + theVar );
thePath = "/acme/foo/what/ever/path/sinclair";
theVar = theMatcher.toWildcardReplacement( thePath, "tail" );
System.out.println( "\"" + thePath + "\" -?-> \"/acme/**/${tail}\" --> " + theVar );
thePath = "/foo/what/ever/path/ghost";
theVar = theMatcher.toWildcardReplacement( thePath, "tail" );
System.out.println( "\"" + thePath + "\" -?-> \"/acme/**/${tail}\" --> " + theVar );
Note that the path variable ${tail}
used here can be of any name (such as ${head}
, ${var}
, ${...}
) and you may use multiple path variables and the path variables can be placed anywhere in the path pattern as path element.
Matcher schema
To introspect your event matcher syntax, the Matcher
type
provides means to generate a MatcherSchema
object, recursively including all the tree node’s MatcherSchema
objects. The MatcherSchema
gives insights on the construction and the current state of all the nodes building up your matcher syntax. Creating a MatcherSchema
is a helpful tool to analyze more complex command line syntax constructions:
1
2
3
4
...
Matcher<String> theSportsMatcher = or( equalWith( "Soccer" ), equalWith( "Football" ) );
System.out.println( theSportsMatcher.toSchema() );
...
The above snippet defines a syntax for anything published for channels Soccer
or Football
(line 1) and prints out the according MatcherSchema
(line 2). The result of the printable version of the MatcherSchema
then looks as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
OrMatcher: {
ALIAS: "OR",
DESCRIPTION: "At least one nested matcher must match (OR).",
TYPE: "org.refcodes.matcher.OrMatcher",
EqualWithMatcher: {
ALIAS: "EQUAL_WITH",
DESCRIPTION: "Compares the matchees for equality (EQUAL WITH).",
TYPE: "org.refcodes.matcher.EqualWithMatcher",
VALUE: "Soccer"
},
EqualWithMatcher: {
ALIAS: "EQUAL_WITH",
DESCRIPTION: "Compares the matchees for equality (EQUAL WITH).",
TYPE: "org.refcodes.matcher.EqualWithMatcher",
VALUE: "Football"
}
}
As you can see, the text output format uses a
JSON
alike notation for easy further processing.
Examples
See the example source codes of this artifact for further information on the usage of this artifact.
Contribution guidelines
- Report issues
- Finding bugs
- Helping fixing bugs
- Making code and documentation better
- Enhance the code
Who do I talk to?
- Siegfried Steiner (steiner@refcodes.org)
Terms and conditions
The REFCODES.ORG
group of artifacts is published under some open source licenses; covered by the refcodes-licensing
(org.refcodes
group) artifact - evident in each artifact in question as of the pom.xml
dependency included in such artifact.