+ public static final <T extends Comparable<T>> Match lessThanOrEqual(final T value) {
+ return new MatchLessThanOrEqual<>(value);
+ }
+
+ public static final Match stringMatches(final Pattern pattern) {
+ return new MatchStringMatches(pattern);
+ }
+
+ public static final Match stringStartsWith(final String str) {
+ return new MatchStringStartsWith(str);
+ }
+
+ public static final Match stringEndsWith(final String str) {
+ return new MatchStringEndsWith(str);
+ }
+
+ public static final Match stringContains(final String str) {
+ return new MatchStringContains(str);
+ }
+
+ public static final <V> Match valueEquals(final V value) {
+ return new MatchValueEquals<>(value);
+ }
+
+ /**
+ * Return a {@link Match} which tests the opposite of this match.
+ *
+ * @return Negated match.
+ */
+ public Match negate() {
+ return new MatchNot(this);
+ }
+
+ public Match and(final Match other) {
+ return new MatchAll(ImmutableList.of(this, other));
+ }
+
+ public Match or(final Match other) {
+ return new MatchAny(ImmutableList.of(this, other));
+ }
+
+ public abstract boolean test(@Nullable NormalizedNode<?, ?> data);
+
+ final void appendTo(final StringBuilder sb) {
+ sb.append(op()).append('(');
+ appendArgument(sb);
+ sb.append(')');
+ }
+
+ void appendArgument(final StringBuilder sb) {
+ // No-op by default