From 071d8c65631a31445de54e0e966a17a00cb70d00 Mon Sep 17 00:00:00 2001 From: Mauricio Uyaguari Date: Thu, 26 Sep 2024 12:32:03 -0400 Subject: [PATCH] add lambdaRelationType (#3125) --- .../finos/legend/engine/server/Server.java | 1 - .../pom.xml | 4 +++ .../language/pure/compiler/api/Compile.java | 27 ++++++++++++++++ .../compiler/api/test/TestCompileApi.java | 31 +++++++++++++++++++ .../language/pure/compiler/Compiler.java | 24 +++++++++++++- 5 files changed, 85 insertions(+), 2 deletions(-) diff --git a/legend-engine-config/legend-engine-server/legend-engine-server-http-server/src/main/java/org/finos/legend/engine/server/Server.java b/legend-engine-config/legend-engine-server/legend-engine-server-http-server/src/main/java/org/finos/legend/engine/server/Server.java index c72e880b361..b948dc633e7 100644 --- a/legend-engine-config/legend-engine-server/legend-engine-server-http-server/src/main/java/org/finos/legend/engine/server/Server.java +++ b/legend-engine-config/legend-engine-server/legend-engine-server-http-server/src/main/java/org/finos/legend/engine/server/Server.java @@ -160,7 +160,6 @@ import javax.servlet.FilterRegistration; import javax.ws.rs.container.DynamicFeature; import java.io.FileInputStream; -import java.util.concurrent.ForkJoinPool; import java.util.Collections; import java.util.EnumSet; import java.util.List; diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler-http-api/pom.xml b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler-http-api/pom.xml index 72396f90e55..01c8379ea6a 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler-http-api/pom.xml +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler-http-api/pom.xml @@ -134,6 +134,10 @@ jackson-databind runtime + + com.fasterxml.jackson.core + jackson-core + diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler-http-api/src/main/java/org/finos/legend/engine/language/pure/compiler/api/Compile.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler-http-api/src/main/java/org/finos/legend/engine/language/pure/compiler/api/Compile.java index 259aa6189b6..91add3ec413 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler-http-api/src/main/java/org/finos/legend/engine/language/pure/compiler/api/Compile.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler-http-api/src/main/java/org/finos/legend/engine/language/pure/compiler/api/Compile.java @@ -24,9 +24,11 @@ import org.finos.legend.engine.language.pure.compiler.toPureGraph.PureModel; import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtensions; import org.finos.legend.engine.language.pure.modelManager.ModelManager; +import org.finos.legend.engine.protocol.pure.PureClientVersions; import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContext; import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContextData; import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContextPointer; +import org.finos.legend.engine.protocol.pure.v1.model.relationType.RelationType; import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.Lambda; import org.finos.legend.engine.shared.core.identity.Identity; import org.finos.legend.engine.shared.core.kerberos.ProfileManagerHelper; @@ -123,6 +125,31 @@ public Response lambdaReturnType(LambdaReturnTypeInput lambdaReturnTypeInput, @A } } + @POST + @Path("lambdaRelationType") + @ApiOperation(value = "Loads a given model and lambda. Returns the lambda relation type") + @Consumes({MediaType.APPLICATION_JSON, APPLICATION_ZLIB}) + @Prometheus(name = "lambda relation type") + public Response lambdaRelationType(LambdaReturnTypeInput lambdaReturnTypeInput, @ApiParam(hidden = true) @Pac4JProfileManager ProfileManager pm, @Context UriInfo uriInfo) + { + MutableList profiles = ProfileManagerHelper.extractProfiles(pm); + Identity identity = Identity.makeIdentity(profiles); + long start = System.currentTimeMillis(); + try + { + PureModelContext model = lambdaReturnTypeInput.model; + Lambda lambda = lambdaReturnTypeInput.lambda; + PureModel pureModel = this.modelManager.loadModel(model, PureClientVersions.production, identity, null); + RelationType relationType = org.finos.legend.engine.language.pure.compiler.Compiler.getLambdaRelationType(lambda, pureModel); + return Response.ok(relationType, MediaType.APPLICATION_JSON_TYPE).build(); + } + catch (Exception ex) + { + MetricsHandler.observeError(LoggingEventType.LAMBDA_RETURN_TYPE_ERROR, ex, null); + return handleException(uriInfo, identity, start, ex); + } + } + private Response handleException(UriInfo uriInfo, Identity identity, long start, Exception ex) { Response.Status status = ex instanceof EngineException ? Response.Status.BAD_REQUEST : Response.Status.INTERNAL_SERVER_ERROR; diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler-http-api/src/test/java/org/finos/legend/engine/language/pure/compiler/api/test/TestCompileApi.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler-http-api/src/test/java/org/finos/legend/engine/language/pure/compiler/api/test/TestCompileApi.java index 6447d4e2603..09b36ef8b99 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler-http-api/src/test/java/org/finos/legend/engine/language/pure/compiler/api/test/TestCompileApi.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler-http-api/src/test/java/org/finos/legend/engine/language/pure/compiler/api/test/TestCompileApi.java @@ -14,13 +14,23 @@ package org.finos.legend.engine.language.pure.compiler.api.test; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import net.javacrumbs.jsonunit.JsonAssert; +import org.finos.legend.engine.language.pure.compiler.Compiler; import org.finos.legend.engine.language.pure.compiler.api.Compile; +import org.finos.legend.engine.language.pure.compiler.api.LambdaReturnTypeInput; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.PureModel; +import org.finos.legend.engine.language.pure.grammar.from.PureGrammarParser; import org.finos.legend.engine.language.pure.modelManager.ModelManager; import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContextData; +import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContextText; +import org.finos.legend.engine.protocol.pure.v1.model.relationType.RelationType; +import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.Lambda; import org.finos.legend.engine.shared.core.ObjectMapperFactory; import org.finos.legend.engine.shared.core.deployment.DeploymentMode; +import org.finos.legend.engine.shared.core.identity.Identity; +import org.junit.Assert; import org.junit.Test; import java.util.Objects; @@ -89,4 +99,25 @@ public void testWithJson(String pureModelContextDataJsonStr, String compilationR throw new RuntimeException(e); } } + + @Test + public void testRelationType() throws JsonProcessingException + { + String model = "Class model::Person {\n" + + "name: String[1];\n" + + "}\n"; + PureModelContextText text = new PureModelContextText(); + text.code = model; + Lambda lambda = PureGrammarParser.newInstance().parseLambda("|model::Person.all()->project(~['Person Name':x|$x.name])", "", 0, 0, false); + LambdaReturnTypeInput lambdaReturnTypeInput = new LambdaReturnTypeInput(); + lambdaReturnTypeInput.model = text; + lambdaReturnTypeInput.lambda = lambda; + String stringResult = objectMapper.writeValueAsString(compileApi.lambdaRelationType(lambdaReturnTypeInput, null, null).getEntity()); + org.finos.legend.engine.protocol.pure.v1.model.relationType.RelationType relationType = objectMapper.readValue(stringResult, RelationType.class); + Assert.assertEquals(1, relationType.columns.size()); + org.finos.legend.engine.protocol.pure.v1.model.relationType.Column column = relationType.columns.get(0); + Assert.assertEquals("Person Name", column.name); + Assert.assertEquals("String", column.type); + } + } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/Compiler.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/Compiler.java index fa1e31ec6ee..3dd7d648f7c 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/Compiler.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/Compiler.java @@ -20,11 +20,15 @@ import org.finos.legend.engine.language.pure.compiler.toPureGraph.ProcessingContext; import org.finos.legend.engine.language.pure.compiler.toPureGraph.PureModel; import org.finos.legend.engine.language.pure.compiler.toPureGraph.PureModelProcessParameter; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.RelationTypeHelper; import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContextData; import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.Lambda; import org.finos.legend.engine.shared.core.deployment.DeploymentMode; +import org.finos.legend.engine.shared.core.operational.Assert; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relation.RelationType; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification; import org.finos.legend.pure.runtime.java.compiled.metadata.Metadata; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Type; public class Compiler { @@ -49,9 +53,27 @@ public static PureModel compile(PureModelContextData model, DeploymentMode deplo return new PureModel(model, user, deploymentMode, pureModelProcessParameter, metaData); } + public static ValueSpecification getLambdaRawType(Lambda lambda, PureModel pureModel) + { + return HelperValueSpecificationBuilder.buildLambdaWithContext(lambda.body, lambda.parameters, new CompileContext.Builder(pureModel).build(), new ProcessingContext("Processing return type for lambda"))._expressionSequence().getLast(); + } + + public static org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relation.RelationType buildLambdaRelationType(Lambda lambda, PureModel pureModel) + { + ValueSpecification valueSpecification = getLambdaRawType(lambda, pureModel); + Type type = valueSpecification._genericType()._typeArguments().getFirst()._rawType(); + Assert.assertTrue(type instanceof RelationType, () -> "Relation type expected in lambda"); + return (org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relation.RelationType) type; + } + + public static org.finos.legend.engine.protocol.pure.v1.model.relationType.RelationType getLambdaRelationType(Lambda lambda, PureModel pureModel) + { + return RelationTypeHelper.convert(buildLambdaRelationType(lambda, pureModel)); + } + public static String getLambdaReturnType(Lambda lambda, PureModel pureModel) { - ValueSpecification valueSpecification = HelperValueSpecificationBuilder.buildLambdaWithContext(lambda.body, lambda.parameters, new CompileContext.Builder(pureModel).build(), new ProcessingContext("Processing return type for lambda"))._expressionSequence().getLast(); + ValueSpecification valueSpecification = getLambdaRawType(lambda, pureModel); return HelperModelBuilder.getTypeFullPath(valueSpecification._genericType()._rawType(), pureModel.getExecutionSupport()); } }