Created
October 3, 2015 05:46
-
-
Save Pyknic/247a50f9d8a35e684aa6 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
package com.pyknic.variant; | |
import com.speedment.codegen.lang.models.Generic; | |
import com.speedment.codegen.lang.models.Type; | |
import static com.speedment.codegen.lang.models.constants.DefaultType.DOUBLE_PRIMITIVE; | |
import static com.speedment.codegen.lang.models.constants.DefaultType.INT_PRIMITIVE; | |
import static com.speedment.codegen.lang.models.constants.DefaultType.LONG_PRIMITIVE; | |
import static com.speedment.codegen.lang.models.constants.DefaultType.OBJECT; | |
import java.util.Optional; | |
import java.util.OptionalDouble; | |
import java.util.OptionalInt; | |
import java.util.OptionalLong; | |
import java.util.function.BinaryOperator; | |
import java.util.function.Consumer; | |
import java.util.function.DoubleBinaryOperator; | |
import java.util.function.DoubleConsumer; | |
import java.util.function.DoubleFunction; | |
import java.util.function.DoublePredicate; | |
import java.util.function.DoubleSupplier; | |
import java.util.function.Function; | |
import java.util.function.IntBinaryOperator; | |
import java.util.function.IntConsumer; | |
import java.util.function.IntFunction; | |
import java.util.function.IntPredicate; | |
import java.util.function.IntSupplier; | |
import java.util.function.LongBinaryOperator; | |
import java.util.function.LongConsumer; | |
import java.util.function.LongFunction; | |
import java.util.function.LongPredicate; | |
import java.util.function.LongSupplier; | |
import java.util.function.Predicate; | |
import java.util.function.Supplier; | |
import java.util.function.ToDoubleFunction; | |
import java.util.function.ToIntFunction; | |
import java.util.function.ToLongFunction; | |
import java.util.stream.DoubleStream; | |
import java.util.stream.IntStream; | |
import java.util.stream.LongStream; | |
import java.util.stream.Stream; | |
/** | |
* | |
* @author Emil Forslund | |
*/ | |
public final class Variants { | |
public static boolean checkCompability(TwoVariants two) { | |
if (two.first == two.second) { | |
return true; | |
} else { | |
if (two.first.isPrimitive()) { | |
return !two.second.isPrimitive(); | |
} else return true; | |
} | |
} | |
public static Stream<Variant> all() { | |
return Stream.of(Variant.values()); | |
} | |
public static Stream<TwoVariants> allByAll() { | |
return all().flatMap(first -> all().map(second -> new TwoVariants(first, second))); | |
} | |
public enum Variant { | |
REFERENCE ("", OBJECT, Stream.class, Optional.class, Function.class, Function.class, Predicate.class, Supplier.class, Consumer.class, BinaryOperator.class), | |
LONG ("Long", LONG_PRIMITIVE, LongStream.class, OptionalLong.class, LongFunction.class, ToLongFunction.class, LongPredicate.class, LongSupplier.class, LongConsumer.class, LongBinaryOperator.class), | |
DOUBLE ("Double", DOUBLE_PRIMITIVE, DoubleStream.class, OptionalDouble.class, DoubleFunction.class, ToDoubleFunction.class, DoublePredicate.class, DoubleSupplier.class, DoubleConsumer.class, DoubleBinaryOperator.class), | |
INTEGER ("Int", INT_PRIMITIVE, IntStream.class, OptionalInt.class, IntFunction.class, ToIntFunction.class, IntPredicate.class, IntSupplier.class, IntConsumer.class, IntBinaryOperator.class); | |
private final String prefix; | |
private final Type type; | |
private final Class<?> | |
stream, | |
optional, | |
function, | |
functionTo, | |
predicate, | |
supplier, | |
consumer, | |
binaryOperator; | |
private Variant( | |
String prefix, | |
Type type, | |
Class<?> stream, | |
Class<?> optional, | |
Class<?> function, | |
Class<?> functionTo, | |
Class<?> predicate, | |
Class<?> supplier, | |
Class<?> consumer, | |
Class<?> binaryOperator) { | |
this.prefix = prefix; | |
this.type = type; | |
this.stream = stream; | |
this.optional = optional; | |
this.function = function; | |
this.functionTo = functionTo; | |
this.predicate = predicate; | |
this.supplier = supplier; | |
this.consumer = consumer; | |
this.binaryOperator = binaryOperator; | |
} | |
public String prefix() { | |
return prefix; | |
} | |
public String getPrefix() { | |
return prefix; | |
} | |
public Type getType() { | |
return type; | |
} | |
public Class<?> getStream() { | |
return stream; | |
} | |
public Type streamType(Type genericType) { | |
return decorate(stream, genericType); | |
} | |
public Class<?> getOptional() { | |
return optional; | |
} | |
public Type optionalType(Type genericType) { | |
return decorate(optional, genericType); | |
} | |
public Class<?> getFunction() { | |
return function; | |
} | |
public Type functionType(Type genericType) { | |
return decorate(function, genericType); | |
} | |
public Class<?> getFunctionTo() { | |
return functionTo; | |
} | |
public Type functionToType(Type genericType) { | |
return decorate(functionTo, genericType); | |
} | |
public Class<?> getPredicate() { | |
return predicate; | |
} | |
public Type predicateType(Type genericType) { | |
return decorate(predicate, genericType); | |
} | |
public Class<?> getSupplier() { | |
return supplier; | |
} | |
public Type supplierType(Type genericType) { | |
return decorate(supplier, genericType); | |
} | |
public Class<?> getConsumer() { | |
return consumer; | |
} | |
public Type consumerType(Type genericType) { | |
return decorate(consumer, genericType); | |
} | |
public Class<?> getBinaryOperator() { | |
return binaryOperator; | |
} | |
public Type binaryOperatorType(Type genericType) { | |
return decorate(binaryOperator, genericType); | |
} | |
public boolean isPrimitive() { | |
return this != REFERENCE; | |
} | |
private Type decorate(Class<?> clazz, Type upperBound) { | |
final Type result = Type.of(clazz); | |
if (this == REFERENCE) { | |
result.add(Generic.of().add(upperBound)); | |
} | |
return result; | |
} | |
} | |
public final static class TwoVariants { | |
private final Variant first, second; | |
private TwoVariants(Variant first, Variant second) { | |
this.first = first; | |
this.second = second; | |
} | |
public Variant first() { | |
return first; | |
} | |
public Variant second() { | |
return second; | |
} | |
public String getName(String separator, String suffix) { | |
return getName("", separator, suffix); | |
} | |
public String getName(String prefix, String separator, String suffix) { | |
final StringBuilder str = new StringBuilder(prefix); | |
str.append(first.getPrefix()); | |
if (second != Variant.REFERENCE) { | |
str.append(separator).append(second.getPrefix()); | |
} | |
return str.append(suffix).toString(); | |
} | |
public Stream<Generic> getGenerics(String firstName, String secondName) { | |
final Stream.Builder<Generic> builder = Stream.builder(); | |
if (first == Variant.REFERENCE) { | |
builder.add(Generic.of().setLowerBound(firstName)); | |
} | |
if (second == Variant.REFERENCE) { | |
builder.add(Generic.of().setLowerBound(secondName)); | |
} | |
return builder.build(); | |
} | |
public Type asFunction(Type firstGeneric, Type secondGeneric) { | |
switch (first) { | |
case REFERENCE : | |
switch (second) { | |
case REFERENCE : | |
return Type.of(Function.class) | |
.add(Generic.of().add(firstGeneric)) | |
.add(Generic.of().add(secondGeneric)); | |
case DOUBLE : | |
return Type.of(ToDoubleFunction.class) | |
.add(Generic.of().add(firstGeneric)); | |
case LONG : | |
return Type.of(ToLongFunction.class) | |
.add(Generic.of().add(firstGeneric)); | |
case INTEGER : | |
return Type.of(ToIntFunction.class) | |
.add(Generic.of().add(firstGeneric)); | |
} break; | |
case DOUBLE : | |
switch (second) { | |
case REFERENCE : | |
return Type.of(DoubleFunction.class) | |
.add(Generic.of().add(secondGeneric)); | |
case DOUBLE : | |
return Type.of(DoubleBinaryOperator.class); | |
} break; | |
case LONG : | |
switch (second) { | |
case REFERENCE : | |
return Type.of(LongFunction.class) | |
.add(Generic.of().add(secondGeneric)); | |
case LONG : | |
return Type.of(LongBinaryOperator.class); | |
} break; | |
case INTEGER : | |
switch (second) { | |
case REFERENCE : | |
return Type.of(IntFunction.class) | |
.add(Generic.of().add(secondGeneric)); | |
case INTEGER : | |
return Type.of(IntBinaryOperator.class); | |
} break; | |
} | |
throw new UnsupportedOperationException( | |
"The current combination of primitive types is not supported as a function." | |
); | |
} | |
} | |
private Variants() {throw new RuntimeException("Should not be instantiated.");} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment