Skip to content

Instantly share code, notes, and snippets.

@panchenko
Created January 8, 2013 06:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save panchenko/4481770 to your computer and use it in GitHub Desktop.
Save panchenko/4481770 to your computer and use it in GitHub Desktop.
public class SequencePattern<T> {
public static final int ONE = 0;
public static final int ONE_OR_MORE = 1;
private static class PredicateRepetitiion {
final int repetitiion;
final Predicate<Object> predicate;
@SuppressWarnings("unchecked")
public PredicateRepetitiion(int repetitiion, Predicate<?> predicate) {
this.repetitiion = repetitiion;
this.predicate = (Predicate<Object>) predicate;
}
}
private final List<PredicateRepetitiion> predicates;
@Internal
SequencePattern(List<PredicateRepetitiion> predicates) {
this.predicates = ImmutableList.copyOf(predicates);
}
public static class Builder<T> {
@Internal
Builder() {
}
private final List<PredicateRepetitiion> predicates = Lists.newArrayList();
@SuppressWarnings("unchecked")
private <N> Builder<N> withNarrowedType() {
return (Builder<N>) this;
}
public Builder<?> match(Predicate<?> predicate) {
return match(ONE, predicate);
}
public Builder<?> match(int repetition, Predicate<?> predicate) {
predicates.add(new PredicateRepetitiion(repetition, predicate));
return this;
}
public <N> Builder<N> match(Class<N> clazz) {
return match(ONE, clazz);
}
public <N> Builder<N> match(int repetition, Class<N> clazz) {
predicates.add(new PredicateRepetitiion(repetition, instanceOf(clazz)));
return withNarrowedType();
}
public <N> Builder<N> match(Class<N> clazz, Predicate<N> predicate) {
return match(ONE, clazz, predicate);
}
public <N> Builder<N> match(int repetition, Class<N> clazz, Predicate<N> predicate) {
predicates.add(new PredicateRepetitiion(repetition, Predicates.and(instanceOf(clazz), predicate)));
return withNarrowedType();
}
public SequencePattern<T> build() {
return new SequencePattern<T>(predicates);
}
}
@SuppressWarnings("unchecked")
public T match(Iterable<?> items) {
Object last = null;
boolean hasLast = false;
final Iterator<?> iterator = items.iterator();
for (PredicateRepetitiion predicate : predicates) {
if (!hasLast) {
if (!iterator.hasNext()) {
return null;
}
last = iterator.next();
hasLast = true;
}
if (!predicate.predicate.apply(last)) {
return null;
}
if (predicate.repetitiion == ONE_OR_MORE) {
while (iterator.hasNext()) {
last = iterator.next();
if (!predicate.predicate.apply(last)) {
break;
}
}
} else {
hasLast = false;
}
}
return (T) last;
}
public static Builder<?> builder() {
return new Builder<Object>();
}
public static void main(String[] args) {
final SequencePattern<String> pattern = builder()
.match(Number.class)
.match(ONE_OR_MORE, not(instanceOf(String.class)))
.match(String.class, new Predicate<String>() {
@Override
public boolean apply(String input) {
return input.length() == 1;
}
})
.build();
System.out.println(pattern.match(Collections.emptyList()));
System.out.println(pattern.match(Arrays.asList(1)));
System.out.println(pattern.match(Arrays.asList("Y")));
System.out.println(pattern.match(Arrays.<Object> asList(1, "1")));
System.out.println(pattern.match(Arrays.<Object> asList(1, true, "Y")));
System.out.println(pattern.match(Arrays.<Object> asList(1, true, "NO")));
System.out.println(pattern.match(Arrays.<Object> asList(1, true, false, "Y")));
System.out.println(pattern.match(Arrays.<Object> asList(1, true, false, "NO")));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment