/**
* Copyright (C) 2013-2016 The Rythm Engine project
* for LICENSE and other details see:
* https://github.com/rythmengine/rythmengine
*/
package org.rythmengine.utils;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Utility classes
*/
// Most of the code come from Play!Framework F.java, under Apache License 2.0
public class F {
private F() {
}
public static interface Action0 {
void invoke();
}
public static interface Action<T> {
void invoke(T result);
}
public static abstract class Option<T> implements Iterable<T> {
public abstract boolean isDefined();
public abstract T get();
public static <T> None<T> none() {
return (None<T>) (Object) None;
}
public static <T> Some<T> some(T value) {
return new Some<T>(value);
}
}
public static <A> Some<A> some(A a) {
return new Some(a);
}
public static class None<T> extends Option<T> {
@Override
public boolean isDefined() {
return false;
}
@Override
public T get() {
throw new IllegalStateException("No value");
}
public Iterator<T> iterator() {
return Collections.<T>emptyList().iterator();
}
@Override
public String toString() {
return "None";
}
}
public static final None<Object> None = new None<Object>();
public static class Some<T> extends Option<T> {
final T value;
public Some(T value) {
this.value = value;
}
@Override
public boolean isDefined() {
return true;
}
@Override
public T get() {
return value;
}
public Iterator<T> iterator() {
return Collections.singletonList(value).iterator();
}
@Override
public String toString() {
return "Some(" + value + ")";
}
}
public static class Either<A, B> {
final public Option<A> _1;
final public Option<B> _2;
private Either(Option<A> _1, Option<B> _2) {
this._1 = _1;
this._2 = _2;
}
public static <A, B> Either<A, B> _1(A value) {
return new Either(some(value), None);
}
public static <A, B> Either<A, B> _2(B value) {
return new Either(None, some(value));
}
@Override
public String toString() {
return "E2(_1: " + _1 + ", _2: " + _2 + ")";
}
}
public static class E2<A, B> extends Either<A, B> {
private E2(Option<A> _1, Option<B> _2) {
super(_1, _2);
}
}
public static class E3<A, B, C> {
final public Option<A> _1;
final public Option<B> _2;
final public Option<C> _3;
private E3(Option<A> _1, Option<B> _2, Option<C> _3) {
this._1 = _1;
this._2 = _2;
this._3 = _3;
}
public static <A, B, C> E3<A, B, C> _1(A value) {
return new E3(some(value), None, None);
}
public static <A, B, C> E3<A, B, C> _2(B value) {
return new E3(None, some(value), None);
}
public static <A, B, C> E3<A, B, C> _3(C value) {
return new E3(None, None, some(value));
}
@Override
public String toString() {
return "E3(_1: " + _1 + ", _2: " + _2 + ", _3:" + _3 + ")";
}
}
public static class E4<A, B, C, D> {
final public Option<A> _1;
final public Option<B> _2;
final public Option<C> _3;
final public Option<D> _4;
private E4(Option<A> _1, Option<B> _2, Option<C> _3, Option<D> _4) {
this._1 = _1;
this._2 = _2;
this._3 = _3;
this._4 = _4;
}
public static <A, B, C, D> E4<A, B, C, D> _1(A value) {
return new E4(Option.some(value), None, None, None);
}
public static <A, B, C, D> E4<A, B, C, D> _2(B value) {
return new E4(None, some(value), None, None);
}
public static <A, B, C, D> E4<A, B, C, D> _3(C value) {
return new E4(None, None, some(value), None);
}
public static <A, B, C, D> E4<A, B, C, D> _4(D value) {
return new E4(None, None, None, some(value));
}
@Override
public String toString() {
return "E4(_1: " + _1 + ", _2: " + _2 + ", _3:" + _3 + ", _4:" + _4 + ")";
}
}
public static class E5<A, B, C, D, E> {
final public Option<A> _1;
final public Option<B> _2;
final public Option<C> _3;
final public Option<D> _4;
final public Option<E> _5;
private E5(Option<A> _1, Option<B> _2, Option<C> _3, Option<D> _4, Option<E> _5) {
this._1 = _1;
this._2 = _2;
this._3 = _3;
this._4 = _4;
this._5 = _5;
}
public static <A, B, C, D, E> E5<A, B, C, D, E> _1(A value) {
return new E5(Option.some(value), None, None, None, None);
}
public static <A, B, C, D, E> E5<A, B, C, D, E> _2(B value) {
return new E5(None, Option.some(value), None, None, None);
}
public static <A, B, C, D, E> E5<A, B, C, D, E> _3(C value) {
return new E5(None, None, Option.some(value), None, None);
}
public static <A, B, C, D, E> E5<A, B, C, D, E> _4(D value) {
return new E5(None, None, None, Option.some(value), None);
}
public static <A, B, C, D, E> E5<A, B, C, D, E> _5(E value) {
return new E5(None, None, None, None, Option.some(value));
}
@Override
public String toString() {
return "E5(_1: " + _1 + ", _2: " + _2 + ", _3:" + _3 + ", _4:" + _4 + ", _5:" + _5 + ")";
}
}
private static boolean eq(Object a, Object b) {
if (a == b) return true;
if (null == a) return null == b;
return a.equals(b);
}
public static class Tuple<A, B> {
final public A _1;
final public B _2;
public Tuple(A _1, B _2) {
this._1 = _1;
this._2 = _2;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o instanceof Tuple) {
Tuple that = (Tuple) o;
return eq(that._1, _1) && eq(that._2, _2);
}
return false;
}
@Override
public int hashCode() {
int i = 17;
if (null != _1) i = i * 31 + _1.hashCode();
if (null != _2) i = i * 31 + _2.hashCode();
return i;
}
@Override
public String toString() {
return "T2(_1: " + _1 + ", _2: " + _2 + ")";
}
}
public static <A, B> Tuple<A, B> tuple(A a, B b) {
return new Tuple(a, b);
}
public static class T2<A, B> extends Tuple<A, B> {
public T2(A _1, B _2) {
super(_1, _2);
}
public Map<A, B> asMap() {
Map<A, B> m = new HashMap<A, B>();
m.put(_1, _2);
return m;
}
}
public static <A, B> T2<A, B> T2(A a, B b) {
return new T2(a, b);
}
public static class T3<A, B, C> {
final public A _1;
final public B _2;
final public C _3;
public T3(A _1, B _2, C _3) {
this._1 = _1;
this._2 = _2;
this._3 = _3;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o instanceof T3) {
T3 that = (T3) o;
return eq(that._1, _1) && eq(that._2, _2) && eq(that._3, _3);
}
return false;
}
@Override
public int hashCode() {
int i = 17;
if (null != _1) i = i * 31 + _1.hashCode();
if (null != _2) i = i * 31 + _2.hashCode();
if (null != _3) i = i * 31 + _3.hashCode();
return i;
}
@Override
public String toString() {
return "T3(_1: " + _1 + ", _2: " + _2 + ", _3:" + _3 + ")";
}
}
public static <A, B, C> T3<A, B, C> T3(A a, B b, C c) {
return new T3(a, b, c);
}
public static class T4<A, B, C, D> {
final public A _1;
final public B _2;
final public C _3;
final public D _4;
public T4(A _1, B _2, C _3, D _4) {
this._1 = _1;
this._2 = _2;
this._3 = _3;
this._4 = _4;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o instanceof T4) {
T4 that = (T4) o;
return eq(that._1, _1) && eq(that._2, _2) && eq(that._3, _3) && eq(that._4, _4);
}
return false;
}
@Override
public int hashCode() {
int i = 17;
if (null != _1) i = i * 31 + _1.hashCode();
if (null != _2) i = i * 31 + _2.hashCode();
if (null != _3) i = i * 31 + _3.hashCode();
if (null != _4) i = i * 31 + _4.hashCode();
return i;
}
@Override
public String toString() {
return "T4(_1: " + _1 + ", _2: " + _2 + ", _3:" + _3 + ", _4:" + _4 + ")";
}
}
public static <A, B, C, D> T4<A, B, C, D> T4(A a, B b, C c, D d) {
return new T4<A, B, C, D>(a, b, c, d);
}
public static class T5<A, B, C, D, E> {
final public A _1;
final public B _2;
final public C _3;
final public D _4;
final public E _5;
public T5(A _1, B _2, C _3, D _4, E _5) {
this._1 = _1;
this._2 = _2;
this._3 = _3;
this._4 = _4;
this._5 = _5;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o instanceof T5) {
T5 that = (T5) o;
return eq(that._1, _1) && eq(that._2, _2) && eq(that._3, _3) && eq(that._4, _4) && eq(that._5, _5);
}
return false;
}
@Override
public int hashCode() {
int i = 17;
if (null != _1) i = i * 31 + _1.hashCode();
if (null != _2) i = i * 31 + _2.hashCode();
if (null != _3) i = i * 31 + _3.hashCode();
if (null != _4) i = i * 31 + _4.hashCode();
if (null != _5) i = i * 31 + _5.hashCode();
return i;
}
@Override
public String toString() {
return "T5(_1: " + _1 + ", _2: " + _2 + ", _3:" + _3 + ", _4:" + _4 + ", _5:" + _5 + ")";
}
}
public static <A, B, C, D, E> T5<A, B, C, D, E> T5(A a, B b, C c, D d, E e) {
return new T5<A, B, C, D, E>(a, b, c, d, e);
}
public static abstract class Matcher<T, R> {
public abstract Option<R> match(T o);
public Option<R> match(Option<T> o) {
if (o.isDefined()) {
return match(o.get());
}
return Option.none();
}
public <NR> Matcher<T, NR> and(final Matcher<R, NR> nextMatcher) {
final Matcher<T, R> firstMatcher = this;
return new Matcher<T, NR>() {
@Override
public Option<NR> match(T o) {
for (R r : firstMatcher.match(o)) {
return nextMatcher.match(r);
}
return Option.none();
}
};
}
public static final Matcher<Object, String> String = new Matcher<Object, String>() {
@Override
public Option<String> match(Object o) {
if (o instanceof String) {
return Option.some((String) o);
}
return Option.none();
}
};
public static <K> Matcher<Object, K> classOf(final Class<K> clazz) {
return new Matcher<Object, K>() {
@Override
public Option<K> match(Object o) {
if (o instanceof Option && ((Option) o).isDefined()) {
o = ((Option) o).get();
}
if (clazz.isInstance(o)) {
return Option.some((K) o);
}
return Option.none();
}
};
}
public static Matcher<String, String> startsWith(final String prefix) {
return new Matcher<String, String>() {
@Override
public Option<String> match(String o) {
if (o.startsWith(prefix)) {
return Option.some(o);
}
return Option.none();
}
};
}
public static Matcher<String, String> re(final String pattern) {
return new Matcher<String, String>() {
@Override
public Option<String> match(String o) {
if (o.matches(pattern)) {
return Option.some(o);
}
return Option.none();
}
};
}
public static <X> Matcher<X, X> eq(final X other) {
return new Matcher<X, X>() {
@Override
public Option<X> match(X o) {
if (o.equals(other)) {
return Option.some(o);
}
return Option.none();
}
};
}
}
public static Range<Integer> R(final int minInclusive, final int maxExclusive) {
return new Range<Integer>(minInclusive, maxExclusive) {
@Override
protected Integer next(Integer element) {
return ++element;
}
@Override
public int size() {
return max() - min();
}
@Override
public boolean include(Integer element) {
return (min() <= element) && (element < max());
}
};
}
public static Range<Character> R(final char minInclusive, final char maxExclusive) {
return new Range<Character>(minInclusive, maxExclusive) {
@Override
protected Character next(Character element) {
return (char) (element + 1);
}
@Override
public int size() {
char min = min();
char max = max();
return (int) max - (int) min;
}
@Override
public boolean include(Character element) {
return (min() <= element) && (element < max());
}
};
}
}