Skip to content

Commit

Permalink
Fixed metadata on deep path operator (#796)
Browse files Browse the repository at this point in the history
* Fixed metadata on deep path operator

* Cleaned
  • Loading branch information
SimonCockx authored Jul 25, 2024
1 parent 0f7f74a commit 9492ad2
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 32 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ plugin.xml_gen
.checkstyle
.classpath
rosetta-profiling/dependency-reduced-pom.xml
rosetta-profiling/reports/

**/.settings
**/src-gen/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class DeepPathUtilGenerator {
}

private def JavaStatementBuilder deepFeatureToStatement(Data choiceType, JavaVariable inputParameter, Attribute deepFeature, Map<Attribute, Map<Attribute, Boolean>> recursiveDeepFeaturesMap, JavaScope scope) {
val deepFeatureHasMeta = !deepFeature.metaAnnotations.empty
val attrs = choiceType.allNonOverridesAttributes
val receiverType = new RDataType(choiceType)
var JavaStatementBuilder acc = JavaExpression.NULL
Expand All @@ -122,13 +123,13 @@ class DeepPathUtilGenerator {
} else {
(attrType as RDataType).data.allNonOverridesAttributes.findFirst[name.equals(deepFeature.name)]
}
attrVar.featureCall(attrType, actualFeature, needsToGoDownDeeper, scope, true)
attrVar.featureCall(attrType, actualFeature, needsToGoDownDeeper, scope, !deepFeatureHasMeta)
}
new JavaIfThenElseBuilder(it, deepFeatureExpr, currAcc, typeUtil)
]
]
}
val resultType = deepFeature.toExpandedAttribute.toMultiRegularJavaType
val resultType = deepFeature.toExpandedAttribute.toMultiMetaOrRegularJavaType
acc.addCoercions(resultType, scope)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ import org.eclipse.xtend2.lib.StringConcatenationClient
import org.eclipse.xtext.EcoreUtil2

import static extension com.regnosys.rosetta.generator.java.enums.EnumHelper.convertValues
import static extension com.regnosys.rosetta.generator.util.RosettaAttributeExtensions.*
import com.regnosys.rosetta.types.RObjectFactory
import javax.inject.Inject
import com.regnosys.rosetta.rosetta.expression.RosettaConstructorExpression
Expand Down Expand Up @@ -128,7 +129,6 @@ import java.time.ZonedDateTime
import com.regnosys.rosetta.rosetta.expression.RosettaDeepFeatureCall
import com.regnosys.rosetta.rosetta.expression.DefaultOperation
import com.regnosys.rosetta.generator.java.statement.builder.JavaConditionalExpression
import com.regnosys.rosetta.rosetta.RosettaSymbol

class ExpressionGenerator extends RosettaExpressionSwitch<JavaStatementBuilder, ExpressionGenerator.Context> {

Expand Down Expand Up @@ -278,7 +278,11 @@ class ExpressionGenerator extends RosettaExpressionSwitch<JavaStatementBuilder,
}

