Skip to content

Commit

Permalink
Updates for unit/measure fixes (finos#3074)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevin-m-knight-gs authored Sep 6, 2024
1 parent 25cf503 commit 3316650
Show file tree
Hide file tree
Showing 11 changed files with 184 additions and 184 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1395,9 +1395,18 @@ private void runShouldPassTestCase(String testName, String expectedType, String

private void assertException(PureException e, String expectedInfo)
{
String info = e.getInfo();
Assert.assertEquals(expectedInfo, info);
// The cause of the exception should be considered the root level fromJson call so that it contains all of the information about the nested JSON structure.
Assert.assertEquals(e.getInfo(), e.getOriginatingPureException().getInfo());
Assert.assertEquals(expectedInfo, e.getInfo());
PureException originatingException = e.getOriginatingPureException();
if (originatingException != e)
{
String originatingInfo = e.getOriginatingPureException().getInfo();
if (!info.endsWith(originatingInfo))
{
Assert.fail("Expected exception info to end with \"" + originatingInfo + "\", got \"" + info + "\"");
}
}
}

private void assertFailsExecution(String testSource, String testFunction, String expectedExceptionMessage)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ public void testSerializationClassWithUnitInstanceAsPropertyNotRemoveOptionalPro
}

@Test
public void testSerializationKilogramTypeAsPackageableElement()
public void testSerializationUnitAsType()
{
String massDefinition =
"Measure pkg::Mass\n" +
Expand All @@ -342,6 +342,29 @@ public void testSerializationKilogramTypeAsPackageableElement()
assertJsonEquals("\"pkg::Mass~Kilogram\"", json);
}

@Test
public void testSerializationMeasureAsType()
{
String massDefinition =
"Measure pkg::Mass\n" +
"{\n" +
" *Gram: x -> $x;\n" +
" Kilogram: x -> $x*1000;\n" +
" Pound: x -> $x*453.59;\n" +
"}";

compileTestSource("fromString.pure",
"import pkg::*;\n" +
massDefinition +
"function testSerializeKilogramType():Any[*]\n" +
"{\n" +
" let res = Mass->meta::json::toJsonBeta(^meta::json::JSONSerializationConfig(typeKeyName='__TYPE', serializePackageableElementName=true));\n" +
"}\n");
CoreInstance result = execute("testSerializeKilogramType():Any[*]");
String json = PrimitiveUtilities.getStringValue(result.getValueForMetaPropertyToOne(M3Properties.values));
assertJsonEquals("\"pkg::Mass\"", json);
}

private void assertJsonEquals(String expectedJson, String actualJson)
{
Object expected;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,39 +18,41 @@
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.factory.Maps;
import org.eclipse.collections.api.list.MutableList;
import org.finos.legend.pure.generated.CoreGen;
import org.finos.legend.pure.m3.coreinstance.meta.pure.functions.collection.Pair;
import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Any;
import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class;
import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.ConstraintsOverride;
import org.finos.legend.pure.m3.exception.PureExecutionException;
import org.finos.legend.pure.m3.execution.ExecutionSupport;
import org.finos.legend.pure.m3.navigation.PackageableElement.PackageableElement;
import org.finos.legend.pure.m3.navigation.measure.Measure;
import org.finos.legend.pure.m4.coreinstance.CoreInstance;
import org.finos.legend.pure.m4.coreinstance.SourceInformation;
import org.finos.legend.pure.runtime.java.compiled.execution.CompiledExecutionSupport;
import org.finos.legend.pure.runtime.java.compiled.generation.JavaPackageAndImportBuilder;
import org.finos.legend.pure.runtime.java.compiled.generation.processors.support.CompiledSupport;
import org.finos.legend.pure.runtime.java.compiled.generation.processors.support.Pure;
import org.finos.legend.pure.runtime.java.compiled.generation.processors.type.measureUnit.UnitProcessor;
import org.finos.legend.pure.runtime.java.extension.external.json.compiled.JsonNativeImplementation;
import org.finos.legend.pure.runtime.java.extension.external.json.compiled.natives.JsonParserHelper;
import org.finos.legend.pure.runtime.java.extension.external.json.shared.JsonDeserializationCache;
import org.finos.legend.pure.runtime.java.extension.external.json.shared.JsonDeserializationContext;
import org.finos.legend.pure.runtime.java.extension.external.json.shared.JsonDeserializer;
import org.finos.legend.pure.runtime.java.extension.external.shared.conversion.ObjectFactory;

import java.lang.reflect.Method;
import java.util.Map;

public class JsonGen
{
@Deprecated
public static <T> T fromJsonDeprecated(String json, org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class<T> clazz, Root_meta_json_JSONDeserializationConfig config, SourceInformation si, ExecutionSupport es)
public static <T> T fromJsonDeprecated(String json, Class<T> clazz, Root_meta_json_JSONDeserializationConfig config, SourceInformation si, ExecutionSupport es)
{
java.lang.Class c = ((CompiledExecutionSupport) es).getClassCache().getIfAbsentPutInterfaceForType(clazz);
T obj = (T) JsonParserHelper.fromJson(json, c, "", "", ((CompiledExecutionSupport) es).getMetadataAccessor(), ((CompiledExecutionSupport) es).getClassLoader(), si, config._typeKeyName(), config._failOnUnknownProperties(), config._constraintsHandler(), es);
return (T) Pure.handleValidation(true, obj, si, es);
}

public static String toJson(Object pureObject, Root_meta_json_JSONSerializationConfig jsonConfig, final SourceInformation si, final ExecutionSupport es)
public static String toJson(Object pureObject, Root_meta_json_JSONSerializationConfig jsonConfig, SourceInformation si, ExecutionSupport es)
{
return toJson(CompiledSupport.toPureCollection(pureObject), jsonConfig, si, es);
}
Expand All @@ -70,40 +72,45 @@ private static String toJson(RichIterable<?> pureObject, Root_meta_json_JSONSeri
RichIterable<? extends CoreInstance> encryptionStereotypes = jsonConfig._encryptionStereotypes();
RichIterable<? extends CoreInstance> decryptionStereotypes = jsonConfig._decryptionStereotypes();

return org.finos.legend.pure.runtime.java.extension.external.json.compiled.JsonNativeImplementation._toJson(pureObject, si, es, typeKeyName, includeType, fullyQualifiedTypePath, serializeQualifiedProperties, dateTimeFormat, serializePackageableElementName, removePropertiesWithEmptyValues, serializeMultiplicityAsNumber, encryptionKey, decryptionKey, encryptionStereotypes, decryptionStereotypes);
return JsonNativeImplementation._toJson(pureObject, si, es, typeKeyName, includeType, fullyQualifiedTypePath, serializeQualifiedProperties, dateTimeFormat, serializePackageableElementName, removePropertiesWithEmptyValues, serializeMultiplicityAsNumber, encryptionKey, decryptionKey, encryptionStereotypes, decryptionStereotypes);
}

public static <T> T fromJson(String json, org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class<T> clazz, Root_meta_json_JSONDeserializationConfig config, final SourceInformation si, final ExecutionSupport es)
public static <T> T fromJson(String json, Class<T> clazz, Root_meta_json_JSONDeserializationConfig config, SourceInformation si, ExecutionSupport es)
{
final ConstraintsOverride constraintsHandler = config._constraintsHandler();
final RichIterable<? extends Pair<? extends String, ? extends String>> _typeLookup = config._typeLookup();
return _fromJson(json, clazz, config._typeKeyName(), config._failOnUnknownProperties(), si, es, constraintsHandler, _typeLookup);
return _fromJson(json, clazz, config._typeKeyName(), config._failOnUnknownProperties(), si, es, config._constraintsHandler(), config._typeLookup());
}

public static <T> T _fromJson(String json, org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class<T> clazz, String _typeKeyName, boolean _failOnUnknownProperties, final SourceInformation si, final ExecutionSupport es, final ConstraintsOverride constraintsHandler, RichIterable<? extends Pair<? extends String, ? extends String>> _typeLookup)
public static <T> T _fromJson(String json, Class<T> clazz, String _typeKeyName, boolean _failOnUnknownProperties, SourceInformation si, ExecutionSupport es, ConstraintsOverride constraintsHandler, RichIterable<? extends Pair<? extends String, ? extends String>> _typeLookup)
{
return _fromJson(json, clazz, _typeKeyName, _failOnUnknownProperties, si, (CompiledExecutionSupport) es, constraintsHandler, _typeLookup);
}

@SuppressWarnings("unchecked")
public static <T> T _fromJson(String json, Class<T> clazz, String _typeKeyName, boolean _failOnUnknownProperties, final SourceInformation si, final CompiledExecutionSupport es, final ConstraintsOverride constraintsHandler, RichIterable<? extends Pair<? extends String, ? extends String>> _typeLookup)
{
String targetClassName = JavaPackageAndImportBuilder.buildInterfaceReferenceFromType(clazz);
try
{
((CompiledExecutionSupport) es).getClassLoader().loadClass(targetClassName);
es.getClassLoader().loadClass(targetClassName);
}
catch (ClassNotFoundException e)
{
throw new RuntimeException("Unable to find class " + targetClassName, e);
}


Map<String, org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class> typeLookup = Maps.mutable.empty();
Map<String, Class> typeLookup = Maps.mutable.empty();
for (Pair<? extends String, ? extends String> pair : _typeLookup)
{
typeLookup.put(pair._first(), ((CompiledExecutionSupport) es).getMetadataAccessor().getClass("Root::" + pair._second()));
typeLookup.put(pair._first(), es.getMetadataAccessor().getClass("Root::" + pair._second()));
}

return (T) JsonDeserializer.fromJson(json, (org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class<? extends Any>) clazz, new JsonDeserializationContext(new JsonDeserializationCache(), si, ((CompiledExecutionSupport) es).getProcessorSupport(), _typeKeyName, typeLookup, _failOnUnknownProperties, new ObjectFactory()
return (T) JsonDeserializer.fromJson(json, (Class<? extends Any>) clazz, new JsonDeserializationContext(new JsonDeserializationCache(), si, es.getProcessorSupport(), _typeKeyName, typeLookup, _failOnUnknownProperties, new ObjectFactory()
{
public <U extends Any> U newObject(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class<U> clazz, Map<String, RichIterable<?>> properties)
@Override
public <U extends Any> U newObject(Class<U> clazz, Map<String, RichIterable<?>> properties)
{
MutableList<Root_meta_pure_functions_lang_KeyValue> keyValues = Lists.mutable.empty();
MutableList<Root_meta_pure_functions_lang_KeyValue> keyValues = Lists.mutable.ofInitialCapacity(properties.size());
for (Map.Entry<String, RichIterable<?>> property : properties.entrySet())
{
Root_meta_pure_functions_lang_KeyValue keyValue = new Root_meta_pure_functions_lang_KeyValue_Impl("Anonymous");
Expand All @@ -114,27 +121,23 @@ public <U extends Any> U newObject(org.finos.legend.pure.m3.coreinstance.meta.pu
}
keyValues.add(keyValue);
}
U result = (U) org.finos.legend.pure.generated.CoreGen.newObject(clazz, keyValues, null, null, null, null, null, null, es);
U result = (U) CoreGen.newObject(clazz, keyValues, null, null, null, null, null, null, es);
result._elementOverride(constraintsHandler);
return (U) Pure.handleValidation(true, result, si, es);
}

public <T extends Any> T newUnitInstance(CoreInstance propertyType, String unitTypeString, Number unitValue) throws Exception
@Override
public <T extends Any> T newUnitInstance(CoreInstance propertyType, String unitTypeString, Number unitValue)
{
CoreInstance unitRetrieved = ((CompiledExecutionSupport) es).getProcessorSupport().package_getByUserPath(unitTypeString);
if (!((CompiledExecutionSupport) es).getProcessorSupport().type_subTypeOf(unitRetrieved, propertyType))
CoreInstance unitRetrieved = es.getProcessorSupport().package_getByUserPath(unitTypeString);
if (!es.getProcessorSupport().type_subTypeOf(unitRetrieved, propertyType))
{
throw new PureExecutionException("Cannot match unit type: " + unitTypeString + " as subtype of type: " + PackageableElement.getUserPathForPackageableElement(propertyType));
StringBuilder builder = new StringBuilder("Cannot match unit type: ").append(unitTypeString).append(" as subtype of type: ");
PackageableElement.writeUserPathForPackageableElement(builder, propertyType);
throw new PureExecutionException(builder.toString());
}

String unitClassName = UnitProcessor.convertToJavaCompatibleClassName(JavaPackageAndImportBuilder.buildImplUnitInstanceClassNameFromType(unitRetrieved));

java.lang.Class c = ((CompiledExecutionSupport) es).getClassLoader().loadClass("org.finos.legend.pure.generated." + unitClassName);

Method method = c.getMethod("_val", Number.class);
Object classInstance = c.getConstructor(String.class, ExecutionSupport.class).newInstance("Anonymous_NoCounter", es);
method.invoke(classInstance, unitValue);
return (T) classInstance;
return (T) CompiledSupport.newUnitInstance(unitRetrieved, unitValue, es);
}
}));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public FromJson(FunctionExecutionInterpreted functionExecution, ModelRepository
this.repository = repository;
}

@SuppressWarnings({"unchecked", "rawtypes"})
@Override
public CoreInstance execute(ListIterable<? extends CoreInstance> params, Stack<MutableMap<String, CoreInstance>> resolvedTypeParameters, Stack<MutableMap<String, CoreInstance>> resolvedMultiplicityParameters, VariableContext variableContext, CoreInstance functionExpressionToUseInStack, Profiler profiler, InstantiationContext instantiationContext, ExecutionSupport executionSupport, Context context, ProcessorSupport processorSupport) throws PureExecutionException
{
Expand Down Expand Up @@ -107,18 +108,21 @@ public <T extends Any> T newObject(Class<T> clazz, Map<String, RichIterable<?>>
return (T) DefaultConstraintHandler.handleConstraints(clazz, value, si, functionExecution, resolvedTypeParameters, resolvedMultiplicityParameters, variableContext, functionExpressionToUseInStack, profiler, instantiationContext, executionSupport);
}

@Override
public <T extends Any> T newUnitInstance(CoreInstance propertyType, String unitTypeString, Number unitValue)
{
CoreInstance retrievedUnit = processorSupport.package_getByUserPath(unitTypeString);
if (!processorSupport.type_subTypeOf(retrievedUnit, propertyType))
{
throw new PureExecutionException("Cannot match unit type: " + unitTypeString + " as subtype of type: " + PackageableElement.getUserPathForPackageableElement(propertyType));
StringBuilder builder = new StringBuilder("Cannot match unit type: ").append(unitTypeString).append(" as subtype of type: ");
PackageableElement.writeUserPathForPackageableElement(builder, propertyType);
throw new PureExecutionException(builder.toString());
}

ListIterable<CoreInstance> params = Lists.immutable.with(
ValueSpecificationBootstrap.wrapValueSpecification(retrievedUnit, false, processorSupport),
NumericUtilities.toPureNumberValueExpression(unitValue, false, repository, processorSupport));
return (T) new NewUnit(functionExecution, repository).execute(params, resolvedTypeParameters, resolvedMultiplicityParameters, variableContext, functionExpressionToUseInStack, profiler, instantiationContext, executionSupport, context, processorSupport);
return (T) new NewUnit(repository).execute(params, resolvedTypeParameters, resolvedMultiplicityParameters, variableContext, functionExpressionToUseInStack, profiler, instantiationContext, executionSupport, context, processorSupport);
}
}));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ public interface ObjectFactory
{
<T extends Any> T newObject(Class<T> clazz, Map<String, RichIterable<?>> properties);

<T extends Any> T newUnitInstance(CoreInstance unit, String unitTypeString, Number unitValue) throws Exception;
<T extends Any> T newUnitInstance(CoreInstance unit, String unitTypeString, Number unitValue);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@

public abstract class UnitConversion<F, T> implements Conversion<F, T>
{
protected static final String UNIT_KEY_NAME = "unit";
protected static final String VALUE_KEY_NAME = "value";
protected static final String UNIT_ID_KEY_NAME = "unitId";
protected static final String EXPONENT_VALUE_KEY_NAME = "exponentValue";

protected final CoreInstance type;
protected final String unitKeyName = "unit";
protected final String valueKeyName = "value";

public UnitConversion(CoreInstance type)
{
Expand Down
Loading

0 comments on commit 3316650

Please sign in to comment.