Skip to content

Commit

Permalink
Enum refactoring (#838)
Browse files Browse the repository at this point in the history
* Copied changes from enum-extensions branch

* Fixed static compilation errors

* Cleaned

* Cleaned

* Fixed
  • Loading branch information
SimonCockx authored Sep 16, 2024
1 parent 5802faa commit f4d4790
Show file tree
Hide file tree
Showing 28 changed files with 1,190 additions and 243 deletions.
12 changes: 5 additions & 7 deletions rosetta-lang/model/Rosetta.xcore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ package com.regnosys.rosetta.rosetta

import com.google.common.collect.Iterables
import java.util.stream.Collectors
import com.regnosys.rosetta.rosetta.simple.Annotated
import com.regnosys.rosetta.rosetta.simple.RootElement
import com.regnosys.rosetta.rosetta.simple.References
import com.regnosys.rosetta.rosetta.simple.Data
import com.regnosys.rosetta.rosetta.simple.Attribute
Expand Down Expand Up @@ -40,10 +42,6 @@ interface RosettaNamed {

interface RosettaTyped {
contains TypeCall typeCall

derived boolean isTypeInferred get {
return typeCall === null
}
}

interface RosettaFeature extends RosettaNamed {
Expand Down Expand Up @@ -132,13 +130,13 @@ class RosettaMetaType extends RosettaRootElement, RosettaTypedFeature, RosettaTy

}

class RosettaEnumeration extends RosettaRootElement, RosettaType, RosettaDefinable, References, RosettaSymbol {
refers RosettaEnumeration superType
class RosettaEnumeration extends RootElement, RosettaType, RosettaDefinable, References, RosettaSymbol {
refers RosettaEnumeration parent
contains RosettaSynonym[] synonyms
contains RosettaEnumValue[] enumValues opposite enumeration
}

class RosettaEnumValue extends RosettaSymbol, RosettaDefinable, RosettaFeature, References {
class RosettaEnumValue extends RosettaSymbol, RosettaDefinable, RosettaFeature, References, Annotated {
String display
contains RosettaEnumSynonym[] enumSynonyms
container RosettaEnumeration enumeration opposite enumValues
Expand Down
11 changes: 5 additions & 6 deletions rosetta-lang/src/main/java/com/regnosys/rosetta/Rosetta.xtext
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,13 @@ Attribute:
;

Enumeration returns RosettaEnumeration:
'enum' RosettaNamed ('extends' superType=[RosettaEnumeration|QualifiedName])? ':' RosettaDefinable?
References*
(synonyms += RosettaSynonym)*
'enum' RosettaNamed ('extends' parent=[RosettaEnumeration|QualifiedName])? ':' RosettaDefinable?
(References|Annotations|synonyms+=RosettaSynonym)*
enumValues += RosettaEnumValue*
;

Function:
'func'
'func'
(
RosettaNamed
| ({FunctionDispatch} RosettaNamed '(' attribute=[Attribute|ValidID] ':' value=EnumValueReference')')
Expand Down Expand Up @@ -282,8 +281,8 @@ RosettaMetaType:
;

RosettaEnumValue:
RosettaNamed ('displayName' display=STRING)? RosettaDefinable? References*
(enumSynonyms += RosettaEnumSynonym)*
RosettaNamed ('displayName' display=STRING)? RosettaDefinable?
(References|Annotations|enumSynonyms+=RosettaEnumSynonym)*
;

RosettaCardinality:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,19 +94,17 @@ class RosettaEcoreUtil {
return result.values();
}

@Deprecated // TODO: move to REnumType, similar to RDataType
@Deprecated // Use REnumType#getAllParents instead
def Set<RosettaEnumeration> getAllSuperEnumerations(RosettaEnumeration e) {
doGetSuperEnumerations(e, newLinkedHashSet)
}

@Deprecated
private def Set<RosettaEnumeration> doGetSuperEnumerations(RosettaEnumeration e, Set<RosettaEnumeration> seenEnums) {
if(e !== null && seenEnums.add(e))
doGetSuperEnumerations(e.superType, seenEnums)
doGetSuperEnumerations(e.parent, seenEnums)
return seenEnums
}

@Deprecated // TODO: move to REnumType, similar to RDataType
@Deprecated // Use REnumType#getAllEnumValues instead
def getAllEnumValues(RosettaEnumeration e) {
e.allSuperEnumerations.map[enumValues].flatten
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ class RosettaGenerator implements IGenerator2 {
]
}
RosettaEnumeration: {
enumGenerator.generate(packages, fsa, elem, version)
enumGenerator.generate(packages, fsa, elem.buildREnumType, version)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,75 +4,64 @@ import com.regnosys.rosetta.generator.java.JavaScope
import com.regnosys.rosetta.generator.java.RosettaJavaPackages.RootPackage
import com.regnosys.rosetta.generator.java.util.ImportManagerExtension
import com.regnosys.rosetta.rosetta.RosettaEnumValue
import com.regnosys.rosetta.rosetta.RosettaEnumeration
import com.rosetta.model.lib.annotations.RosettaEnum
import com.rosetta.model.lib.annotations.RosettaSynonym
import java.util.ArrayList
import java.util.Collections
import java.util.Map
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
import org.eclipse.xtend2.lib.StringConcatenationClient
import org.eclipse.xtext.generator.IFileSystemAccess2

import static com.regnosys.rosetta.generator.java.enums.EnumHelper.*
import static com.regnosys.rosetta.generator.java.util.ModelGeneratorUtil.*
import com.regnosys.rosetta.types.REnumType
import com.regnosys.rosetta.generator.java.types.JavaTypeTranslator
import org.apache.commons.text.StringEscapeUtils

class EnumGenerator {
@Inject extension ImportManagerExtension
@Inject extension JavaTypeTranslator

def generate(RootPackage root, IFileSystemAccess2 fsa, RosettaEnumeration enumeration, String version) {
def generate(RootPackage root, IFileSystemAccess2 fsa, REnumType enumeration, String version) {
fsa.generateFile(root.withForwardSlashes + '/' + enumeration.name + '.java', enumeration.toJava(root, version))
}

private def allEnumsValues(RosettaEnumeration enumeration) {
val enumValues = new ArrayList
var e = enumeration;

while (e !== null) {
e.enumValues.forEach[enumValues.add(it)]
e = e.superType
}
return enumValues;
}

private def String toJava(RosettaEnumeration e, RootPackage root, String version) {
private def String toJava(REnumType e, RootPackage root, String version) {
val scope = new JavaScope(root)

val javaEnum = e.toJavaReferenceType

val StringConcatenationClient classBody = '''
«javadoc(e, version)»
«javadoc(e.EObject, version)»
@«RosettaEnum»("«e.name»")
public enum «e.name» {
«FOR value: allEnumsValues(e) SEPARATOR ',\n' AFTER ';'»
«javadoc(value)»
«value.contributeAnnotations»
@«com.rosetta.model.lib.annotations.RosettaEnumValue»(value = "«value.name»"«IF value.display !== null», displayName = "«value.display»"«ENDIF») «convertValuesWithDisplay(value)»
«FOR value: javaEnum.enumValues SEPARATOR ',\n' AFTER ';'»
«javadoc(value.EObject)»
«value.EObject.contributeAnnotations»
@«com.rosetta.model.lib.annotations.RosettaEnumValue»(value = "«value.rosettaName»"«IF value.displayName !== null», displayName = "«value.displayName»"«ENDIF»)
«value.name»("«value.rosettaName»", «IF value.displayName !== null»"«StringEscapeUtils.escapeJava(value.displayName)»"«ELSE»null«ENDIF»)
«ENDFOR»
private static «Map»<«String», «e.name»> values;
private static «Map»<«String», «javaEnum»> values;
static {
«Map»<«String», «e.name»> map = new «ConcurrentHashMap»<>();
for («e.name» instance : «e.name».values()) {
«Map»<«String», «javaEnum»> map = new «ConcurrentHashMap»<>();
for («javaEnum» instance : «javaEnum».values()) {
map.put(instance.toDisplayString(), instance);
}
values = «Collections».unmodifiableMap(map);
}
private final «String» rosettaName;
private final «String» displayName;
«e.name»(«String» rosettaName) {
this(rosettaName, null);
}
«e.name»(«String» rosettaName, «String» displayName) {
«javaEnum»(«String» rosettaName, «String» displayName) {
this.rosettaName = rosettaName;
this.displayName = displayName;
}
public static «e.name» fromDisplayName(String name) {
«e.name» value = values.get(name);
public static «javaEnum» fromDisplayName(String name) {
«javaEnum» value = values.get(name);
if (value == null) {
throw new «IllegalArgumentException»("No enum constant with display name \"" + name + "\".");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,8 @@ import java.util.List
import java.util.stream.Collectors

class EnumHelper {

def static convertValuesWithDisplay(RosettaEnumValue enumValue) {
formatEnumName(enumValue.name) + '''("«enumValue.name»"«IF enumValue.display !== null», "«enumValue.display»"«ENDIF»)'''
}

def static convertValues(RosettaEnumValue enumValue) {

def static convertValue(RosettaEnumValue enumValue) {
formatEnumName(enumValue.name)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ import java.time.format.DateTimeParseException
import java.util.Arrays
import java.util.Collection
import java.util.List
import java.util.Objects
import java.util.Optional
import java.util.stream.Collectors
import javax.inject.Inject
Expand All @@ -129,7 +128,7 @@ import org.eclipse.emf.ecore.EObject
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.java.enums.EnumHelper.convertValue
import com.regnosys.rosetta.rosetta.expression.SwitchCase

class ExpressionGenerator extends RosettaExpressionSwitch<JavaStatementBuilder, ExpressionGenerator.Context> {
Expand Down Expand Up @@ -273,9 +272,9 @@ class ExpressionGenerator extends RosettaExpressionSwitch<JavaStatementBuilder,
»«FOR input : inputs SEPARATOR ", "»«scope.getIdentifierOrThrow(input)»«ENDFOR»'''
}

def JavaStatementBuilder enumCall(RosettaEnumValue feature, EObject context) {
val resultItemType = typeProvider.getRTypeOfFeature(feature, context).toJavaReferenceType
return JavaExpression.from('''«resultItemType».«feature.convertValues»''', resultItemType)
def JavaStatementBuilder enumCall(RosettaEnumValue feature, JavaType expectedType) {
val itemType = expectedType.itemType
return JavaExpression.from('''«itemType».«feature.convertValue»''', itemType)
}
def JavaStatementBuilder featureCall(JavaStatementBuilder receiverCode, RType receiverType, RosettaFeature feature, boolean isDeepFeature, JavaScope scope, boolean autoValue) {
if (feature instanceof Attribute) {
Expand Down Expand Up @@ -626,7 +625,6 @@ class ExpressionGenerator extends RosettaExpressionSwitch<JavaStatementBuilder,
val thenBranch = expr.ifthen.javaCode(context.expectedType, context.scope)
val elseBranch = expr.elsethen.javaCode(context.expectedType, context.scope)

// TODO: fix result type (should join both types)
condition
.collapseToSingleExpression(context.scope)
.mapExpression[new JavaIfThenElseBuilder(it, thenBranch, elseBranch, typeUtil)]
Expand Down Expand Up @@ -683,7 +681,7 @@ class ExpressionGenerator extends RosettaExpressionSwitch<JavaStatementBuilder,

override protected caseFeatureCall(RosettaFeatureCall expr, Context context) {
if (expr.feature instanceof RosettaEnumValue) {
return enumCall(expr.feature as RosettaEnumValue, expr)
return enumCall(expr.feature as RosettaEnumValue, context.expectedType)
}
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 &&
Expand Down Expand Up @@ -1209,7 +1207,7 @@ class ExpressionGenerator extends RosettaExpressionSwitch<JavaStatementBuilder,
head.literalGuard.javaCode(MAPPER_S.wrap(conditionType), javaScope).collapseToSingleExpression(javaScope)
} else {
val condition = head.enumGuard
JavaExpression.from('''«MapperS».of(«conditionType».«condition.convertValues»)''', MAPPER_S.wrap(conditionType))
JavaExpression.from('''«MapperS».of(«conditionType».«condition.convertValue»)''', MAPPER_S.wrap(conditionType))

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,12 @@ public JavaClass<?> toJavaReferenceType(RType type) {
throw new UnsupportedOperationException("Cannot convert type " + getTypeDebugInfo(type) + " to a Java reference type.");
}
}
public RJavaPojoInterface toJavaReferenceType(RDataType type) {
return toJavaType(type);
}
public RJavaEnum toJavaReferenceType(REnumType type) {
return toJavaType(type);
}
public JavaClass<?> toJavaReferenceType(Optional<RType> type) {
if (type.isPresent()) {
return toJavaReferenceType(type.orElseThrow());
Expand All @@ -284,12 +290,15 @@ public JavaClass<?> toJavaReferenceType(Optional<RType> type) {
public JavaType toJavaType(RType type) {
return doSwitch(type, null);
}
public RJavaPojoInterface toJavaType(RDataType type) {
return caseDataType(type, null);
}
public RJavaEnum toJavaType(REnumType type) {
return caseEnumType(type, null);
}
public JavaType toJavaType(Optional<RType> type) {
return type.map(t -> toJavaType(t)).orElse(typeUtil.OBJECT);
}
public JavaClass<?> toJavaType(RDataType type) {
return caseDataType(type, null);
}

public JavaClass<?> toPolymorphicListOrSingleJavaType(RType type, boolean isMany) {
if (isMany) {
Expand Down Expand Up @@ -342,11 +351,11 @@ protected JavaType caseErrorType(RErrorType type, Void context) {
throw new IllegalArgumentException("Cannot convert an error type to a Java type.");
}
@Override
protected JavaClass<?> caseDataType(RDataType type, Void context) {
protected RJavaPojoInterface caseDataType(RDataType type, Void context) {
return new RJavaPojoInterface(type, typeSystem);
}
@Override
protected JavaClass<?> caseEnumType(REnumType type, Void context) {
protected RJavaEnum caseEnumType(REnumType type, Void context) {
return new RJavaEnum(type);
}
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,16 @@

package com.regnosys.rosetta.generator.java.types;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.regnosys.rosetta.generator.java.enums.EnumHelper;
import com.regnosys.rosetta.rosetta.RosettaEnumValue;
import com.regnosys.rosetta.types.REnumType;
import com.regnosys.rosetta.types.RObjectFactory;
import com.rosetta.util.DottedPath;
import com.rosetta.util.types.JavaClass;
import com.rosetta.util.types.JavaPrimitiveType;
Expand All @@ -28,10 +34,38 @@

public class RJavaEnum extends JavaClass<Object> {
private final REnumType enumeration;

private RJavaEnum parent = null;
private List<RJavaEnumValue> enumValues = null;

public RJavaEnum(REnumType enumeration) {
this.enumeration = enumeration;
}

public RJavaEnum getParent() {
if (enumeration.getParent() != null) {
if (parent == null) {
parent = new RJavaEnum(enumeration.getParent());
}
}
return parent;
}

public List<RJavaEnumValue> getEnumValues() {
if (enumValues == null) {
enumValues = new ArrayList<>();
RJavaEnum p = getParent();
if (p != null) {
for (RJavaEnumValue v : p.getEnumValues()) {
enumValues.add(new RJavaEnumValue(this, v.getName(), v.getEObject(), v));
}
}
for (RosettaEnumValue v : enumeration.getOwnEnumValues()) {
enumValues.add(new RJavaEnumValue(this, EnumHelper.convertValue(v), v, null));
}
}
return enumValues;
}

@Override
public boolean isSubtypeOf(JavaType other) {
Expand Down Expand Up @@ -71,7 +105,7 @@ public List<JavaClass<?>> getInterfaces() {

@Override
public boolean extendsDeclaration(JavaTypeDeclaration<?> other) {
return false;
return other.equals(JavaClass.OBJECT);
}

@Override
Expand Down
Loading

0 comments on commit f4d4790

Please sign in to comment.