def JavaStatementBuilder featureCall(JavaStatementBuilder receiverCode, RType receiverType, RosettaFeature feature, boolean isDeepFeature, JavaScope scope, boolean autoValue) {
val resultItemType = typeProvider.getRTypeOfFeature(feature).toJavaReferenceType
val resultItemType = if (feature instanceof Attribute && !autoValue) {
(feature as Attribute).toExpandedAttribute.toMetaOrRegularJavaType
} else {
typeProvider.getRTypeOfFeature(feature).toJavaReferenceType
}
val StringConcatenationClient right = switch (feature) {
Attribute: {
receiverType.buildMapFunc(feature, isDeepFeature, autoValue, scope)
Expand All @@ -288,7 +292,7 @@ class ExpressionGenerator extends RosettaExpressionSwitch<JavaStatementBuilder,
RosettaEnumValue:
return JavaExpression.from('''«resultItemType».«feature.convertValues»''', resultItemType)
RosettaRecordFeature:
'''.<«feature.typeCall.typeCallToRType.toJavaReferenceType»>map("«feature.name.toFirstUpper»", «recordUtil.recordFeatureToLambda(receiverType as RRecordType, feature, scope)»)'''
'''.<«resultItemType»>map("«feature.name.toFirstUpper»", «recordUtil.recordFeatureToLambda(receiverType as RRecordType, feature, scope)»)'''
default:
throw new UnsupportedOperationException("Unsupported feature type of " + feature?.class?.name)
}
Expand Down Expand Up @@ -411,7 +415,7 @@ class ExpressionGenerator extends RosettaExpressionSwitch<JavaStatementBuilder,
*/
private def StringConcatenationClient buildMapFunc(RType itemType, Attribute attribute, boolean isDeepFeature, boolean autoValue, JavaScope scope) {
val mapFunc = itemType.buildMapFuncAttribute(attribute, isDeepFeature, scope)
val resultType = if (attribute.metaAnnotations.nullOrEmpty || isDeepFeature) {
val resultType = if (attribute.metaAnnotations.nullOrEmpty) {
typeProvider.getRTypeOfSymbol(attribute).toJavaReferenceType
} else {
attribute.toMetaJavaType
Expand Down Expand Up @@ -679,7 +683,12 @@ class ExpressionGenerator extends RosettaExpressionSwitch<JavaStatementBuilder,
}

override protected caseDeepFeatureCall(RosettaDeepFeatureCall expr, Context context) {
return featureCall(expr.receiver.javaCode(MAPPER.wrapExtends(expr.receiver), context.scope), typeProvider.getRType(expr.receiver), expr.feature, true, context.scope, false)
var autoValue = true // if the attribute being referenced is WithMeta and we aren't accessing the meta fields then access the value by default
if (expr.eContainer instanceof RosettaFeatureCall &&
(expr.eContainer as RosettaFeatureCall).feature instanceof RosettaMetaType) {
autoValue = false;
}
return featureCall(expr.receiver.javaCode(MAPPER.wrapExtends(expr.receiver), context.scope), typeProvider.getRType(expr.receiver), expr.feature, true, context.scope, autoValue)
}

override protected caseFilterOperation(FilterOperation expr, Context context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,8 @@ class RosettaScopeProvider extends ImportedNamespaceAwareLocalScopeProvider {
//if an attribute has metafields then the meta names are valid in a feature call e.g. -> currency -> scheme
val feature = if (receiver instanceof RosettaFeatureCall) {
receiver.feature
} else if (receiver instanceof RosettaDeepFeatureCall) {
receiver.feature
} else if (receiver instanceof RosettaSymbolReference) {
receiver.symbol
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
package com.regnosys.rosetta.utils;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import javax.inject.Inject;

import com.google.common.collect.Iterables;
import com.regnosys.rosetta.RosettaExtensions;
import com.regnosys.rosetta.rosetta.RosettaCardinality;
import com.regnosys.rosetta.rosetta.expression.OneOfOperation;
import com.regnosys.rosetta.rosetta.expression.RosettaDeepFeatureCall;
import com.regnosys.rosetta.rosetta.expression.RosettaExpression;
import com.regnosys.rosetta.rosetta.expression.RosettaImplicitVariable;
import com.regnosys.rosetta.rosetta.simple.Attribute;
Expand All @@ -27,9 +21,7 @@

public class DeepFeatureCallUtil {
private final RosettaTypeProvider typeProvider;

private final CardinalityProvider cardinalityProvider;

private final RosettaExtensions ext;

@Inject
Expand Down Expand Up @@ -78,23 +70,13 @@ public Map<String, Attribute> findDeepFeatureMap(RDataType type) {
return result;
}
private void intersect(Map<String, Attribute> featuresMapToModify, Map<String, Attribute> otherFeatureMap) {
featuresMapToModify.entrySet().removeIf(entry -> {
String attrName = entry.getKey();
Attribute otherAttr = otherFeatureMap.get(attrName);
if (otherAttr != null) {
Attribute attr = entry.getValue();
if (match(attr, otherAttr)) {
return false;
}
}
return true;
});
intersectButRetainAttribute(featuresMapToModify, otherFeatureMap, null);
}
private void intersectButRetainAttribute(Map<String, Attribute> featuresMapToModify, Map<String, Attribute> otherFeatureMap, Attribute attributeToRetain) {
featuresMapToModify.entrySet().removeIf(entry -> {
String attrName = entry.getKey();
Attribute attr = entry.getValue();
if (attributeToRetain.equals(attr)) {
if (attr.equals(attributeToRetain)) {
return false;
}
Attribute otherAttr = otherFeatureMap.get(attrName);
Expand All @@ -105,13 +87,25 @@ private void intersectButRetainAttribute(Map<String, Attribute> featuresMapToMod
}
return true;
});
// Make sure we don't give back an attribute with metadata if not all of them have it.
for (Map.Entry<String, Attribute> e : featuresMapToModify.entrySet()) {
String name = e.getKey();
Attribute currFeature = e.getValue();
Attribute otherFeature = otherFeatureMap.get(name);
if (otherFeature != null && !Iterables.isEmpty(ext.metaAnnotations(currFeature)) && Iterables.isEmpty(ext.metaAnnotations(otherFeature))) {
e.setValue(otherFeature);
}
}
}
private void merge(Map<String, Attribute> featuresMapToModify, Map<String, Attribute> otherFeatureMap) {
otherFeatureMap.forEach((name, attr) -> {
Attribute candidate = featuresMapToModify.get(name);
if (candidate != null) {
if (!match(candidate, attr)) {
featuresMapToModify.remove(name);
} else if (!Iterables.isEmpty(ext.metaAnnotations(candidate)) && Iterables.isEmpty(ext.metaAnnotations(attr))) {
// Make sure we don't give back an attribute with metadata if not all of them have it.
featuresMapToModify.put(name, attr);
}
} else {
featuresMapToModify.put(name, attr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class FunctionGeneratorTest {
result string (1..1)
set result:
a ->> id
a ->> id -> scheme
'''.generateCode

val classes = code.compileToClasses
Expand All @@ -203,7 +203,7 @@ class FunctionGeneratorTest {
})
})

assertEquals("abc123", test.invokeFunc(String, #[aB]))
assertEquals("myScheme", test.invokeFunc(String, #[aB]))
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,32 @@ class RosettaValidatorTest implements RosettaIssueCodes {
@Inject extension ExpressionParser

@Test
def void testCannotAccessMetaFeatureAfterDeepFeatureCall() {
def void testCannotAccessUncommonMetaFeatureOfDeepFeatureCall() {
val model = '''
type A:
a string (1..1)
[metadata scheme]
type B:
a string (1..1)
type C:
a string (1..1)
[metadata scheme]
choice ABC:
A
B
C
'''.parseRosettaWithNoIssues

"abc ->> a -> scheme"
.parseExpression(#[model], #["abc ABC (1..1)"])
.assertError(ROSETTA_FEATURE_CALL, Diagnostic.LINKING_DIAGNOSTIC, "Couldn't resolve reference to RosettaFeature 'scheme'.")
}

@Test
def void testCanAccessMetaFeatureAfterDeepFeatureCall() {
val context = '''
type A:
b B (0..1)
Expand Down Expand Up @@ -60,7 +85,7 @@ class RosettaValidatorTest implements RosettaIssueCodes {

"a ->> id -> scheme"
.parseExpression(#[context], #["a A (1..1)"])
.assertError(ROSETTA_FEATURE_CALL, Diagnostic.LINKING_DIAGNOSTIC, "Couldn't resolve reference to RosettaFeature 'scheme'.")
.assertNoIssues
}

@Test
Expand Down

0 comments on commit 9492ad2

Please sign in to comment.