Skip to content

Commit

Permalink
Introduce mechanism to do protocol conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelbey committed Nov 25, 2024
1 parent 1aa758e commit 925c37f
Show file tree
Hide file tree
Showing 9 changed files with 419 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand All @@ -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
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<TDSRow>(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<meta::pure::metamodel::type::Any|1..*>[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<meta::pure::metamodel::type::Any|1..*>[1]): Any[1]\n" +
"{\n" +
" 1\n" +
"}\n",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -180,4 +195,133 @@ public Map<java.lang.Class<? extends PackageableElement>, String> getExtraProtoc
.withKeyValue(SectionIndex.class, "meta::pure::metamodel::section::SectionIndex")
.withKeyValue(RelationalMapper.class, "meta::relational::metamodel::RelationalMapper");
}

@Override
public List<ProtocolConverter<?>> getConverterDeserializers()
{
return Lists.fixedSize.with(
new ProtocolConverter<>(new ResultVariableWithMissingTypeConverter()),
new ProtocolConverter<>(
Lists.mutable.with(
new BasicColumnSpecificationToColFunctionConverter(),
new TdsOlapRankToColFunctionConverter()))
);
}

private static class ResultVariableWithMissingTypeConverter extends StdConverter<Variable, Variable>
{
@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<AppliedFunction, AppliedFunction>
{
@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<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);

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);

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<AppliedFunction, AppliedFunction>
{
@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<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 (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;
}
}
}
Loading

0 comments on commit 925c37f

Please sign in to comment.