Skip to content

Commit

Permalink
Protocol converter public api to not depend on jackson
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelbey committed Nov 28, 2024
1 parent 4e2cfa7 commit ef7ddf4
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -203,163 +202,149 @@ public Map<java.lang.Class<? extends PackageableElement>, String> getExtraProtoc
public List<ProtocolConverter<?>> 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)
);
}

/**
* Converts/fix variables of type Result to ensure they have the type and multiplicity
* Result[1] -> Result&lt;Any|*&gt;[1]
*/
private static class ResultVariableWithMissingTypeConverter extends StdConverter<Variable, Variable>
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<AppliedFunction, AppliedFunction>
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<String> classesThatNeedTypeFixing = Sets.fixedSize.of(
"meta::pure::tds::BasicColumnSpecification",
"BasicColumnSpecification"
);
Set<String> classesThatNeedTypeFixing = Sets.fixedSize.of(
"meta::pure::tds::BasicColumnSpecification",
"BasicColumnSpecification"
);

if (classesThatNeedTypeFixing.contains(type.fullPath))
{
Collection collection = (Collection) appliedFunction.parameters.get(2);
Optional<Lambda> 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<Lambda> 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<CString> 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<CString> 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<CString> 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<CString> 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<AppliedFunction, AppliedFunction>
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<String> classesThatNeedTypeFixing = Sets.fixedSize.of(
"meta::pure::tds::TdsOlapRank",
"TdsOlapRank"
);
Set<String> classesThatNeedTypeFixing = Sets.fixedSize.of(
"meta::pure::tds::TdsOlapRank",
"TdsOlapRank"
);

if (classesThatNeedTypeFixing.contains(type.fullPath))
{
Collection collection = (Collection) appliedFunction.parameters.get(2);
Optional<Lambda> 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<Lambda> 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -187,10 +188,10 @@ public static ObjectMapper withPureProtocolConverter(ObjectMapper objectMapper)
.flatMap(List::stream)
.collect(Collectors.toList());

Map<JavaType, ProtocolConverter<?>> converterByType = protocolConverters
Map<Class<?>, ProtocolConverter<?>> converterByType = protocolConverters
.stream()
.collect(Collectors.toMap(
x -> x.getInputType(objectMapper.getTypeFactory()),
ProtocolConverter::getType,
Function.identity(),
(a, b) -> ProtocolConverter.merge((ProtocolConverter<Object>) a, (ProtocolConverter<Object>) b))
);
Expand All @@ -207,21 +208,21 @@ public static ObjectMapper withPureProtocolConverter(ObjectMapper objectMapper)

private static class ConverterHandlerInstantiator extends HandlerInstantiator
{
private final Map<JavaType, ProtocolConverter<?>> converterByType;
private final Map<Class<?>, ProtocolConverter<?>> converterByType;

public ConverterHandlerInstantiator(Map<JavaType, ProtocolConverter<?>> converterByType)
public ConverterHandlerInstantiator(Map<Class<?>, ProtocolConverter<?>> converterByType)
{
this.converterByType = converterByType;
}

@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;
}
Expand Down Expand Up @@ -253,22 +254,50 @@ public TypeIdResolver typeIdResolverInstance(MapperConfig<?> config, Annotated a

private static class ConverterBeanDeserializerModifier extends BeanDeserializerModifier
{
private final Map<JavaType, ProtocolConverter<?>> converterByType;
private final Map<Class<?>, ProtocolConverter<?>> converterByType;

public ConverterBeanDeserializerModifier(Map<JavaType, ProtocolConverter<?>> converterByType)
public ConverterBeanDeserializerModifier(Map<Class<?>, ProtocolConverter<?>> converterByType)
{
this.converterByType = converterByType;
}

@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<T> implements Converter<T, T>
{
private final ProtocolConverter<T> converter;

private JacksonProtocolConverter(ProtocolConverter<T> 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());
}
}
}
Loading

0 comments on commit ef7ddf4

Please sign in to comment.