org.finos.legend.engine.plan.compilation.GeneratePureConfig Maven / Gradle / Ivy
// Copyright 2020 Goldman Sachs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.finos.legend.engine.plan.compilation;
import org.eclipse.collections.api.factory.Sets;
import org.eclipse.collections.api.tuple.Pair;
import org.finos.legend.engine.plan.dependencies.domain.dataQuality.BasicDefect;
import org.finos.legend.engine.plan.dependencies.domain.dataQuality.BasicRelativePathNode;
import org.finos.legend.engine.plan.dependencies.domain.dataQuality.Constrained;
import org.finos.legend.engine.plan.dependencies.domain.dataQuality.EnforcementLevel;
import org.finos.legend.engine.plan.dependencies.domain.dataQuality.GraphContext;
import org.finos.legend.engine.plan.dependencies.domain.dataQuality.IChecked;
import org.finos.legend.engine.plan.dependencies.domain.dataQuality.IDefect;
import org.finos.legend.engine.plan.dependencies.domain.dataQuality.RelativePathNode;
import org.finos.legend.engine.plan.dependencies.domain.dataQuality.RuleType;
import org.finos.legend.engine.plan.dependencies.domain.date.DayOfWeek;
import org.finos.legend.engine.plan.dependencies.domain.date.DurationUnit;
import org.finos.legend.engine.plan.dependencies.domain.date.Month;
import org.finos.legend.engine.plan.dependencies.domain.date.PureDate;
import org.finos.legend.engine.plan.dependencies.domain.date.Quarter;
import org.finos.legend.engine.plan.dependencies.domain.graphFetch.IGraphInstance;
import org.finos.legend.engine.plan.dependencies.store.inMemory.DataParsingException;
import org.finos.legend.engine.plan.dependencies.store.inMemory.IGraphFetchM2MExecutionNodeContext;
import org.finos.legend.engine.plan.dependencies.store.inMemory.IStoreStreamReader;
import org.finos.legend.engine.plan.dependencies.store.inMemory.IStoreStreamReadingExecutionNodeContext;
import org.finos.legend.engine.plan.dependencies.store.inMemory.graphFetch.IInMemoryCrossStoreGraphFetchExecutionNodeSpecifics;
import org.finos.legend.engine.plan.dependencies.store.inMemory.graphFetch.IInMemoryPropertyGraphFetchExecutionNodeSpecifics;
import org.finos.legend.engine.plan.dependencies.store.inMemory.graphFetch.IInMemoryRootGraphFetchExecutionNodeSpecifics;
import org.finos.legend.engine.plan.dependencies.store.inMemory.graphFetch.IInMemoryRootGraphFetchMergeExecutionNodeSpecifics;
import org.finos.legend.engine.plan.dependencies.store.inMemory.graphFetch.IStoreStreamReadingExecutionNodeSpecifics;
import org.finos.legend.engine.plan.dependencies.store.platform.IGraphSerializer;
import org.finos.legend.engine.plan.dependencies.store.platform.IPlatformPureExpressionExecutionNodeGraphFetchMergeSpecifics;
import org.finos.legend.engine.plan.dependencies.store.platform.IPlatformPureExpressionExecutionNodeGraphFetchUnionSpecifics;
import org.finos.legend.engine.plan.dependencies.store.platform.IPlatformPureExpressionExecutionNodeSerializeSpecifics;
import org.finos.legend.engine.plan.dependencies.store.platform.ISerializationWriter;
import org.finos.legend.engine.plan.dependencies.store.platform.PredefinedExpressions;
import org.finos.legend.engine.plan.dependencies.store.platform.graphFetch.IPlatformPrimitiveQualifierLocalGraphFetchExecutionNodeSpecifics;
import org.finos.legend.engine.plan.dependencies.store.relational.IRelationalCreateAndPopulateTempTableExecutionNodeSpecifics;
import org.finos.legend.engine.plan.dependencies.store.relational.classResult.IRelationalClassInstantiationNodeExecutor;
import org.finos.legend.engine.plan.dependencies.store.relational.graphFetch.IRelationalChildGraphNodeExecutor;
import org.finos.legend.engine.plan.dependencies.store.relational.graphFetch.IRelationalClassQueryTempTableGraphFetchExecutionNodeSpecifics;
import org.finos.legend.engine.plan.dependencies.store.relational.graphFetch.IRelationalCrossRootGraphNodeExecutor;
import org.finos.legend.engine.plan.dependencies.store.relational.graphFetch.IRelationalCrossRootQueryTempTableGraphFetchExecutionNodeSpecifics;
import org.finos.legend.engine.plan.dependencies.store.relational.graphFetch.IRelationalPrimitiveQueryGraphFetchExecutionNodeSpecifics;
import org.finos.legend.engine.plan.dependencies.store.relational.graphFetch.IRelationalRootGraphNodeExecutor;
import org.finos.legend.engine.plan.dependencies.store.relational.graphFetch.IRelationalRootQueryTempTableGraphFetchExecutionNodeSpecifics;
import org.finos.legend.engine.plan.dependencies.store.serviceStore.IServiceParametersResolutionExecutionNodeSpecifics;
import org.finos.legend.engine.plan.dependencies.store.shared.IConstantResult;
import org.finos.legend.engine.plan.dependencies.store.shared.IExecutionNodeContext;
import org.finos.legend.engine.plan.dependencies.store.shared.IReferencedObject;
import org.finos.legend.engine.plan.dependencies.store.shared.IResult;
import org.finos.legend.engine.plan.dependencies.util.Library;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.sql.ResultSet;
import java.time.Instant;
import java.time.LocalDate;
import java.time.temporal.Temporal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
/*
* Use this to generate the PURE code for integrating with this module or equivalent extension modules.
*
* Run the main() in this class to generate the main configuration and use the output to replace
* all of /core/pure/executionPlan/javaPlatform/planConventions/enginePlatformDependencies.pure
*
* Extensions will use their own mains to generate a plan_javaRuntime_enginePlatformDependencies_conventions
* value to be added to a router extension.
*/
public class GeneratePureConfig
{
private static final String PURE_PACKAGE = "meta::pure::executionPlan::platformBinding::legendJava::";
static final Map> MAIN_DEPENDENCIES = new LinkedHashMap<>();
static
{
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IConstantResult", IConstantResult.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "EngineIResult", IResult.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IExecutionNodeContext", IExecutionNodeContext.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IGraphFetchM2MExecutionNodeContext", IGraphFetchM2MExecutionNodeContext.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "StoreStreamReader", IStoreStreamReader.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "DataParsingException", DataParsingException.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "PredefinedExpressions", PredefinedExpressions.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "Library", Library.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "GraphInstance", IGraphInstance.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "RelationalRootGraphNodeExecutor", IRelationalRootGraphNodeExecutor.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "RelationalCrossRootGraphNodeExecutor", IRelationalCrossRootGraphNodeExecutor.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "RelationalChildGraphNodeExecutor", IRelationalChildGraphNodeExecutor.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "RelationalClassInstantiationNodeExecutor", IRelationalClassInstantiationNodeExecutor.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "PureDate", PureDate.class);
MAIN_DEPENDENCIES.put("meta::pure::functions::date::DurationUnit", DurationUnit.class);
MAIN_DEPENDENCIES.put("meta::pure::functions::date::DayOfWeek", DayOfWeek.class);
MAIN_DEPENDENCIES.put("meta::pure::functions::date::Month", Month.class);
MAIN_DEPENDENCIES.put("meta::pure::functions::date::Quarter", Quarter.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "DataQualityBasicDefectClass", BasicDefect.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "DataQualityBasicRelativePathNodeClass", BasicRelativePathNode.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "DataQualityGraphContextClass", GraphContext.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "DataQualityConstrainedInterface", Constrained.class);
MAIN_DEPENDENCIES.put("meta::pure::dataQuality::Checked", IChecked.class);
MAIN_DEPENDENCIES.put("meta::pure::dataQuality::Defect", IDefect.class);
MAIN_DEPENDENCIES.put("meta::pure::dataQuality::EnforcementLevel", EnforcementLevel.class);
MAIN_DEPENDENCIES.put("meta::pure::dataQuality::RuleType", RuleType.class);
MAIN_DEPENDENCIES.put("meta::pure::dataQuality::RelativePathNode", RelativePathNode.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IReferencedObject", IReferencedObject.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IRelationalCreateAndPopulateTempTableExecutionNodeSpecifics", IRelationalCreateAndPopulateTempTableExecutionNodeSpecifics.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IPlatformPureExpressionExecutionNodeSerializeSpecifics", IPlatformPureExpressionExecutionNodeSerializeSpecifics.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IPlatformPureExpressionExecutionNodeGraphFetchUnionSpecifics", IPlatformPureExpressionExecutionNodeGraphFetchUnionSpecifics.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IPlatformPureExpressionExecutionNodeGraphFetchMergeSpecifics", IPlatformPureExpressionExecutionNodeGraphFetchMergeSpecifics.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "ISerializationWriter", ISerializationWriter.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IGraphSerializer", IGraphSerializer.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IStoreStreamReadingExecutionNodeSpecifics", IStoreStreamReadingExecutionNodeSpecifics.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IStoreStreamReadingExecutionNodeContext", IStoreStreamReadingExecutionNodeContext.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IInMemoryRootGraphFetchExecutionNodeSpecifics", IInMemoryRootGraphFetchExecutionNodeSpecifics.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IInMemoryRootGraphFetchMergeExecutionNodeSpecifics", IInMemoryRootGraphFetchMergeExecutionNodeSpecifics.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IInMemoryPropertyGraphFetchExecutionNodeSpecifics", IInMemoryPropertyGraphFetchExecutionNodeSpecifics.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IRelationalRootQueryTempTableGraphFetchExecutionNodeSpecifics", IRelationalRootQueryTempTableGraphFetchExecutionNodeSpecifics.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IRelationalCrossRootQueryTempTableGraphFetchExecutionNodeSpecifics", IRelationalCrossRootQueryTempTableGraphFetchExecutionNodeSpecifics.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IInMemoryCrossStoreGraphFetchExecutionNodeSpecifics", IInMemoryCrossStoreGraphFetchExecutionNodeSpecifics.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IRelationalClassQueryTempTableGraphFetchExecutionNodeSpecifics", IRelationalClassQueryTempTableGraphFetchExecutionNodeSpecifics.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IRelationalPrimitiveQueryGraphFetchExecutionNodeSpecifics", IRelationalPrimitiveQueryGraphFetchExecutionNodeSpecifics.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IServiceParametersResolutionExecutionNodeSpecifics", IServiceParametersResolutionExecutionNodeSpecifics.class);
MAIN_DEPENDENCIES.put(PURE_PACKAGE + "IPlatformPrimitiveQualifierLocalGraphFetchExecutionNodeSpecifics", IPlatformPrimitiveQualifierLocalGraphFetchExecutionNodeSpecifics.class);
}
private final Class> extensionClass;
public static void main(String[] args)
{
System.out.println(new GeneratePureConfig().generate());
}
private final Map> pureToJavaClasses = new LinkedHashMap<>();
private final GeneratePureConfig mainConfig;
private final String extensionName;
private final String purePackage;
private final List> classes = new ArrayList<>();
private final List> providedTypes = new ArrayList<>();
private final Map javaClasses = new LinkedHashMap<>();
private final Map standardTypes = new HashMap<>();
private final Map predefinedJavaClasses = new LinkedHashMap<>();
private GeneratePureConfig()
{
this.mainConfig = null;
this.extensionClass = null;
this.purePackage = PURE_PACKAGE;
initStandardTypes();
MAIN_DEPENDENCIES.forEach(this::addClass);
this.extensionName = null;
}
public GeneratePureConfig(String extensionName, Class> extensionClass, String purePackage)
{
this.mainConfig = new GeneratePureConfig();
this.extensionClass = extensionClass;
this.purePackage = purePackage;
initStandardTypes();
this.extensionName = Objects.requireNonNull(extensionName);
}
private void initStandardTypes()
{
standardTypes.put(Character.TYPE, new FactoryType("javaChar"));
standardTypes.put(Integer.TYPE, new FactoryType("javaInt"));
standardTypes.put(Long.TYPE, new FactoryType("javaLong"));
standardTypes.put(Float.TYPE, new FactoryType("javaFloat"));
standardTypes.put(Double.TYPE, new FactoryType("javaDouble"));
standardTypes.put(Boolean.TYPE, new FactoryType("javaBoolean"));
standardTypes.put(Void.TYPE, new FactoryType("javaVoid"));
standardTypes.put(Character.class, new FactoryType("javaCharBoxed"));
standardTypes.put(Integer.class, new FactoryType("javaIntBoxed"));
standardTypes.put(Long.class, new FactoryType("javaLongBoxed"));
standardTypes.put(Float.class, new FactoryType("javaFloatBoxed"));
standardTypes.put(Double.class, new FactoryType("javaDoubleBoxed"));
standardTypes.put(Boolean.class, new FactoryType("javaBooleanBoxed"));
standardTypes.put(Object.class, new FactoryType("javaObject"));
standardTypes.put(String.class, new FactoryType("javaString"));
standardTypes.put(Date.class, new FactoryType("javaDate"));
standardTypes.put(Instant.class, new FactoryType("javaInstant"));
standardTypes.put(LocalDate.class, new FactoryType("javaLocalDate"));
standardTypes.put(Temporal.class, new FactoryType("javaTemporal"));
standardTypes.put(java.sql.Date.class, new FactoryType("javaSqlDate"));
standardTypes.put(java.sql.Timestamp.class, new FactoryType("javaSqlTimestamp"));
standardTypes.put(Appendable.class, new FactoryType("javaAppendable"));
standardTypes.put(Number.class, new FactoryType("javaNumber"));
standardTypes.put(BigInteger.class, new FactoryType("javaBigInteger"));
standardTypes.put(BigDecimal.class, new FactoryType("javaBigDecimal"));
standardTypes.put(Calendar.class, new FactoryType("javaCalendar"));
standardTypes.put(GregorianCalendar.class, new FactoryType("javaGregorianCalendar"));
standardTypes.put(Type.class, new FactoryType("javaReflectType"));
standardTypes.put(Method.class, new FactoryType("javaReflectMethod"));
standardTypes.put(ResultSet.class, new FactoryType("javaResultSet"));
standardTypes.put(StringBuilder.class, new FactoryType("javaStringBuilder"));
standardTypes.put(URL.class, new FactoryType("javaURL"));
}
public GeneratePureConfig addClass(String pureClassPath, Class> clazz)
{
pureToJavaClasses.put(pureClassPath, clazz);
return (pureClassPath.startsWith(purePackage))
? this.defineClass(pureClassPath, clazz)
: this.mapClass(pureClassPath, clazz);
}
public String pureClassFor(Class> clazz)
{
return pureToJavaClasses.entrySet().stream().filter(kv -> kv.getValue().equals(clazz)).findFirst().map(Map.Entry::getKey)
.orElseGet(() ->
{
if (mainConfig == null)
{
throw new IllegalArgumentException("No mapping for " + clazz.getName());
}
return mainConfig.pureClassFor(clazz);
});
}
private GeneratePureConfig defineClass(String pureClassPath, Class> clazz)
{
classes.add((o -> o.lineOut("Class " + pureClassPath + " {}")));
mapClass(pureClassPath, clazz);
return this;
}
private GeneratePureConfig mapClass(String pureClassPath, Class> clazz)
{
JavaClass javaClass = new JavaClass(clazz);
javaClasses.put(clazz, javaClass);
provided(pureClassPath, javaClass.reference());
return this;
}
private void provided(String pureClassPath, String as)
{
providedTypes.add(o ->
{
o.finishLine("");
o.startLine("->addProvidedType(" + pureClassPath + ", " + as + ")");
});
}
private EncodeableType encodeType(Type type)
{
if (standardTypes.containsKey(type))
{
return standardTypes.get(type);
}
else if (javaClasses.containsKey(type))
{
return javaClasses.get(type);
}
else if (predefinedJavaClasses.containsKey(type))
{
return predefinedJavaClasses.get(type);
}
else if (mainConfig != null && mainConfig.javaClasses.containsKey(type))
{
PredefinedJavaClass predefined = new PredefinedJavaClass(mainConfig.javaClasses.get(type));
predefinedJavaClasses.put(type, predefined);
return predefined;
}
else if (type instanceof GenericArrayType)
{
return new FactoryType("javaArray", encodeType(((GenericArrayType) type).getGenericComponentType()));
}
else if (type instanceof Class && ((Class>) type).isArray())
{
return new FactoryType("javaArray", encodeType(((Class>) type).getComponentType()));
}
else if (type instanceof ParameterizedType)
{
Type raw = ((ParameterizedType) type).getRawType();
Type[] typeParams = ((ParameterizedType) type).getActualTypeArguments();
if (List.class.equals(raw))
{
return new FactoryType("javaList", encodeType(typeParams[0]));
}
if (Collection.class.equals(raw))
{
return new FactoryType("javaCollection", encodeType(typeParams[0]));
}
else if (Stream.class.equals(raw))
{
return new FactoryType("javaStream", encodeType(typeParams[0]));
}
else if (Predicate.class.equals(raw))
{
return new FactoryType("javaPredicate", encodeType(typeParams[0]));
}
else if (Comparator.class.equals(raw))
{
return new FactoryType("javaComparator", encodeType(typeParams[0]));
}
else if (Function.class.equals(raw))
{
return new FactoryType("javaFunction", encodeType(typeParams[0]), encodeType(typeParams[1]));
}
else if (BiFunction.class.equals(raw))
{
return new FactoryType("javaBiFunction", encodeType(typeParams[0]), encodeType(typeParams[1]), encodeType(typeParams[2]));
}
else if (BiPredicate.class.equals(raw))
{
return new FactoryType("javaBiPredicate", encodeType(typeParams[0]), encodeType(typeParams[1]));
}
else if (Supplier.class.equals(raw))
{
return new FactoryType("javaSupplier", encodeType(typeParams[0]));
}
else if (Consumer.class.equals(raw))
{
return new FactoryType("javaConsumer", encodeType(typeParams[0]));
}
else if (Pair.class.equals(raw))
{
List params = Arrays.stream(typeParams).map(this::encodeType).collect(Collectors.toList());
return new FactoryType("javaParameterizedType", new FactoryType("javaClass", Pair.class.getCanonicalName()), params);
}
else if (Map.class.equals(raw))
{
List params = Arrays.stream(typeParams).map(this::encodeType).collect(Collectors.toList());
return new FactoryType("javaParameterizedType", new FactoryType("javaClass", Map.class.getCanonicalName()), params);
}
else if (javaClasses.containsKey(raw))
{
List params = Arrays.stream(typeParams).map(this::encodeType).collect(Collectors.toList());
return new FactoryType("javaParameterizedType", javaClasses.get(raw), params);
}
else if (raw instanceof Class>)
{
List params = Arrays.stream(typeParams).map(this::encodeType).collect(Collectors.toList());
return new FactoryType("javaParameterizedType", encodeType(raw), params);
}
}
else if (type instanceof TypeVariable)
{
return new FactoryType("javaTypeVar", ((TypeVariable) type).getName());
}
else if (type instanceof WildcardType)
{
WildcardType w = (WildcardType) type;
List lowers = Arrays.stream(w.getLowerBounds()).map(this::encodeType).collect(Collectors.toList());
List uppers = Arrays.stream(w.getLowerBounds()).map(this::encodeType).collect(Collectors.toList());
if (lowers.isEmpty() && uppers.isEmpty())
{
return new FactoryType("javaWildcard");
}
else if (lowers.isEmpty())
{
return new FactoryType("javaWildcardExtends", uppers);
}
else if (uppers.isEmpty())
{
return new FactoryType("javaWildcardSuper", lowers);
}
else
{
return new FactoryType("javaWildcardType", lowers, uppers);
}
}
else if (type instanceof Class>)
{
return new FactoryType("javaClass", ((Class>) type).getCanonicalName());
}
throw new IllegalArgumentException("Cannot encode: " + type);
}
public String generate()
{
javaClasses.values().forEach(JavaClass::computeDependencies);
Output out = new Output();
// Splits to avoid checkstyle error
out.lineOut("// Copy" + "right " + LocalDate.now().getYear() + " Goldman Sachs");
out.lineOut("//");
out.lineOut("// Licensed under the Apache License, Version 2.0 (the \"License\");");
out.lineOut("// you may not use this file except in compliance with the License.");
out.lineOut("// You may obtain a copy of the License at");
out.lineOut("//");
out.lineOut("// http://www.apache.org" + "/licenses/LICENSE-2.0");
out.lineOut("//");
out.lineOut("// Unless required by applicable law or agreed to in writing, software");
out.lineOut("// distributed under the License is distributed on an \"AS IS\" BASIS,");
out.lineOut("// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.");
out.lineOut("// See the License for the specific language governing permissions and");
out.lineOut("// limitations under the License.");
out.lineOut("");
if (extensionName == null)
{
out.lineOut("/*");
out.lineOut(" * Generated main configuration: see " + GeneratePureConfig.class.getCanonicalName());
out.lineOut(" */");
}
else
{
out.lineOut("/*");
out.lineOut(" * Generated extension " + extensionName + " class definitions: see " + extensionClass.getCanonicalName());
out.lineOut(" */");
}
out.lineOut("");
out.lineOut("import " + purePackage + "*;");
out.lineOut("import meta::external::language::java::factory::*;");
out.lineOut("import meta::external::language::java::transform::*;");
out.lineOut("");
if (!classes.isEmpty())
{
classes.forEach(c -> c.accept(out));
out.lineOut("");
}
if (extensionName == null)
{
out.lineOut("function " + purePackage + "applyJavaEngineDependencies(conventions:Conventions[1], extensions:meta::pure::extension::Extension[*]):Conventions[1]");
}
else
{
out.lineOut("/*");
out.lineOut(" * This function should be assigned to the router extension:");
out.lineOut(" *");
out.lineOut(" * plan_javaRuntime_enginePlatformDependencies_conventions = " + purePackage + "extendJavaEngineDependencies_Conventions_1__Conventions_1_");
out.lineOut(" */");
out.lineOut("function " + purePackage + "extendJavaEngineDependencies(conventions:Conventions[1]):Conventions[1]");
}
out.lineOut("{");
out.indent();
if (!predefinedJavaClasses.isEmpty())
{
out.lineOut("");
predefinedJavaClasses.values().forEach(p -> p.declaration(out));
}
out.lineOut("");
List pending = new ArrayList<>(javaClasses.values());
while (!pending.isEmpty())
{
JavaClass toDeclare = pending.stream()
.filter(jc -> !jc.dependsOnUndeclared())
.findFirst()
.orElse(pending.get(0));
toDeclare.declaration(out);
out.lineOut("");
pending.remove(toDeclare);
}
if (extensionName == null)
{
out.startLine("let res = $conventions");
out.indent();
providedTypes.forEach(pt -> pt.accept(out));
out.outdent();
out.finishLine(";");
out.lineOut("");
out.lineOut("$extensions.plan_javaRuntime_enginePlatformDependencies_conventions->fold({e,b|$e->eval($b)}, $res);");
}
else
{
out.startLine("$conventions");
out.indent();
providedTypes.forEach(pt -> pt.accept(out));
out.outdent();
out.finishLine(";");
}
out.outdent();
out.lineOut("}");
return out.toString();
}
private static class Output
{
private final StringBuilder builder = new StringBuilder();
private int indent = 0;
void indent()
{
indent++;
}
void outdent()
{
indent--;
}
void lineOut(String line)
{
startLine(line);
finishLine("");
}
void startLine(String line)
{
if (!line.isEmpty())
{
IntStream.range(0, indent).forEach(i -> builder.append(" "));
builder.append(line);
}
}
void finishLine(String remaining)
{
builder.append(remaining);
builder.append("\n");
}
public String toString()
{
return builder.toString();
}
}
private class JavaMethod implements Comparable
{
private final Method method;
private final EncodeableType returnType;
private final List paramTypes;
JavaMethod(Method method)
{
this.method = Objects.requireNonNull(method);
this.returnType = GeneratePureConfig.this.encodeType(method.getGenericReturnType());
this.paramTypes = Arrays.stream(method.getGenericParameterTypes())
.map(GeneratePureConfig.this::encodeType)
.collect(Collectors.toList());
}
Set dependsOn()
{
Set result = new HashSet<>();
addDependency(result, returnType);
this.paramTypes.forEach(t -> addDependency(result, t));
return result;
}
private void addDependency(Set set, EncodeableType type)
{
if (type instanceof JavaClass)
{
set.add((JavaClass) type);
}
else
{
set.addAll(type.dependsOn());
}
}
String construction()
{
StringBuilder builder = new StringBuilder()
.append("javaMethod(")
.append("'public'")
.append(", ")
.append(this.returnType.code())
.append(", '")
.append(this.method.getName())
.append("', [");
for (int i = 0; i < paramTypes.size(); i++)
{
String type = this.paramTypes.get(i).code();
String name = "p" + i;
if (i > 0)
{
builder.append(", ");
}
builder.append("javaParam(").append(type).append(", '").append(name).append("')");
}
return builder
.append("])")
.toString();
}
@Override
public int compareTo(JavaMethod other)
{
int result = this.method.getName().compareTo(other.method.getName());
for (int i = 0; result == 0; i++)
{
if (this.paramTypes.size() <= i)
{
result = -1;
}
else if (other.paramTypes.size() <= i)
{
result = 1;
}
else
{
result = this.paramTypes.get(i).code().compareTo(other.paramTypes.get(i).code());
}
}
return result;
}
}
private abstract class EncodeableType
{
abstract String code();
Set dependsOn()
{
return Collections.emptySet();
}
}
private class FactoryType extends EncodeableType
{
private final String func;
private final List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy