/** * 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()); } }; } }