From ef7ddf414d52c28017adcbcca7737a54e8ee627a Mon Sep 17 00:00:00 2001 From: Rafael Bey Date: Thu, 28 Nov 2024 12:22:19 -0500 Subject: [PATCH] Protocol converter public api to not depend on jackson --- .../pure/v1/CorePureProtocolExtension.java | 193 ++++++++---------- .../v1/PureProtocolObjectMapperFactory.java | 51 ++++- .../pure/v1/extension/ProtocolConverter.java | 93 ++++++--- 3 files changed, 197 insertions(+), 140 deletions(-) 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 0323e631578..911c51c5474 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,7 +14,6 @@ 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; @@ -203,11 +202,9 @@ public Map, String> getExtraProtoc public List> getProtocolConverters() { return Lists.fixedSize.with( - new ProtocolConverter<>(new ResultVariableWithMissingTypeConverter()), - new ProtocolConverter<>( - Lists.mutable.with( - new BasicColumnSpecificationToColFunctionConverter(), - new TdsOlapRankToColFunctionConverter())) + ProtocolConverter.converter(Variable.class, CorePureProtocolExtension::fixVariableOfResultTypeWithMissingTypeAndMultiplicityArgument), + ProtocolConverter.converter(AppliedFunction.class, CorePureProtocolExtension::convertNewBasicColumnSpecificationToColFunctionCall), + ProtocolConverter.converter(AppliedFunction.class, CorePureProtocolExtension::convertNewTdsOlapRankToFuncFunctionCall) ); } @@ -215,151 +212,139 @@ public List> getProtocolConverters() * Converts/fix variables of type Result to ensure they have the type and multiplicity * Result[1] -> Result<Any|*>[1] */ - private static class ResultVariableWithMissingTypeConverter extends StdConverter + private static Variable fixVariableOfResultTypeWithMissingTypeAndMultiplicityArgument(Variable variable) { - @Override - public Variable convert(Variable variable) + if (variable.genericType != null && variable.genericType.rawType instanceof PackageableType) { - 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) { - 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); - } + 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; } + return variable; } /** * Convert the usage of BasicColumnSpecification to the equivalent function * ^BasicColumnSpecification(...) == col(...) */ - private static class BasicColumnSpecificationToColFunctionConverter extends StdConverter + private static AppliedFunction convertNewBasicColumnSpecificationToColFunctionCall(AppliedFunction appliedFunction) { - @Override - public AppliedFunction convert(AppliedFunction appliedFunction) + if (appliedFunction.function.equals("new")) { - if (appliedFunction.function.equals("new")) - { - PackageableElementPtr type; + PackageableElementPtr type; - if (appliedFunction.parameters.get(0) instanceof GenericTypeInstance) - { - GenericTypeInstance typeInstance = (GenericTypeInstance) appliedFunction.parameters.get(0); - if (typeInstance.genericType.typeArguments.size() >= 1 && typeInstance.genericType.typeArguments.get(0).rawType instanceof PackageableType) - { - type = (PackageableType) typeInstance.genericType.typeArguments.get(0).rawType; - } - else - { - return appliedFunction; - } - } - else if (appliedFunction.parameters.get(0) instanceof PackageableElementPtr) + if (appliedFunction.parameters.get(0) instanceof GenericTypeInstance) + { + GenericTypeInstance typeInstance = (GenericTypeInstance) appliedFunction.parameters.get(0); + if (typeInstance.genericType.typeArguments.size() >= 1 && typeInstance.genericType.typeArguments.get(0).rawType instanceof PackageableType) { - type = (PackageableElementPtr) appliedFunction.parameters.get(0); + type = (PackageableType) typeInstance.genericType.typeArguments.get(0).rawType; } else { return appliedFunction; } + } + else if (appliedFunction.parameters.get(0) instanceof PackageableElementPtr) + { + type = (PackageableElementPtr) appliedFunction.parameters.get(0); + } + else + { + return appliedFunction; + } - Set classesThatNeedTypeFixing = Sets.fixedSize.of( - "meta::pure::tds::BasicColumnSpecification", - "BasicColumnSpecification" - ); + 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); + 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 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); + 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); - appliedFunction.function = "meta::pure::tds::col"; - appliedFunction.fControl = "meta::pure::tds::col_Function_1__String_1__BasicColumnSpecification_1_"; - appliedFunction.parameters = Stream.of(func, name, doc).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList()); - if (appliedFunction.parameters.size() == 3) - { - appliedFunction.fControl = "meta::pure::tds::col_Function_1__String_1__String_1__BasicColumnSpecification_1_"; - } + appliedFunction.function = "meta::pure::tds::col"; + appliedFunction.fControl = "meta::pure::tds::col_Function_1__String_1__BasicColumnSpecification_1_"; + appliedFunction.parameters = Stream.of(func, name, doc).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList()); + if (appliedFunction.parameters.size() == 3) + { + appliedFunction.fControl = "meta::pure::tds::col_Function_1__String_1__String_1__BasicColumnSpecification_1_"; } } - return appliedFunction; } + return appliedFunction; } /** * Convert the usage of TdsOlapRank to the equivalent function * ^TdsOlapRank(...) == func(...) */ - private static class TdsOlapRankToColFunctionConverter extends StdConverter + private static AppliedFunction convertNewTdsOlapRankToFuncFunctionCall(AppliedFunction appliedFunction) { - @Override - public AppliedFunction convert(AppliedFunction appliedFunction) + if (appliedFunction.function.equals("new")) { - if (appliedFunction.function.equals("new")) - { - PackageableElementPtr type; + PackageableElementPtr type; - if (appliedFunction.parameters.get(0) instanceof GenericTypeInstance) - { - GenericTypeInstance typeInstance = (GenericTypeInstance) appliedFunction.parameters.get(0); - if (typeInstance.genericType.typeArguments.size() >= 1 && typeInstance.genericType.typeArguments.get(0).rawType instanceof PackageableType) - { - type = (PackageableType) typeInstance.genericType.typeArguments.get(0).rawType; - } - else - { - return appliedFunction; - } - } - else if (appliedFunction.parameters.get(0) instanceof PackageableElementPtr) + if (appliedFunction.parameters.get(0) instanceof GenericTypeInstance) + { + GenericTypeInstance typeInstance = (GenericTypeInstance) appliedFunction.parameters.get(0); + if (typeInstance.genericType.typeArguments.size() >= 1 && typeInstance.genericType.typeArguments.get(0).rawType instanceof PackageableType) { - type = (PackageableElementPtr) appliedFunction.parameters.get(0); + type = (PackageableType) typeInstance.genericType.typeArguments.get(0).rawType; } else { return appliedFunction; } + } + else if (appliedFunction.parameters.get(0) instanceof PackageableElementPtr) + { + type = (PackageableElementPtr) appliedFunction.parameters.get(0); + } + else + { + return appliedFunction; + } - Set classesThatNeedTypeFixing = Sets.fixedSize.of( - "meta::pure::tds::TdsOlapRank", - "TdsOlapRank" - ); + 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 (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); - appliedFunction.function = "meta::pure::tds::func"; - appliedFunction.fControl = "meta::pure::tds::func_FunctionDefinition_1__TdsOlapRank_1_"; - appliedFunction.parameters = Stream.of(func).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList()); - } + appliedFunction.function = "meta::pure::tds::func"; + appliedFunction.fControl = "meta::pure::tds::func_FunctionDefinition_1__TdsOlapRank_1_"; + appliedFunction.parameters = Stream.of(func).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList()); } - return appliedFunction; } + 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 9c076d282a2..0f3c0d6f781 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 @@ -32,7 +32,9 @@ 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 com.fasterxml.jackson.databind.util.Converter; import java.util.Collection; import java.util.List; import java.util.Map; @@ -44,7 +46,6 @@ import java.util.stream.Collectors; import org.eclipse.collections.api.block.function.Function0; import org.eclipse.collections.api.factory.Maps; -import org.eclipse.collections.impl.factory.Lists; import org.eclipse.collections.impl.utility.LazyIterate; import org.finos.legend.engine.protocol.pure.v1.extension.ProtocolConverter; import org.finos.legend.engine.protocol.pure.v1.extension.ProtocolSubTypeInfo; @@ -187,10 +188,10 @@ public static ObjectMapper withPureProtocolConverter(ObjectMapper objectMapper) .flatMap(List::stream) .collect(Collectors.toList()); - Map> converterByType = protocolConverters + Map, ProtocolConverter> converterByType = protocolConverters .stream() .collect(Collectors.toMap( - x -> x.getInputType(objectMapper.getTypeFactory()), + ProtocolConverter::getType, Function.identity(), (a, b) -> ProtocolConverter.merge((ProtocolConverter) a, (ProtocolConverter) b)) ); @@ -207,9 +208,9 @@ public static ObjectMapper withPureProtocolConverter(ObjectMapper objectMapper) private static class ConverterHandlerInstantiator extends HandlerInstantiator { - private final Map> converterByType; + private final Map, ProtocolConverter> converterByType; - public ConverterHandlerInstantiator(Map> converterByType) + public ConverterHandlerInstantiator(Map, ProtocolConverter> converterByType) { this.converterByType = converterByType; } @@ -217,11 +218,11 @@ public ConverterHandlerInstantiator(Map> converte @Override public JsonDeserializer deserializerInstance(DeserializationConfig config, Annotated annotated, Class deserClass) { - ProtocolConverter converter = this.converterByType.get(annotated.getType()); + ProtocolConverter converter = this.converterByType.get(annotated.getRawType()); if (converter != null) { JsonDeserializer deserializer = (JsonDeserializer) ClassUtil.createInstance(deserClass, config.canOverrideAccessModifiers()); - return new StdDelegatingDeserializer(converter, annotated.getType(), deserializer); + return new StdDelegatingDeserializer(new JacksonProtocolConverter<>(converter), annotated.getType(), deserializer); } return null; } @@ -253,9 +254,9 @@ public TypeIdResolver typeIdResolverInstance(MapperConfig config, Annotated a private static class ConverterBeanDeserializerModifier extends BeanDeserializerModifier { - private final Map> converterByType; + private final Map, ProtocolConverter> converterByType; - public ConverterBeanDeserializerModifier(Map> converterByType) + public ConverterBeanDeserializerModifier(Map, ProtocolConverter> converterByType) { this.converterByType = converterByType; } @@ -263,12 +264,40 @@ public ConverterBeanDeserializerModifier(Map> con @Override public JsonDeserializer modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer deserializer) { - ProtocolConverter converter = this.converterByType.get(beanDesc.getType()); + ProtocolConverter converter = this.converterByType.get(beanDesc.getBeanClass()); if (converter != null) { - return new StdDelegatingDeserializer(converter, beanDesc.getType(), deserializer); + return new StdDelegatingDeserializer(new JacksonProtocolConverter<>(converter), beanDesc.getType(), deserializer); } return deserializer; } } + + private static class JacksonProtocolConverter implements Converter + { + private final ProtocolConverter converter; + + private JacksonProtocolConverter(ProtocolConverter converter) + { + this.converter = converter; + } + + @Override + public T convert(T value) + { + return this.converter.convert(value); + } + + @Override + public JavaType getInputType(TypeFactory typeFactory) + { + return typeFactory.constructType(this.converter.getType()); + } + + @Override + public JavaType getOutputType(TypeFactory typeFactory) + { + return typeFactory.constructType(this.converter.getType()); + } + } } 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 index 061932e5bbd..5cda7bc6f44 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/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 @@ -15,49 +15,92 @@ 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 org.eclipse.collections.api.list.MutableList; +import java.util.Objects; +import java.util.function.Function; import org.eclipse.collections.impl.factory.Lists; import org.eclipse.collections.impl.utility.ListIterate; -public class ProtocolConverter implements Converter +public abstract class ProtocolConverter { - private final List> converters; - - public ProtocolConverter(Converter converters) + private ProtocolConverter() { - this(Lists.fixedSize.of(converters)); - } - public ProtocolConverter(List> converters) - { - this.converters = converters; } - @Override - public JavaType getInputType(TypeFactory typeFactory) + public abstract T convert(T value); + + public abstract Class getType(); + + public static ProtocolConverter converter(Class type, Function func) { - return this.converters.get(0).getInputType(typeFactory); + return new DefaultProtocolConverter<>(type, func); } - @Override - public JavaType getOutputType(TypeFactory typeFactory) + public static ProtocolConverter merge(ProtocolConverter one, ProtocolConverter two) { - return this.converters.get(0).getOutputType(typeFactory); + return new MergedProtocolConverter<>(Objects.requireNonNull(one), Objects.requireNonNull(two)); } - @Override - public T convert(T value) + private static class MergedProtocolConverter extends ProtocolConverter { - return ListIterate.injectInto(value, this.converters, (t, c) -> c.convert(t)); + private final List> converters = Lists.mutable.empty(); + + public MergedProtocolConverter(ProtocolConverter one, ProtocolConverter two) + { + if (one instanceof MergedProtocolConverter) + { + this.converters.addAll(((MergedProtocolConverter) one).converters); + } + else + { + this.converters.add((DefaultProtocolConverter) one); + } + + if (two instanceof MergedProtocolConverter) + { + this.converters.addAll(((MergedProtocolConverter) two).converters); + } + else + { + this.converters.add((DefaultProtocolConverter) two); + } + } + + @Override + public T convert(T value) + { + return ListIterate.injectInto(value, this.converters, (v, c) -> c.convert(v)); + } + + @Override + public Class getType() + { + return this.converters.get(0).type; + } } - public static ProtocolConverter merge(ProtocolConverter one, ProtocolConverter two) + private static class DefaultProtocolConverter extends ProtocolConverter { - MutableList> allConverters = Lists.mutable.withAll(one.converters).withAll(two.converters); - return new ProtocolConverter<>(allConverters); + private final Class type; + private final Function converter; + + public DefaultProtocolConverter(Class type, Function converter) + { + this.type = type; + this.converter = converter; + } + + @Override + public T convert(T value) + { + return this.converter.apply(value); + } + + @Override + public Class getType() + { + return this.type; + } } }