diff --git a/legend-engine-config/legend-engine-repl/legend-engine-repl-client/pom.xml b/legend-engine-config/legend-engine-repl/legend-engine-repl-client/pom.xml index 9b488ba6262..4dd645c7e84 100644 --- a/legend-engine-config/legend-engine-repl/legend-engine-repl-client/pom.xml +++ b/legend-engine-config/legend-engine-repl/legend-engine-repl-client/pom.xml @@ -85,6 +85,14 @@ + + + org.finos.legend.engine + legend-engine-xt-javaPlatformBinding-PCT + runtime + + + org.finos.legend.engine diff --git a/legend-engine-config/legend-engine-repl/legend-engine-repl-client/src/main/java/org/finos/legend/engine/repl/client/Client.java b/legend-engine-config/legend-engine-repl/legend-engine-repl-client/src/main/java/org/finos/legend/engine/repl/client/Client.java index f49cc845b32..891eaaa316d 100644 --- a/legend-engine-config/legend-engine-repl/legend-engine-repl-client/src/main/java/org/finos/legend/engine/repl/client/Client.java +++ b/legend-engine-config/legend-engine-repl/legend-engine-repl-client/src/main/java/org/finos/legend/engine/repl/client/Client.java @@ -39,6 +39,7 @@ import org.finos.legend.pure.m3.pct.aggregate.generation.DocumentationGeneration; import org.finos.legend.pure.m3.pct.aggregate.model.Documentation; import org.finos.legend.pure.m3.pct.aggregate.model.FunctionDocumentation; +import org.finos.legend.pure.m3.pct.reports.model.AdapterKey; import org.jline.reader.EndOfFileException; import org.jline.reader.LineReader; import org.jline.reader.LineReaderBuilder; @@ -328,6 +329,11 @@ private void persistHistory() } } + public MutableList getDocumentationAdapterKeys() + { + return Lists.mutable.withAll(this.documentation.adapters); + } + public List getDocumentedFunctions() { return this.functionDocIndex.keysView().toSortedList(); diff --git a/legend-engine-config/legend-engine-repl/legend-engine-repl-client/src/main/java/org/finos/legend/engine/repl/core/commands/Doc.java b/legend-engine-config/legend-engine-repl/legend-engine-repl-client/src/main/java/org/finos/legend/engine/repl/core/commands/Doc.java index 813983ef05b..93e966f4bb7 100644 --- a/legend-engine-config/legend-engine-repl/legend-engine-repl-client/src/main/java/org/finos/legend/engine/repl/core/commands/Doc.java +++ b/legend-engine-config/legend-engine-repl/legend-engine-repl-client/src/main/java/org/finos/legend/engine/repl/core/commands/Doc.java @@ -55,7 +55,7 @@ public boolean process(String line) throws Exception FunctionDocumentation functionDocumentation = this.client.getFunctionDocumentation(path); if (functionDocumentation != null) { - client.println(DocumentationHelper.generateANSIFunctionDocumentation(functionDocumentation)); + client.println(DocumentationHelper.generateANSIFunctionDocumentation(functionDocumentation, client.getDocumentationAdapterKeys())); } else { diff --git a/legend-engine-config/legend-engine-repl/legend-engine-repl-client/src/main/java/org/finos/legend/engine/repl/shared/DocumentationHelper.java b/legend-engine-config/legend-engine-repl/legend-engine-repl-client/src/main/java/org/finos/legend/engine/repl/shared/DocumentationHelper.java index 0dcb117c1ea..a19c062a9ac 100644 --- a/legend-engine-config/legend-engine-repl/legend-engine-repl-client/src/main/java/org/finos/legend/engine/repl/shared/DocumentationHelper.java +++ b/legend-engine-config/legend-engine-repl/legend-engine-repl-client/src/main/java/org/finos/legend/engine/repl/shared/DocumentationHelper.java @@ -16,14 +16,24 @@ import org.apache.commons.lang3.StringUtils; import org.eclipse.collections.api.block.function.Function0; +import org.eclipse.collections.api.factory.Lists; import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.api.map.MutableMap; +import org.eclipse.collections.impl.tuple.Tuples; +import org.eclipse.collections.impl.utility.ArrayIterate; +import org.eclipse.collections.impl.utility.ListIterate; +import org.eclipse.collections.impl.utility.MapIterate; import org.finos.legend.engine.repl.client.Client; +import org.finos.legend.pure.m3.pct.aggregate.model.Documentation; import org.finos.legend.pure.m3.pct.aggregate.model.FunctionDocumentation; -import org.finos.legend.pure.m3.pct.functions.model.Signature; +import org.finos.legend.pure.m3.pct.functions.model.FunctionDefinition; +import org.finos.legend.pure.m3.pct.reports.model.Adapter; +import org.finos.legend.pure.m3.pct.reports.model.AdapterKey; +import org.finos.legend.pure.m3.pct.reports.model.TestInfo; -import static org.finos.legend.engine.repl.shared.REPLHelper.ansiDim; -import static org.finos.legend.engine.repl.shared.REPLHelper.ansiGreen; +import java.util.Objects; + +import static org.finos.legend.engine.repl.shared.REPLHelper.*; public class DocumentationHelper { @@ -37,51 +47,73 @@ public class DocumentationHelper MODULE_URLS.put("relation", "https://github.com/finos/legend-engine/tree/master/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-functions-relation/legend-engine-pure-functions-relation-pure/src/main/resources"); } - private static final int ANSI_ATTR_WIDTH = 20; + private static final int ANSI_ATTR_WIDTH = 8; - public static String generateANSIFunctionDocumentation(FunctionDocumentation functionDocumentation) + public static String generateANSIFunctionDocumentation(FunctionDocumentation functionDocumentation, MutableList adapterKeys) { StringBuilder builder = new StringBuilder(); - builder.append(ansiAttr("function")).append(ansiGreen(functionDocumentation.reportScope._package + "::" + functionDocumentation.functionDefinition.name + "()")).append("\n"); - builder.append(ansiAttr(" [src]")).append(getFunctionSourceUrl(functionDocumentation)).append("\n"); - builder.append("\n"); - for (int i = 0; i < functionDocumentation.functionDefinition.signatures.size(); i++) + FunctionDefinition definition = functionDocumentation.functionDefinition; + String name = definition.name; + String path = definition._package + "::" + name; + String src = MODULE_URLS.get(functionDocumentation.reportScope.module) + definition.sourceId; + String grouping = definition.sourceId.substring(functionDocumentation.reportScope.filePath.length(), definition.sourceId.lastIndexOf("/")); + // NOTE: make assumption that each function has doc/usage on exactly one of the signatures + String syntax = ListIterate.detectOptional(definition.signatures, signature -> signature.grammarCharacter != null).map(s -> s.grammarCharacter).orElse(null); + String doc = ListIterate.detectOptional(definition.signatures, signature -> signature.documentation != null).map(s -> s.documentation).orElse(null); + String usage = ListIterate.detectOptional(definition.signatures, signature -> signature.grammarDoc != null).map(s -> s.grammarDoc).orElse(null); + + Lists.mutable.with(syntax != null ? ansiGreen(syntax) : null) + .with(name) + .withAll(ListIterate.collect(definition.signatures, s -> s.simple.substring(definition._package.length() + 2))) + .select(Objects::nonNull) + .forEachWithIndex((value, idx) -> builder.append(ansiAttr(idx == 0 ? "function" : null)).append(value).append("\n")); + builder.append(ansiAttr("path")).append(path).append("\n"); + builder.append(ansiAttr("grouping")).append("(" + functionDocumentation.reportScope.module + ") " + grouping).append("\n"); + builder.append(ansiAttr("src")).append(src).append("\n"); + if (doc != null) { - Signature signature = functionDocumentation.functionDefinition.signatures.get(i); - builder.append(ansiGreen(ansiAttr("#[" + (i + 1) + "]"))); - if (signature.grammarCharacter != null) - { - builder.append(ansiGreen(signature.grammarCharacter)); - builder.append("\n").append(ansiAttr("")); - } - builder.append(ansiGreen(signature.simple)).append("\n"); - builder.append(ansiAttr(" [id]")).append(ansiDim(signature.id)); - if (signature.documentation != null) - { - builder.append("\n"); - builder.append(ansiAttr(" [doc]")).append(signature.documentation); - } - if (signature.grammarDoc != null) + builder.append(ansiAttr("doc")).append(ArrayIterate.makeString(wrap(doc).split("\n"), "\n" + ansiAttr(null))).append("\n"); + } + if (usage != null) + { + builder.append(ansiAttr("usage")).append(usage).append("\n"); + } + + // compatibility + MutableMap matrix = MapIterate.collect(functionDocumentation.functionTestResults, (adapterKey, testResults) -> + { + String key = adapterKey.adapter.group + (adapterKey.adapter.group.isEmpty() ? "" : "/") + adapterKey.adapter.name; + MutableList tests = Lists.mutable.withAll(testResults.tests); + String value; + if (tests.isEmpty()) { - builder.append("\n"); - builder.append(ansiAttr(" [usage]")).append(signature.grammarDoc); + value = ansiDim("∅"); } - if (i != functionDocumentation.functionDefinition.signatures.size() - 1) + else { - builder.append("\n"); + int passedCount = tests.select(t -> t.success).size(); + value = passedCount + "/" + tests.size(); + value = passedCount == 0 ? ansiRed(value) : passedCount == tests.size() ? ansiGreen(value) : ansiYellow(value); } - } + return Tuples.pair(key, value); + }); + // NOTE: here we sort the adapter naively, and it achieves the desired order anyway, + // but we should consider a more methodical/intentional sort: e.g. native goes first, followed by platforms and stores + MutableList adapters = adapterKeys.collect(adapterKey -> adapterKey.adapter.group + (adapterKey.adapter.group.isEmpty() ? "" : "/") + adapterKey.adapter.name).toSortedList(); + int maxKeyLength = adapters.collect(String::length).max(); + + builder.append("\n").append(StringUtils.rightPad("compatibility", maxKeyLength + 2)).append(" :").append("\n"); + builder.append(adapters.collect(adapter -> StringUtils.rightPad(" " + adapter, maxKeyLength + 2) + " : " + matrix.getOrDefault(adapter, "∅")).makeString("\n")); return builder.toString(); } private static String ansiAttr(String attr) { - return StringUtils.rightPad(attr, ANSI_ATTR_WIDTH); - } - - private static String getFunctionSourceUrl(FunctionDocumentation functionDocumentation) - { - return MODULE_URLS.get(functionDocumentation.reportScope.module) + functionDocumentation.functionDefinition.sourceId; + if (attr == null) + { + return StringUtils.rightPad("", ANSI_ATTR_WIDTH + 3); + } + return StringUtils.rightPad(attr, ANSI_ATTR_WIDTH) + " : "; } public abstract static class Walkthrough diff --git a/legend-engine-config/legend-engine-repl/legend-engine-repl-data-cube/pom.xml b/legend-engine-config/legend-engine-repl/legend-engine-repl-data-cube/pom.xml index 2a8f2114265..3bc734d4a63 100644 --- a/legend-engine-config/legend-engine-repl/legend-engine-repl-data-cube/pom.xml +++ b/legend-engine-config/legend-engine-repl/legend-engine-repl-data-cube/pom.xml @@ -28,7 +28,7 @@ false - 12.28.0 + 12.31.0 ${npm.registry.url}/@finos/legend-application-repl-deployment/-/legend-application-repl-deployment-${repl.web-application.version}.tgz diff --git a/legend-engine-config/legend-engine-repl/legend-engine-repl-data-cube/src/main/java/org/finos/legend/engine/repl/dataCube/commands/DataCubeWalkthrough.java b/legend-engine-config/legend-engine-repl/legend-engine-repl-data-cube/src/main/java/org/finos/legend/engine/repl/dataCube/commands/DataCubeWalkthrough.java index e8f6d511435..10ff63e85bd 100644 --- a/legend-engine-config/legend-engine-repl/legend-engine-repl-data-cube/src/main/java/org/finos/legend/engine/repl/dataCube/commands/DataCubeWalkthrough.java +++ b/legend-engine-config/legend-engine-repl/legend-engine-repl-data-cube/src/main/java/org/finos/legend/engine/repl/dataCube/commands/DataCubeWalkthrough.java @@ -302,7 +302,7 @@ protected MutableList> getSteps() "usages for 'filter', use the following command:")); this.printCommand("doc meta::pure::functions::relation::filter"); this.println(ansiDim(printRule(null))); - this.println(DocumentationHelper.generateANSIFunctionDocumentation(this.client.getFunctionDocumentation("meta::pure::functions::relation::filter"))); + this.println(DocumentationHelper.generateANSIFunctionDocumentation(this.client.getFunctionDocumentation("meta::pure::functions::relation::filter"), this.client.getDocumentationAdapterKeys())); this.client.addCommandToHistory("doc meta::pure::functions::relation::filter"); this.println(ansiDim(printRule(null))); this.println(""); diff --git a/legend-engine-config/legend-engine-repl/legend-engine-repl-data-cube/src/main/java/org/finos/legend/engine/repl/dataCube/server/REPLServer.java b/legend-engine-config/legend-engine-repl/legend-engine-repl-data-cube/src/main/java/org/finos/legend/engine/repl/dataCube/server/REPLServer.java index 776342ed624..8356baa8129 100644 --- a/legend-engine-config/legend-engine-repl/legend-engine-repl-data-cube/src/main/java/org/finos/legend/engine/repl/dataCube/server/REPLServer.java +++ b/legend-engine-config/legend-engine-repl/legend-engine-repl-data-cube/src/main/java/org/finos/legend/engine/repl/dataCube/server/REPLServer.java @@ -14,21 +14,18 @@ package org.finos.legend.engine.repl.dataCube.server; -import com.fasterxml.jackson.databind.ObjectMapper; import com.sun.net.httpserver.Filter; import com.sun.net.httpserver.HttpContext; import com.sun.net.httpserver.HttpServer; import org.eclipse.collections.api.factory.Lists; import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.impl.factory.Maps; -import org.finos.legend.engine.plan.execution.PlanExecutor; import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContextData; import org.finos.legend.engine.repl.client.Client; import org.finos.legend.engine.repl.dataCube.server.handler.DataCubeInfrastructure; import org.finos.legend.engine.repl.dataCube.server.handler.DataCubeQueryBuilder; import org.finos.legend.engine.repl.dataCube.server.handler.DataCubeQueryExecutor; import org.finos.legend.engine.repl.shared.ExecutionHelper; -import org.finos.legend.engine.shared.core.ObjectMapperFactory; import java.net.InetSocketAddress; import java.util.List; @@ -37,8 +34,6 @@ public class REPLServer { - private static final ObjectMapper objectMapper = ObjectMapperFactory.getNewStandardObjectMapperWithPureProtocolExtensionSupports(); - private static final PlanExecutor planExecutor = PlanExecutor.newPlanExecutorBuilder().withAvailableStoreExecutors().build(); private final Client client; private final REPLServerHelpers.REPLServerState state; @@ -49,7 +44,7 @@ public class REPLServer public REPLServer(Client client) { this.client = client; - this.state = new REPLServerHelpers.REPLServerState(client, objectMapper, planExecutor, client.getLegendInterface()); + this.state = new REPLServerHelpers.REPLServerState(client, client.getObjectMapper(), client.getPlanExecutor(), client.getLegendInterface()); } public void initializeStateWithREPLExecutedQuery(ExecutionHelper.ExecuteResultSummary executeResultSummary) diff --git a/legend-engine-config/legend-engine-repl/legend-engine-repl-relational/pom.xml b/legend-engine-config/legend-engine-repl/legend-engine-repl-relational/pom.xml index ac5661dba33..ea938a5128d 100644 --- a/legend-engine-config/legend-engine-repl/legend-engine-repl-relational/pom.xml +++ b/legend-engine-config/legend-engine-repl/legend-engine-repl-relational/pom.xml @@ -85,6 +85,30 @@ + + + org.finos.legend.engine + legend-engine-xt-relationalStore-duckdb-PCT + runtime + + + + org.finos.legend.engine + legend-engine-xt-relationalStore-h2-PCT + runtime + + + org.finos.legend.engine + legend-engine-xt-relationalStore-postgres-PCT + runtime + + + org.finos.legend.engine + legend-engine-xt-relationalStore-snowflake-PCT + runtime + + + com.h2database h2 diff --git a/legend-engine-pure/legend-engine-pure-ide/legend-engine-pure-ide-light-http-server/pom.xml b/legend-engine-pure/legend-engine-pure-ide/legend-engine-pure-ide-light-http-server/pom.xml index 7529ff2b916..b24c4ee3e8e 100644 --- a/legend-engine-pure/legend-engine-pure-ide/legend-engine-pure-ide-light-http-server/pom.xml +++ b/legend-engine-pure/legend-engine-pure-ide/legend-engine-pure-ide-light-http-server/pom.xml @@ -28,7 +28,7 @@ false - 9.0.0 + 12.31.0 ${npm.registry.url}/@finos/legend-application-pure-ide-deployment/-/legend-application-pure-ide-deployment-${pure-ide.web-application.version}.tgz