Created
January 8, 2013 06:38
-
-
Save panchenko/4481770 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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