Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.nosqlbench.virtdata.api.bindings.VirtDataConversions Maven / Gradle / Ivy
Go to download
A Shaded CQL ActivityType driver for http://nosqlbench.io/
package io.nosqlbench.virtdata.api.bindings;
import io.nosqlbench.nb.api.errors.BasicError;
import java.lang.reflect.*;
import java.security.InvalidParameterException;
import java.util.*;
import java.util.List;
import java.util.function.*;
public class VirtDataConversions {
private enum FuncType {
LongToDoubleFunction(java.util.function.LongToDoubleFunction.class, long.class, double.class),
LongToIntFunction(java.util.function.LongToIntFunction.class, long.class, int.class),
LongFunction(LongFunction.class, long.class, Object.class),
LongUnaryOperator(java.util.function.LongUnaryOperator.class, long.class, long.class),
IntFunction(java.util.function.IntFunction.class, int.class, Object.class),
IntUnaryOperator(java.util.function.IntUnaryOperator.class, int.class, int.class),
DoubleFunction(java.util.function.DoubleFunction.class, double.class, Object.class),
DoubleUnaryOperator(java.util.function.DoubleUnaryOperator.class, double.class, double.class),
DoubleToLongFunction(java.util.function.DoubleToLongFunction.class, double.class, long.class),
Function(java.util.function.Function.class, Object.class, Object.class);
private final Class> functionClazz;
private final Class> inputClazz;
private final Class> outputClazz;
FuncType(Class> functionClazz, Class> inputClazz, Class> outputClazz) {
this.functionClazz = functionClazz;
this.inputClazz = inputClazz;
this.outputClazz = outputClazz;
}
public static FuncType valueOf(Class> clazz) {
for (FuncType value : FuncType.values()) {
if (value.functionClazz.isAssignableFrom(clazz)) {
return value;
}
}
throw new InvalidParameterException("No func type was found for " + clazz.getCanonicalName());
}
}
public static List adaptFunctionList(F[] funcs, Class functionType, Class... resultSignature) {
List functions = new ArrayList<>();
for (Object func : funcs) {
T adapted = adaptFunction(func, functionType, resultSignature);
functions.add(adapted);
}
return functions;
}
/**
* Adapt a functional object into a different type of functional object.
*
* @param func The original function object.
* @param functionType The type of the function you need
* @param The generic type of function being converted from
* @param The generic type of function being converted to
* @param resultSignature The signature of all output types, linearized for use after type-erasure.
* @return An instance of T
*/
public static T adaptFunction(F func, Class functionType, Class>... resultSignature) {
FuncType funcType = FuncType.valueOf(func.getClass());
List> signature = new ArrayList<>();
List> fromSignature = linearizeObjectSignature(func);
List> resultTypes = new ArrayList<>();
resultTypes.add(functionType);
for (Class> aClass : resultSignature) {
resultTypes.add(aClass);
}
List> toSignature = linearizeSignature(resultTypes);
signature.addAll(fromSignature);
signature.addAll(toSignature);
if (fromSignature.equals(toSignature)) {
return (T) func;
}
if (isAssignableFromTo(fromSignature, toSignature)) {
return (T) func;
}
Class>[] methodSignature = signature.toArray(new Class>[0]);
Method adapter = null;
Class> hostclass = AdaptFunctionsFlexibly.class;
try {
adapter = AdaptFunctionsFlexibly.class.getMethod("adapt", methodSignature);
} catch (NoSuchMethodException e) {
StringBuilder example = new StringBuilder();
example.append(" // Ignore the place holders, but ensure the return type is accurate\n");
String toTypeSyntax = canonicalSyntaxFor(toSignature);
example.append(" public static ").append(toTypeSyntax);
example.append(" adapt(");
String fromTypeSyntax = canonicalSyntaxFor(fromSignature);
example.append(fromTypeSyntax).append(" f");
int idx = 1;
for (int i = 1; i < signature.size(); i++) {
Class> sigpart = signature.get(i);
example.append(", ").append(sigpart.getSimpleName()).append(" i").append(idx++);
}
example.append(") {\n }\n");
String forInstance = example.toString();
throw new BasicError("adapter method is not implemented on class " + hostclass.getCanonicalName() + ":\n" + forInstance);
}
FuncType fromType = FuncType.valueOf(func.getClass());
if (fromType.functionClazz.getTypeParameters().length > 0) {
TypeVariable extends Class>>[] funcParms = func.getClass().getTypeParameters();
}
Object[] args = new Object[signature.size()];
args[0] = func;
for (int i = 1; i < args.length; i++) {
args[i] = null;
}
T result = null;
try {
result = (T) adapter.invoke(null, args);
return result;
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
/**
* Slice the incoming object list into a set of functions, based on a grouping interval and an offset.
* @param mod The grouping interval, or modulo to slice the function groups into
* @param offset The offset within the group for the provided function
* @param funcs A list of source objects to convert to functions.
* @return
*/
public static List getFunctions(int mod, int offset, Class extends T> functionType, Object... funcs) {
// if ((funcs.length%mod)!=0) {
// throw new RuntimeException("uneven division of functions, where multiples of " + mod + " are expected.");
// }
List functions = new ArrayList<>();
for (int i = offset; i < funcs.length; i+=mod) {
Object func = funcs[i];
T longFunction = VirtDataConversions.adaptFunction(func, functionType, Object.class);
functions.add(longFunction);
}
return functions;
}
private static boolean isAssignableFromTo(List> fromSignature, List> toSignature) {
if (fromSignature.size() != toSignature.size()) {
return false;
}
for (int i = 0; i < fromSignature.size(); i++) {
Class> aClass0 = fromSignature.get(i);
Class> aClass1 = toSignature.get(i);
if (!aClass1.isAssignableFrom(aClass0)) {
return false;
}
}
return true;
}
/**
* This constructs a type-erasure compatible signature of a tuple of types based on the caller's specified types.
* More specifically, it takes a type A and a type B and reifies their syntactical types as a list of runtime
* classes.
*
* For example, {@code LongFunction, Function} would be converted to {@code
* LongFunction.class, Integer.class, Function.class, Integer.class, String.class}
*
* The types must be provided by the caller.
*
* The purpose of this is to create an unambiguous signature to allow explicit method lookup which is the only
* pair-wise association of the two provided types within some namespace.
*
* This only works for types recognized by FuncType, as imposing this type system exposes the generic parameters
* that are useful for adapting functions.
*
* @return An array of classes
*/
private static List> linearizeSignature(Class>... types) {
List> reified = new ArrayList<>();
LinkedList> provided = new LinkedList<>(Arrays.asList(types));
while (provided.size() > 0) {
Class> mainType = provided.removeFirst();
FuncType funcType = FuncType.valueOf(mainType);
reified.add(funcType.functionClazz);
for (TypeVariable extends Class>> typeParameter : funcType.functionClazz.getTypeParameters()) {
if (provided.size() == 0) {
throw new RuntimeException("ran out of type parameters while qualifying generic parameter " + typeParameter.getName() + " for " + funcType.functionClazz);
}
Class> paramType = provided.remove();
if (paramType.isPrimitive()) {
throw new RuntimeException("You must provide non primitive types for parameter positions here, not " + paramType.getCanonicalName());
}
reified.add(paramType);
}
}
return reified;
}
private static List> linearizeSignature(List> types) {
return linearizeSignature(types.toArray(new Class>[0]));
}
/**
* Create a linearized list of classes to represent the provided instance.
*
* @param f An object which is represnted in the FuncTypes enum
* @return A list of classes that uniquely describe the functional type signature of f, with generic parameters made
* explicit.
*/
private static List> linearizeObjectSignature(Object f) {
LinkedList> linearized = new LinkedList<>();
FuncType type = FuncType.valueOf(f.getClass());
Class> functionClazz = type.functionClazz;
linearized.add(functionClazz);
TypeVariable extends Class>>[] typeParameters = functionClazz.getTypeParameters();
Method applyMethod = findApplyMethod(functionClazz);
switch (typeParameters.length) {
case 2:
linearized.add(applyMethod.getParameterTypes()[0]);
case 1:
linearized.add(applyMethod.getReturnType());
}
if (linearized.size() > 0 && linearized.peekLast().equals(Object.class)) {
Object out = null;
try {
Class> input = applyMethod.getParameterTypes()[0];
switch (input.getSimpleName()) {
case "int":
case "Integer":
out = applyMethod.invoke(f, 1);
break;
case "long":
case "Long":
out = applyMethod.invoke(f, 1L);
break;
case "double":
case "Double":
out = applyMethod.invoke(f, 1d);
break;
default:
out = Object.class;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
linearized.removeLast();
linearized.addLast(out.getClass());
}
return linearized;
}
private static String canonicalSyntaxFor(List> elements) {
return canonicalSyntaxFor(elements.toArray(new Class>[0]));
}
private static String canonicalSyntaxFor(Class>... elements) {
StringBuilder sb = new StringBuilder();
sb.append(elements[0].getSimpleName());
if (elements.length > 1) {
sb.append("<");
for (int i = 1; i < elements.length; i++) {
sb.append(elements[i].getSimpleName()).append(",");
}
sb.setLength(sb.length() - 1);
sb.append(">");
}
return sb.toString();
}
private static Method findApplyMethod(Class> c) {
Optional applyMethods = Arrays.stream(c.getMethods())
.filter(m -> {
boolean isNotDefault = !m.isDefault();
boolean isNotBridge = !m.isBridge();
boolean isNotSynthetic = !m.isSynthetic();
boolean isPublic = (m.getModifiers() & Modifier.PUBLIC) > 0;
boolean isNotString = !m.getName().equals("toString");
boolean isApplyMethod = m.getName().startsWith("apply");
boolean isFunctional = isNotDefault && isNotBridge && isNotSynthetic && isPublic && isNotString && isApplyMethod;
return isFunctional;
})
.distinct()
.findFirst();
return applyMethods.orElseThrow(() -> new RuntimeException("Unable to find apply method on " + c.getCanonicalName()));
}
private static Method findMethod(Class> hostclass, Class> fromClass, Class> toClass, Class>... generics) {
Class>[] argTypes = new Class[generics.length + 2];
argTypes[0] = fromClass;
argTypes[1] = toClass;
for (int i = 0; i < generics.length; i++) {
argTypes[i + 2] = generics[i];
}
try {
return hostclass.getMethod("adapt", argTypes);
} catch (NoSuchMethodException e) {
StringBuilder example = new StringBuilder();
StringBuilder genericsBuffer = new StringBuilder();
TypeVariable extends Class>>[] typeParameters = toClass.getTypeParameters();
if (typeParameters.length > 0) {
genericsBuffer.append("<");
for (int i = 0; i < typeParameters.length; i++) {
if (generics.length < typeParameters.length) {
throw new RuntimeException("You must provide " + typeParameters.length + " generic parameter types for " + toClass.getCanonicalName());
}
// if (generics[i].isPrimitive()) {
// throw new RuntimeException("You must declare non-primitive types in generic parameter placeholders, not " + generics[i].getSimpleName());
// }
genericsBuffer.append(generics[i].getSimpleName());
genericsBuffer.append(",");
}
genericsBuffer.setLength(genericsBuffer.length() - 1);
genericsBuffer.append(">");
}
String genericSignature = genericsBuffer.toString();
example.append(" // Ignore the place holders, but ensure the return type is accurate\n");
example.append(" public static ").append(toClass.getSimpleName());
example.append(genericSignature);
example.append(" adapt(");
example.append(fromClass.getSimpleName()).append(" f, ");
example.append(toClass.getSimpleName()).append(genericSignature).append(" ignore0");
int idx = 1;
for (Class> generic : generics) {
example.append(", ").append(generic.getSimpleName()).append(" ignore").append(+idx);
}
example.append(") {\n }\n");
String forInstance = example.toString();
throw new BasicError("adapter method is not implemented on class " + hostclass.getCanonicalName() + ":\n" + forInstance);
}
}
// private static void assertOutputAssignable(Object result, Class> clazz) {
// if (!ClassUtils.isAssignable(result.getClass(), clazz, true)) {
// throw new InvalidParameterException("Unable to assign type of " + result.getClass().getCanonicalName()
// + " to " + clazz.getCanonicalName());
// }
//
//// if (!clazz.isAssignableFrom(result.getClass())) {
//// throw new InvalidParameterException("Unable to assign type of " + result.getClass().getCanonicalName()
//// + " to " + clazz.getCanonicalName());
//// }
// }
//
/**
* Given a base object and a wanted type to convert it to, assert that the type of the base object is assignable to
* the wanted type. Further, if the wanted type is a generic type, assert that additional classes are assignable to
* the generic type parameters. Thus, if you want to assign to a generic type from a non-generic type, you must
* qualify the types of values that will be used in those generic parameter positions in declaration order.
*
* This is useful for taking any object and a known type and reifying it as the known type so that it can be
* then used idiomatically with normal type awareness. This scenario occurs when you are accepting an open type for
* flexiblity but then need to narrow the type sufficiently for additional conversion in a type-safe way.
*
* @param base The object to be assigned to the wanted type
* @param wantType The class type that the base object needs to be assignable to
* @param clazzes The types of values which will checked against generic type parameters of the wanted type
* @param Generic parameter T for the wanted type
* @return The original object casted to the wanted type after verification of parameter assignability
*/
private static T assertTypesAssignable(
Object base,
Class wantType,
Class>... clazzes) {
if (!wantType.isAssignableFrom(base.getClass())) {
throw new InvalidParameterException("Unable to assign " + wantType.getCanonicalName() + " from " +
base.getClass().getCanonicalName());
}
TypeVariable extends Class>>[] typeParameters = base.getClass().getTypeParameters();
if (typeParameters.length > 0) {
if (clazzes.length != typeParameters.length) {
throw new InvalidParameterException(
"type parameter lengths are mismatched:" + clazzes.length + ", " + typeParameters.length
);
}
for (int i = 0; i < clazzes.length; i++) {
Class> from = clazzes[i];
TypeVariable extends Class>> to = typeParameters[i];
boolean assignableFrom = to.getGenericDeclaration().isAssignableFrom(from);
if (!assignableFrom) {
throw new InvalidParameterException("Can not assign " + from.getCanonicalName() + " to " + to.getGenericDeclaration().getCanonicalName());
}
}
}
return (T) (base);
}
//
// /**
// * Throw an error indicating a narrowing conversion was attempted for strict conversion.
// * @param func The source function to convert from
// * @param targetClass The target class which was requested
// */
// private static void throwNarrowingError(Object func, Class> targetClass) {
// throw new BasicError("Converting from " + func.getClass().getCanonicalName() + " to " + targetClass.getCanonicalName() +
// " is not allowed when strict conversion is requested.");
// }
}