Skip to content

Instantly share code, notes, and snippets.

@Pyknic
Created October 3, 2015 05:46
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 Pyknic/247a50f9d8a35e684aa6 to your computer and use it in GitHub Desktop.
Save Pyknic/247a50f9d8a35e684aa6 to your computer and use it in GitHub Desktop.
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