/** * Instantiate an optional data mapping function if possible. * * @param flowSpec The VirtData specifier for the mapping function * @param <T> The parameterized return type of the function * @return An optional function which will be empty if the function could not be resolved. */ public static <T> Optional<DataMapper<T>> getOptionalMapper(String flowSpec) { flowSpec = CompatibilityFixups.fixup(flowSpec); VirtDataDSL.ParseResult parseResult = VirtDataDSL.parse(flowSpec); if (parseResult.throwable != null) { throw new RuntimeException(parseResult.throwable); } VirtDataFlow flow = parseResult.flow; VirtDataComposer composer = new VirtDataComposer(); Optional<ResolvedFunction> resolvedFunction = composer.resolveFunctionFlow(flow); return resolvedFunction.map(ResolvedFunction::getFunctionObject).map(DataMapperFunctionMapper::map); }
/** * If there are direct type matches between the inner func and the outer func, then remove all * other outer funcs except the ones with direct matches. * * @param prevFuncs The list of candidate inner functions * @param nextFuncs The list of candidate outer functions * @return count of items removed */ private int reduceByDirectTypes(List<ResolvedFunction> prevFuncs, List<ResolvedFunction> nextFuncs) { int progressed = 0; // Rule 1: If there are direct type matches, remove extraneous next funcs Set<Class<?>> outputs = getOutputs(prevFuncs); Set<Class<?>> inputs = getInputs(nextFuncs); Set<Class<?>> directMatches = inputs.stream().filter(outputs::contains).collect(Collectors.toCollection(HashSet::new)); if (directMatches.size() > 0) { List<ResolvedFunction> toremove = new ArrayList<>(); for (ResolvedFunction nextFunc : nextFuncs) { if (!directMatches.contains(nextFunc.getArgType())) { String logmsg = "BY-DIRECT-TYPE removing next func: " + nextFunc + " because its input types are not satisfied by any previous func"; logger.trace(logmsg); toremove.add(nextFunc); progressed++; } } nextFuncs.removeAll(toremove); } return progressed; }
pass++; progress = 0; progress += reduceByRequiredResultsType(funcs.get(funcs.size() - 1), type); if (funcs.size() > 1) { int stage = 0; if (prevFuncs != null && nextFuncs != null) { if (progress == 0) { progress += reduceByDirectTypes(prevFuncs, nextFuncs); if (progress == 0) { progress += reduceByAssignableTypes(prevFuncs, nextFuncs, false); if (progress == 0) { progress += reduceByAssignableTypes(prevFuncs, nextFuncs, true); if (progress == 0) { progress += reduceByPreferredTypes(prevFuncs, nextFuncs); progress += reduceByPreferredResultTypes(funcs.get(0));
Class<?> outputType = ValueType.classOfType(call.getOutputType()); Object[] args = call.getArguments(); args = populateFunctions(args); summarizeBulk(funcs)); removeNonLongFunctions(funcs.getFirst()); List<ResolvedFunction> flattenedFuncs = optimizePath(funcs, ValueType.classOfType(flow.getLastExpression().getCall().getOutputType())); logger.trace("composed summary: " + summarize(flattenedFuncs)); logger.trace("FUNCTION chain selected: (multi) '" + this.summarize(flattenedFuncs) + "'"); for (ResolvedFunction resolvedFunction : flattenedFuncs) { try {
private Object[] populateFunctions(Object[] args) { for (int i = 0; i < args.length; i++) { Object o = args[i]; if (o instanceof FunctionCall) { FunctionCall call = (FunctionCall) o; String funcName = call.getFunctionName(); Class<?> inputType = ValueType.classOfType(call.getInputType()); Class<?> outputType = ValueType.classOfType(call.getOutputType()); Object[] fargs = call.getArguments(); fargs = populateFunctions(fargs); List<ResolvedFunction> resolved = functionLibrary.resolveFunctions(outputType, inputType, funcName, fargs); if (resolved.size() == 0) { throw new RuntimeException("Unable to find even one function for " + call); } args[i] = resolved.get(0).getFunctionObject(); } } return args; }
VirtDataComposer composer = new VirtDataComposer(); Optional<ResolvedFunction> resolvedFunction = composer.resolveFunctionFlow(flow); Optional<DataMapper<T>> mapper = resolvedFunction.map(ResolvedFunction::getFunctionObject).map(DataMapperFunctionMapper::map); if (mapper.isPresent()) {
Set<Class<?>> outputs = getOutputs(prevFuncs); Set<Class<?>> inputs = getInputs(nextFuncs); Set<Class<?>> compatibleInputs = new HashSet<>();
VirtDataComposer composer = new VirtDataComposer(); Optional<ResolvedFunction> resolvedFunction = composer.resolveFunctionFlow(flow);