diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar/src/test/java/org/finos/legend/engine/language/pure/grammar/test/TestGrammarRoundtrip.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar/src/test/java/org/finos/legend/engine/language/pure/grammar/test/TestGrammarRoundtrip.java index 77933497a25..6b193a4dc12 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar/src/test/java/org/finos/legend/engine/language/pure/grammar/test/TestGrammarRoundtrip.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar/src/test/java/org/finos/legend/engine/language/pure/grammar/test/TestGrammarRoundtrip.java @@ -120,12 +120,17 @@ private static void test(String code, String message, boolean keepSectionIndex) public static void testFormatWithSectionInfoPreserved(String code, String unformattedCode) { - testFormat(code, unformattedCode, false); + testFormat(code, unformattedCode, false, false); } public static void testFormat(String code, String unformattedCode) { - testFormat(code, unformattedCode, true); + testFormat(code, unformattedCode, true, false); + } + + public static void testConvert(String code, String unformattedCode) + { + testFormat(code, unformattedCode, true, true); } /** @@ -143,7 +148,7 @@ public static void testFormat(String code, String unformattedCode) * ... * // end of example */ - private static void testFormat(String code, String unformattedCode, boolean omitSectionIndex) + private static void testFormat(String code, String unformattedCode, boolean omitSectionIndex, boolean withConvert) { PureGrammarComposer grammarTransformer = PureGrammarComposer.newInstance(PureGrammarComposerContext.Builder.newInstance().build()); // NOTE: no need to get source information @@ -153,8 +158,11 @@ private static void testFormat(String code, String unformattedCode, boolean omit parsedModel = PureModelContextData.newPureModelContextData(parsedModel.getSerializer(), parsedModel.getOrigin(), LazyIterate.reject(parsedModel.getElements(), e -> e instanceof SectionIndex)); } - // run json deserializer to apply protocol updates (migrate from old to new)... - parsedModel = ObjectMapperFactory.getNewStandardObjectMapperWithPureProtocolExtensionSupports().convertValue(parsedModel, PureModelContextData.class); + if (withConvert) + { + // run json deserializer to apply protocol updates (migrate from old to new)... + parsedModel = ObjectMapperFactory.getNewStandardObjectMapperWithPureProtocolConverterSupports().convertValue(parsedModel, PureModelContextData.class); + } String formatted = grammarTransformer.renderPureModelContextData(parsedModel); Assert.assertEquals(code, formatted); diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar/src/test/java/org/finos/legend/engine/language/pure/grammar/test/roundtrip/TestDomainGrammarRoundtrip.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar/src/test/java/org/finos/legend/engine/language/pure/grammar/test/roundtrip/TestDomainGrammarRoundtrip.java index 50e008462f3..9af1f1935aa 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar/src/test/java/org/finos/legend/engine/language/pure/grammar/test/roundtrip/TestDomainGrammarRoundtrip.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar/src/test/java/org/finos/legend/engine/language/pure/grammar/test/roundtrip/TestDomainGrammarRoundtrip.java @@ -665,18 +665,53 @@ public void testTypeArgumentsAreBackwardCompatibleForOldProtocolMissingIt() thro } @Test - public void testTypeArgumentsAreBackwardCompatibleForOldGrammarMissingIt() throws JsonProcessingException + public void testConvertBasicColumnSpecification() { - testFormat("function test::new(): Any[1]\n" + + testConvert("function test::new(): Any[1]\n" + "{\n" + - " ^BasicColumnSpecification(func=r: TDSRow[1]|1)\n" + + " meta::pure::tds::col(r: TDSRow[1]|1, 'hello')\n" + "}\n", "function test::new(): Any[1]\n" + "{\n" + - " ^BasicColumnSpecification(func=r: TDSRow[1]|1)\n" + + " ^BasicColumnSpecification(func=r: TDSRow[1]|1, name='hello')\n" + "}\n"); - testFormat("function test::new(res: Result[1]): Any[1]\n" + + testConvert("function test::new(): Any[1]\n" + + "{\n" + + " meta::pure::tds::col(r: TDSRow[1]|1, 'hello', 'documentation here')\n" + + "}\n", + "function test::new(): Any[1]\n" + + "{\n" + + " ^meta::pure::tds::BasicColumnSpecification(documentation='documentation here', func=r: TDSRow[1]|1, name='hello')\n" + + "}\n"); + } + + @Test + public void testConvertTdsOlapRank() + { + testConvert("function test::new(): Any[1]\n" + + "{\n" + + " meta::pure::tds::func(r: TDSRow[1]|1)\n" + + "}\n", + "function test::new(): Any[1]\n" + + "{\n" + + " ^meta::pure::tds::TdsOlapRank(func=r: TDSRow[1]|1)\n" + + "}\n"); + + testConvert("function test::new(): Any[1]\n" + + "{\n" + + " meta::pure::tds::func(r: TDSRow[1]|1)\n" + + "}\n", + "function test::new(): Any[1]\n" + + "{\n" + + " ^TdsOlapRank(func=r: TDSRow[1]|1)\n" + + "}\n"); + } + + @Test + public void testConvertResult() + { + testConvert("function test::new(res: Result[1]): Any[1]\n" + "{\n" + " 1\n" + "}\n", diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/CorePureProtocolExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/CorePureProtocolExtension.java index be0ff35841a..0c7faa0d09c 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/CorePureProtocolExtension.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/CorePureProtocolExtension.java @@ -14,10 +14,18 @@ package org.finos.legend.engine.protocol.pure.v1; +import com.fasterxml.jackson.databind.util.StdConverter; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; import org.eclipse.collections.api.block.function.Function0; import org.eclipse.collections.api.factory.Lists; import org.eclipse.collections.api.factory.Maps; +import org.eclipse.collections.api.factory.Sets; import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.impl.utility.ListIterate; +import org.finos.legend.engine.protocol.pure.v1.extension.ProtocolConverter; import org.finos.legend.engine.protocol.pure.v1.extension.ProtocolSubTypeInfo; import org.finos.legend.engine.protocol.pure.v1.extension.PureProtocolExtension; import org.finos.legend.engine.protocol.pure.v1.model.data.DataElementReference; @@ -42,6 +50,7 @@ import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Enumeration; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Function; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Measure; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Multiplicity; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Profile; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.externalFormat.Binding; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.externalFormat.ExternalFormatSchemaSet; @@ -71,9 +80,15 @@ import org.finos.legend.engine.protocol.pure.v1.model.test.result.TestExecuted; import org.finos.legend.engine.protocol.pure.v1.model.test.result.TestExecutionPlanDebug; import org.finos.legend.engine.protocol.pure.v1.model.test.result.TestResult; - -import java.util.List; -import java.util.Map; +import org.finos.legend.engine.protocol.pure.v1.model.type.GenericType; +import org.finos.legend.engine.protocol.pure.v1.model.type.PackageableType; +import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.Variable; +import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.application.AppliedFunction; +import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.Collection; +import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.KeyExpression; +import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.Lambda; +import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.datatype.CString; +import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.packageableElement.GenericTypeInstance; public class CorePureProtocolExtension implements PureProtocolExtension { @@ -180,4 +195,133 @@ public Map, String> getExtraProtoc .withKeyValue(SectionIndex.class, "meta::pure::metamodel::section::SectionIndex") .withKeyValue(RelationalMapper.class, "meta::relational::metamodel::RelationalMapper"); } + + @Override + public List> getConverterDeserializers() + { + return Lists.fixedSize.with( + new ProtocolConverter<>(new ResultVariableWithMissingTypeConverter()), + new ProtocolConverter<>( + Lists.mutable.with( + new BasicColumnSpecificationToColFunctionConverter(), + new TdsOlapRankToColFunctionConverter())) + ); + } + + private static class ResultVariableWithMissingTypeConverter extends StdConverter + { + @Override + public Variable convert(Variable variable) + { + if (variable.genericType != null && variable.genericType.rawType instanceof PackageableType) + { + String _class = ((PackageableType) variable.genericType.rawType).fullPath; + if (("meta::pure::mapping::Result".equals(_class) || "Result".equals(_class)) && variable.genericType.typeArguments.size() == 0) + { + variable.genericType.typeArguments = Lists.mutable.of(new GenericType(new PackageableType("meta::pure::metamodel::type::Any"))); + variable.genericType.multiplicityArguments = Lists.mutable.of(Multiplicity.PURE_MANY); + } + } + return variable; + } + } + + private static class BasicColumnSpecificationToColFunctionConverter extends StdConverter + { + @Override + public AppliedFunction convert(AppliedFunction appliedFunction) + { + if (appliedFunction.function.equals("new")) + { + GenericTypeInstance typeInstance = (GenericTypeInstance) appliedFunction.parameters.get(0); + if (typeInstance.genericType.typeArguments.size() >= 1 && typeInstance.genericType.typeArguments.get(0).rawType instanceof PackageableType) + { + PackageableType type = (PackageableType) typeInstance.genericType.typeArguments.get(0).rawType; + + Set classesThatNeedTypeFixing = Sets.fixedSize.of( + "meta::pure::tds::BasicColumnSpecification", + "BasicColumnSpecification" + ); + + if (classesThatNeedTypeFixing.contains(type.fullPath)) + { + Collection collection = (Collection) appliedFunction.parameters.get(2); + Optional func = ListIterate.detectOptional(collection.values, x -> ((CString) ((KeyExpression) x).key).value.equals("func")) + .map(KeyExpression.class::cast) + .map(x -> x.expression) + .filter(Lambda.class::isInstance) + .map(Lambda.class::cast); + + Optional name = ListIterate.detectOptional(collection.values, x -> ((CString) ((KeyExpression) x).key).value.equals("name")) + .map(KeyExpression.class::cast) + .map(x -> x.expression) + .filter(CString.class::isInstance) + .map(CString.class::cast); + + Optional doc = ListIterate.detectOptional(collection.values, x -> ((CString) ((KeyExpression) x).key).value.equals("documentation")) + .map(KeyExpression.class::cast) + .map(x -> x.expression) + .filter(CString.class::isInstance) + .map(CString.class::cast); + + if (func.isPresent() && name.isPresent()) + { + appliedFunction.function = "meta::pure::tds::col"; + appliedFunction.parameters = Lists.mutable.with(func.get(), name.get()); + + if (doc.isPresent()) + { + appliedFunction.fControl = "meta::pure::tds::col_Function_1__String_1__String_1__BasicColumnSpecification_1_"; + appliedFunction.parameters.add(doc.get()); + } + else + { + appliedFunction.fControl = "meta::pure::tds::col_Function_1__String_1__BasicColumnSpecification_1_"; + } + } + } + } + } + return appliedFunction; + } + } + + private static class TdsOlapRankToColFunctionConverter extends StdConverter + { + @Override + public AppliedFunction convert(AppliedFunction appliedFunction) + { + if (appliedFunction.function.equals("new")) + { + GenericTypeInstance typeInstance = (GenericTypeInstance) appliedFunction.parameters.get(0); + if (typeInstance.genericType.typeArguments.size() >= 1 && typeInstance.genericType.typeArguments.get(0).rawType instanceof PackageableType) + { + PackageableType type = (PackageableType) typeInstance.genericType.typeArguments.get(0).rawType; + + Set classesThatNeedTypeFixing = Sets.fixedSize.of( + "meta::pure::tds::TdsOlapRank", + "TdsOlapRank" + ); + + if (classesThatNeedTypeFixing.contains(type.fullPath)) + { + Collection collection = (Collection) appliedFunction.parameters.get(2); + Optional func = ListIterate.detectOptional(collection.values, x -> ((CString) ((KeyExpression) x).key).value.equals("func")) + .map(KeyExpression.class::cast) + .map(x -> x.expression) + .filter(Lambda.class::isInstance) + .map(Lambda.class::cast); + + if (func.isPresent()) + { + appliedFunction.function = "meta::pure::tds::func"; + appliedFunction.fControl = "meta::pure::tds::func_FunctionDefinition_1__TdsOlapRank_1_"; + appliedFunction.parameters = Lists.mutable.with(func.get()); + } + } + } + } + return appliedFunction; + } + } } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/PureProtocolObjectMapperFactory.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/PureProtocolObjectMapperFactory.java index 864ad077362..5d6c11c0474 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/PureProtocolObjectMapperFactory.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/PureProtocolObjectMapperFactory.java @@ -14,13 +14,41 @@ package org.finos.legend.engine.protocol.pure.v1; +import com.fasterxml.jackson.databind.BeanDescription; +import com.fasterxml.jackson.databind.DeserializationConfig; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; import com.fasterxml.jackson.databind.cfg.MapperBuilder; +import com.fasterxml.jackson.databind.cfg.MapperConfig; +import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier; +import com.fasterxml.jackson.databind.deser.std.StdDelegatingDeserializer; +import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.jsontype.NamedType; +import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; +import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.type.TypeFactory; +import com.fasterxml.jackson.databind.util.ClassUtil; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.Predicate; +import java.util.stream.Collectors; import org.eclipse.collections.api.block.function.Function0; import org.eclipse.collections.api.factory.Maps; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.impl.multimap.list.FastListMultimap; import org.eclipse.collections.impl.utility.LazyIterate; +import org.eclipse.collections.impl.utility.ListIterate; +import org.finos.legend.engine.protocol.pure.v1.extension.ProtocolConverter; import org.finos.legend.engine.protocol.pure.v1.extension.ProtocolSubTypeInfo; import org.finos.legend.engine.protocol.pure.v1.extension.PureProtocolExtension; import org.finos.legend.engine.protocol.pure.v1.extension.PureProtocolExtensionLoader; @@ -41,12 +69,6 @@ import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.classInstance.relation.ColSpecArray; import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.classInstance.relation.RelationStoreAccessor; -import java.util.Collection; -import java.util.Map; -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.Predicate; - public class PureProtocolObjectMapperFactory { public static > T withPureProtocolExtensions(T mapperBuilder) @@ -158,4 +180,93 @@ public static ObjectMapper getNewObjectMapper(Set excludedSubTypes) { return withPureProtocolExtensions(new ObjectMapper(), excludedSubTypes); } + + public static ObjectMapper withPureProtocolConverter(ObjectMapper objectMapper) + { + ObjectMapper withPureProtocolExtensions = withPureProtocolExtensions(objectMapper); + + List> protocolConverters = PureProtocolExtensionLoader.extensions().stream() + .map(PureProtocolExtension::getConverterDeserializers) + .filter(Objects::nonNull) + .flatMap(List::stream) + .collect(Collectors.toList()); + + FastListMultimap> converterByType = ListIterate.groupBy(protocolConverters, x -> x.getInputType(TypeFactory.defaultInstance())); + + DeserializationConfig deserializationConfig = withPureProtocolExtensions + .getDeserializationConfig() + .with(new ConverterHandlerInstantiator(converterByType)); + + SimpleModule module = new SimpleModule("protocol converters"); + module.setDeserializerModifier(new ConverterBeanDeserializerModifier(converterByType)); + + return withPureProtocolExtensions.setConfig(deserializationConfig).registerModule(module); + } + + private static class ConverterHandlerInstantiator extends HandlerInstantiator + { + private final FastListMultimap> converterByType; + + public ConverterHandlerInstantiator(FastListMultimap> converterByType) + { + this.converterByType = converterByType; + } + + @Override + public JsonDeserializer deserializerInstance(DeserializationConfig config, Annotated annotated, Class deserClass) + { + MutableList> converters = this.converterByType.get(annotated.getType()); + if (!converters.isEmpty()) + { + JsonDeserializer deser = (JsonDeserializer) ClassUtil.createInstance(deserClass, config.canOverrideAccessModifiers()); + return new StdDelegatingDeserializer<>(ProtocolConverter.merge((List) converters), annotated.getType(), deser); + } + return null; + } + + @Override + public KeyDeserializer keyDeserializerInstance(DeserializationConfig config, Annotated annotated, Class keyDeserClass) + { + return null; + } + + @Override + public JsonSerializer serializerInstance(com.fasterxml.jackson.databind.SerializationConfig config, Annotated annotated, Class serClass) + { + return null; + } + + @Override + public TypeResolverBuilder typeResolverBuilderInstance(MapperConfig config, Annotated annotated, Class builderClass) + { + return null; + } + + @Override + public TypeIdResolver typeIdResolverInstance(MapperConfig config, Annotated annotated, Class resolverClass) + { + return null; + } + } + + private static class ConverterBeanDeserializerModifier extends BeanDeserializerModifier + { + private final FastListMultimap> converterByType; + + public ConverterBeanDeserializerModifier(FastListMultimap> converterByType) + { + this.converterByType = converterByType; + } + + @Override + public JsonDeserializer modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer deserializer) + { + MutableList> converters = this.converterByType.get(beanDesc.getType()); + if (!converters.isEmpty()) + { + return new StdDelegatingDeserializer(ProtocolConverter.merge((List) converters), beanDesc.getType(), deserializer); + } + return deserializer; + } + } } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/extension/ProtocolConverter.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/extension/ProtocolConverter.java new file mode 100644 index 00000000000..2cf4daa96a2 --- /dev/null +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/extension/ProtocolConverter.java @@ -0,0 +1,63 @@ +// Copyright 2024 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.protocol.pure.v1.extension; + +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.type.TypeFactory; +import com.fasterxml.jackson.databind.util.Converter; +import java.util.List; +import java.util.stream.Collectors; +import org.eclipse.collections.impl.factory.Lists; +import org.eclipse.collections.impl.utility.ListIterate; + +public class ProtocolConverter implements Converter +{ + private final List> converters; + + public ProtocolConverter(Converter converters) + { + this(Lists.fixedSize.of(converters)); + } + + public ProtocolConverter(List> converters) + { + this.converters = converters; + } + + @Override + public JavaType getInputType(TypeFactory typeFactory) + { + return this.converters.get(0).getInputType(typeFactory); + } + + @Override + public JavaType getOutputType(TypeFactory typeFactory) + { + return this.converters.get(0).getOutputType(typeFactory); + } + + @Override + public T convert(T value) + { + return ListIterate.injectInto(value, this.converters, (t, c) -> c.convert(t)); + } + + public static ProtocolConverter merge(List> converters) + { + List> allConverters = converters.stream().flatMap(x -> x.converters.stream()).collect(Collectors.toList()); + return new ProtocolConverter<>(allConverters); + } +} diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/extension/PureProtocolExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/extension/PureProtocolExtension.java index 4913301d80a..3ca9aab7f8a 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/extension/PureProtocolExtension.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/extension/PureProtocolExtension.java @@ -15,6 +15,7 @@ package org.finos.legend.engine.protocol.pure.v1.extension; import org.eclipse.collections.api.block.function.Function0; +import org.eclipse.collections.impl.factory.Lists; import org.eclipse.collections.impl.factory.Maps; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement; import org.finos.legend.engine.shared.core.extension.LegendLanguageExtension; @@ -47,4 +48,8 @@ default Map getExtraClassInstanceTypeMappings() return Maps.mutable.empty(); } + default List> getConverterDeserializers() + { + return Lists.fixedSize.empty(); + } } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/valueSpecification/Variable.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/valueSpecification/Variable.java index 2cef81ec1d6..e97a3ead7ce 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/valueSpecification/Variable.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/valueSpecification/Variable.java @@ -90,19 +90,6 @@ public ValueSpecification deserialize(JsonParser jsonParser, DeserializationCont else if (node.get("genericType") != null) { variable.genericType = om.treeToValue(node.get("genericType"), GenericType.class); - - // Backward compatibility - old grammar ------------------------------------------------------------------- - if (variable.genericType != null && variable.genericType.rawType instanceof PackageableType) - { - String _class = ((PackageableType) variable.genericType.rawType).fullPath; - if (("meta::pure::mapping::Result".equals(_class) || "Result".equals(_class)) && variable.genericType.typeArguments.size() == 0) - { - variable.genericType.typeArguments = Lists.mutable.of(new GenericType(new PackageableType("meta::pure::metamodel::type::Any"))); - variable.genericType.multiplicityArguments = Lists.mutable.of(Multiplicity.PURE_MANY); - } - } - // Backward compatibility - old grammar ------------------------------------------------------------------- - } if (node.get("multiplicity") != null) { diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/valueSpecification/application/AppliedFunction.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/valueSpecification/application/AppliedFunction.java index e03f00b8fbc..9356bcdc45b 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/valueSpecification/application/AppliedFunction.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/valueSpecification/application/AppliedFunction.java @@ -16,9 +16,12 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.util.StdConverter; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.Set; import org.eclipse.collections.api.factory.Lists; import org.eclipse.collections.api.factory.Sets; -import org.eclipse.collections.api.set.FixedSizeSet; import org.eclipse.collections.impl.utility.ListIterate; import org.finos.legend.engine.protocol.pure.v1.model.type.GenericType; import org.finos.legend.engine.protocol.pure.v1.model.type.PackageableType; @@ -31,11 +34,6 @@ import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.packageableElement.GenericTypeInstance; import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.packageableElement.PackageableElementPtr; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.Set; - @JsonDeserialize(converter = AppliedFunction.AppliedFunctionConverter.class) public class AppliedFunction extends AbstractAppliedFunction { @@ -54,58 +52,42 @@ public static class AppliedFunctionConverter extends StdConverter classesThatNeedTypeFixing = Sets.fixedSize.of( - "meta::pure::tds::BasicColumnSpecification", - "BasicColumnSpecification", - "meta::pure::tds::TdsOlapRank", - "TdsOlapRank" - ); - if (classesThatNeedTypeFixing.contains(type.fullPath)) - { - Collection collection = (Collection) appliedFunction.parameters.get(2); - Optional func = ListIterate.detectOptional(collection.values, x -> ((CString) ((KeyExpression) x).key).value.equals("func")) - .map(KeyExpression.class::cast) - .map(x -> x.expression) - .filter(Lambda.class::isInstance) - .map(Lambda.class::cast) - .filter(x -> x.parameters.size() == 1); + PackageableElementPtr packageableElementPtr = (PackageableElementPtr) appliedFunction.parameters.get(0); - if (func.isPresent()) + Set classesThatNeedTypeFixing = Sets.fixedSize.of( + "meta::pure::tds::BasicColumnSpecification", + "BasicColumnSpecification", + "meta::pure::tds::TdsOlapRank", + "TdsOlapRank" + ); + if (classesThatNeedTypeFixing.contains(packageableElementPtr.fullPath)) { - Lambda l = func.get(); + Collection collection = (Collection) appliedFunction.parameters.get(2); + Optional func = ListIterate.detectOptional(collection.values, x -> ((CString) ((KeyExpression) x).key).value.equals("func")) + .map(KeyExpression.class::cast) + .map(x -> x.expression) + .filter(Lambda.class::isInstance) + .map(Lambda.class::cast) + .filter(x -> x.parameters.size() == 1); - PackageableType rawType = new PackageableType(type.fullPath); - rawType.sourceInformation = type.sourceInformation; - List classType = Lists.mutable.of(new GenericType(rawType, Lists.mutable.with(l.parameters.get(0).genericType))); - GenericTypeInstance generic = new GenericTypeInstance(new GenericType(new PackageableType("meta::pure::metamodel::type::Class"), classType)); - appliedFunction.parameters.set(0, generic); + if (func.isPresent()) + { + Lambda l = func.get(); + PackageableType rawType = new PackageableType(packageableElementPtr.fullPath); + rawType.sourceInformation = packageableElementPtr.sourceInformation; + List classType = Lists.mutable.of(new GenericType(rawType, Lists.mutable.with(l.parameters.get(0).genericType))); + GenericTypeInstance generic = new GenericTypeInstance(new GenericType(new PackageableType("meta::pure::metamodel::type::Class"), classType)); + appliedFunction.parameters.set(0, generic); + } } } + // Backward compatibility ------------------------------------------------------------------- } - // Backward compatibility ------------------------------------------------------------------- return appliedFunction; } } diff --git a/legend-engine-core/legend-engine-core-shared/legend-engine-shared-core/src/main/java/org/finos/legend/engine/shared/core/ObjectMapperFactory.java b/legend-engine-core/legend-engine-core-shared/legend-engine-shared-core/src/main/java/org/finos/legend/engine/shared/core/ObjectMapperFactory.java index ead31e1cc3b..ba623662613 100644 --- a/legend-engine-core/legend-engine-core-shared/legend-engine-shared-core/src/main/java/org/finos/legend/engine/shared/core/ObjectMapperFactory.java +++ b/legend-engine-core/legend-engine-core-shared/legend-engine-shared-core/src/main/java/org/finos/legend/engine/shared/core/ObjectMapperFactory.java @@ -46,4 +46,9 @@ public static ObjectMapper getNewStandardObjectMapperWithPureProtocolExtensionSu { return withStandardConfigurations(PureProtocolObjectMapperFactory.withPureProtocolExtensions(new ObjectMapper())); } + + public static ObjectMapper getNewStandardObjectMapperWithPureProtocolConverterSupports() + { + return withStandardConfigurations(PureProtocolObjectMapperFactory.withPureProtocolConverter(new ObjectMapper())); + } }