Skip to content

Commit

Permalink
Merged
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonCockx committed Oct 30, 2024
2 parents 7f16aa8 + fb297a7 commit 4da3da3
Show file tree
Hide file tree
Showing 64 changed files with 2,474 additions and 875 deletions.
27 changes: 27 additions & 0 deletions docs/rune-modelling-component.md
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,33 @@ Each attribute of the `metadata` annotation corresponds to a different qualifier
- The `template` qualifier indicates that a data type is eligible to be used as a [data template](#data-template). Data templates provide a way to store data which may be duplicated across multiple objects into a single template, to be referenced by all these objects.
- the other metadata annotations are used for [cross-referencing](#cross-referencing).
#### Meta-Data Use In Functions And Expressions
It is possible to use `metadata` annotated function inputs and expressions outputs to access the value of a piece of metadata. The following is an example of using `metadata` that has been passed into a function:
```Haskell
func MyFunc:
inputs:
myInput string (1..1)
[metadata scheme]
output:
myResult string (1..1)
set myResult: myInput -> scheme
```
Additionally here is an example of how to work with metadata that is the output of an expression:
```Haskell
func MyFunc:
inputs:
myInput string (1..*)
[metadata scheme]
output:
myResult string (1..*)
set myResult: myInput extract scheme
```
### Document Reference
#### Purpose
Expand Down
25 changes: 14 additions & 11 deletions rosetta-ide/rosetta.tmLanguage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1038,19 +1038,22 @@ repository:
- include: '#documentationFollowedByExpression'

expression:
include: '#parameterizedExpression'
arguments:
extraEnd: ''
patterns:
- include: '#parameterizedExpression'
arguments:
extraEnd: ''

expressionWithoutThenOperation:
include: '#parameterizedExpression'
arguments:
extraEnd: '(?={{wordStart}}then{{wordEnd}})|'
patterns:
- include: '#parameterizedExpression'
arguments:
extraEnd: '(?={{wordStart}}then{{wordEnd}})|'

expressionWithoutThenAndDefaultOperation:
include: '#parameterizedExpression'
arguments:
extraEnd: '(?={{wordStart}}then|default{{wordEnd}})|'
patterns:
- include: '#parameterizedExpression'
arguments:
extraEnd: '(?={{wordStart}}then|default{{wordEnd}})|'

parameterizedExpression:
parameters: ['extraEnd']
Expand Down Expand Up @@ -1167,7 +1170,7 @@ repository:
- name: meta.switch-operation.rosetta
begin: '{{wordStart}}switch{{wordEnd}}'
beginCaptures:
0: { name: keyword.operator.word.rosetta }
0: { name: keyword.control.conditional.switch.rosetta }
end: '{{extraEnd}}{{expressionEndIgnoringComma}}'
patterns:
- include: '#comment'
Expand Down Expand Up @@ -1370,4 +1373,4 @@ repository:

comma:
name: punctuation.separator.comma.rosetta
match: ','
match: ','
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public List<String> getDocumentationFromOwner(EObject o) {
if (o instanceof RosettaSymbolReference) {
RosettaSymbol symbol = ((RosettaSymbolReference)o).getSymbol();
if (symbol instanceof RosettaEnumValue) {
RType t = expectedTypeProvider.getExpectedTypeFromContainer(o);
RType t = expectedTypeProvider.getExpectedTypeFromContainer(o).getRType();
docs.add(t.toString());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public InlayHint checkFunctionalOperation(RosettaFunctionalOperation op) {
if (op.getFunction() != null && operationHasBrackets(op.getFunction())) {
if (op instanceof ReduceOperation || op instanceof MapOperation) {
if (extensions.isResolved(op.getFunction())) {
RType outputType = types.getRType(op);
RType outputType = types.getRMetaAnnotatedType(op).getRType();
boolean outputMulti = card.isMulti(op);

if (outputType != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
import com.regnosys.rosetta.rosetta.simple.Segment;
import com.regnosys.rosetta.rosetta.simple.ShortcutDeclaration;
import com.regnosys.rosetta.types.CardinalityProvider;
import com.regnosys.rosetta.types.RType;
import com.regnosys.rosetta.types.RMetaAnnotatedType;
import com.regnosys.rosetta.types.RosettaTypeProvider;

import static com.regnosys.rosetta.rosetta.RosettaPackage.Literals.*;
Expand Down Expand Up @@ -263,7 +263,7 @@ public SemanticToken markFeature(RosettaFeatureCall featureCall) {

private SemanticToken markSymbol(EObject objectToMark, EStructuralFeature featureToMark, RosettaSymbol symbol) {
if (symbol instanceof Attribute) {
RType implicitType = typeProvider.typeOfImplicitVariable(objectToMark);
RMetaAnnotatedType implicitType = typeProvider.typeOfImplicitVariable(objectToMark);
if (implicitType != null) {
Set<? extends RosettaFeature> implicitFeatures = Sets.newHashSet(extensions.allFeatures(implicitType, objectToMark));
if (implicitFeatures.contains(symbol)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,11 @@ private void validatePattern(TmValue<Object> pattern, Map<Object, Object> namedP
// - begin/while
// - list of patterns
if (tmMap.value.get("include") != null) {
if (!tmMap.path.get(tmMap.path.size() - 1).equals("patterns")) {
// Note: this check is only necessary for Monaco. See https://github.com/zikaari/monaco-textmate/issues/13.
// VS Code supports direct includes.
throw new ConfigurationException("Validation failed on include: may only be used inside 'patterns'. " + tmMap.getPath());
}
runValidators(tmMap, Map.of("include", include, "comment", comment, "repository", repository));
} else if (tmMap.value.get("match") != null) {
runValidators(tmMap, Map.of("name", scopes, "match", regex, "captures", captures, "comment", comment, "repository", repository));
Expand Down
2 changes: 1 addition & 1 deletion rosetta-lang/model/Rosetta.xcore
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class RosettaTypeAlias extends RosettaRootElement, RosettaType, RosettaTyped, Ro
}


class RosettaMetaType extends RosettaRootElement, RosettaTypedFeature, RosettaType {
class RosettaMetaType extends RosettaRootElement, RosettaTypedFeature, RosettaType, RosettaSymbol {

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.regnosys.rosetta

import com.google.common.base.CaseFormat
import com.regnosys.rosetta.rosetta.RosettaEnumeration
import com.regnosys.rosetta.rosetta.RosettaFactory
import com.regnosys.rosetta.rosetta.RosettaFeature
import com.regnosys.rosetta.rosetta.RosettaRecordType
import com.regnosys.rosetta.rosetta.RosettaSynonym
Expand All @@ -12,41 +13,48 @@ import com.regnosys.rosetta.rosetta.simple.Attribute
import com.regnosys.rosetta.rosetta.simple.Condition
import com.regnosys.rosetta.rosetta.simple.Data
import com.regnosys.rosetta.rosetta.simple.Function
import com.regnosys.rosetta.rosetta.simple.SimpleFactory
import com.regnosys.rosetta.scoping.RosettaScopeProvider
import com.regnosys.rosetta.types.RAttribute
import com.regnosys.rosetta.types.RChoiceType
import com.regnosys.rosetta.types.RDataType
import com.regnosys.rosetta.types.REnumType
import com.regnosys.rosetta.types.RMetaAnnotatedType
import com.regnosys.rosetta.types.RObjectFactory
import com.regnosys.rosetta.types.RType
import com.regnosys.rosetta.types.builtin.RBuiltinTypeService
import com.regnosys.rosetta.types.builtin.RRecordType
import com.regnosys.rosetta.utils.PositiveIntegerInterval
import com.regnosys.rosetta.utils.RosettaConfigExtension
import java.util.Collection
import java.util.LinkedHashSet
import java.util.List
import java.util.Set
import javax.inject.Inject
import javax.inject.Singleton
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.resource.ResourceSet

import com.regnosys.rosetta.types.builtin.RRecordType
import com.regnosys.rosetta.types.builtin.RBuiltinTypeService
import javax.inject.Singleton
import java.util.List
import com.regnosys.rosetta.utils.PositiveIntegerInterval
import org.eclipse.xtext.util.SimpleCache
import com.regnosys.rosetta.rosetta.RosettaFactory
import com.regnosys.rosetta.scoping.RosettaScopeProvider
import com.regnosys.rosetta.rosetta.simple.SimpleFactory
import com.regnosys.rosetta.types.RObjectFactory
import java.util.LinkedHashSet
import com.regnosys.rosetta.types.TypeSystem
import com.regnosys.rosetta.types.RChoiceType

import static extension com.regnosys.rosetta.types.RMetaAnnotatedType.withMeta
import org.eclipse.emf.ecore.util.EcoreUtil

@Singleton // see `metaFieldsCache`
class RosettaEcoreUtil {

@Inject RBuiltinTypeService builtins
@Inject RObjectFactory objectFactory
@Inject extension TypeSystem typeSystem
@Inject extension RObjectFactory objectFactory
@Inject extension RosettaConfigExtension configs

def boolean isResolved(EObject obj) {
obj !== null && !obj.eIsProxy
}

def Iterable<? extends RosettaFeature> allFeatures(RMetaAnnotatedType t, EObject context) {
val List<RosettaFeature> metas = getMetaDescriptions(t, context)
allFeatures(t.RType, context?.eResource?.resourceSet) + metas
}

def Iterable<? extends RosettaFeature> allFeatures(RType t, EObject context) {
allFeatures(t, context?.eResource?.resourceSet)
}
Expand Down Expand Up @@ -134,10 +142,6 @@ class RosettaEcoreUtil {
metaAnnotations.exists[attribute?.name == "template"]
}

def boolean hasMetaDataAnnotations(RAttribute attribute) {
attribute.metaAnnotations.exists[name == "reference" || name == "location" || name == "scheme" || name == "id"]
}

def boolean hasMetaDataAnnotations(Annotated it) {
metaAnnotations.exists[attribute?.name == "reference" || attribute?.name == "location" || attribute?.name == "scheme" || attribute?.name == "id"]
}
Expand All @@ -146,8 +150,12 @@ class RosettaEcoreUtil {
metaAnnotations.exists[attribute?.name != "reference" && attribute?.name != "address"]
}

def boolean hasMetaDataReference(RAttribute attribute) {
attribute.RMetaAnnotatedType.getMetaAttributes.exists[name == "reference"]
}

def boolean hasMetaDataAddress(RAttribute attribute) {
attribute.metaAnnotations.exists[name == "address"]
attribute.RMetaAnnotatedType.getMetaAttributes.exists[name == "address"]
}

def boolean hasMetaDataAddress(Annotated it) {
Expand All @@ -158,7 +166,7 @@ class RosettaEcoreUtil {
metaAnnotations.exists[attribute?.name == "id"]
}
def boolean hasIdAnnotation(RAttribute it) {
metaAnnotations.exists[name == "id"]
RMetaAnnotatedType.getMetaAttributes.exists[name == "id"]
}
def boolean hasReferenceAnnotation(Annotated it) {
metaAnnotations.exists[attribute?.name == "reference"]
Expand All @@ -167,11 +175,8 @@ class RosettaEcoreUtil {
allAnnotations.exists[annotation?.name == "calculation"]
}

def boolean isReference(Attribute attribute) {
return attribute.hasMetaDataAnnotations || attribute.hasMetaDataAddress
}
def boolean isReference(RAttribute attribute) {
return attribute.hasMetaDataAnnotations || attribute.hasMetaDataAddress
return attribute.hasMetaDataReference || attribute.hasMetaDataAddress
}

def private allAnnotations(Annotated withAnnotations) {
Expand Down Expand Up @@ -222,6 +227,30 @@ class RosettaEcoreUtil {
return '''«containerName»«name»'''
}

/*
* This method is resolving references during scoping which is not an advised approach.
* It could lead to poor performance as it is possible that it could be called upon to
* resolve across multiple files. For now this is acceptable as in reality it's not going
* going to get called to run across multiple files.
*
* TODO: find an alternative approach to this.
*
*/
private def List<RosettaFeature> getMetaDescriptions(RMetaAnnotatedType type, EObject context) {
val metas = type.metaAttributes.map[it.name].toList
if (!metas.isEmpty) {
configs.findMetaTypes(context).filter[
metas.contains(it.name.lastSegment.toString)
]
.map[it.EObjectOrProxy]
.map[EcoreUtil.resolve(it, context)]
.filter(RosettaFeature)
.toList
} else {
emptyList
}
}

@Deprecated
def String toConditionJavaType(String conditionName) {
val allUnderscore = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, conditionName)
Expand All @@ -231,9 +260,9 @@ class RosettaEcoreUtil {

@Deprecated
def String javaAnnotation(RAttribute attr) {
if (attr.name == "key" && attr.RType.name == "Key" && attr.RType.namespace.toString == "com.rosetta.model.lib.meta") {
if (attr.name == "key" && attr.RMetaAnnotatedType.RType.name == "Key" && attr.RMetaAnnotatedType.RType.namespace.toString == "com.rosetta.model.lib.meta") {
return 'location'
} else if (attr.name == "reference" && attr.RType.name == "Reference" && attr.RType.namespace.toString == "com.rosetta.model.lib.meta") {
} else if (attr.name == "reference" && attr.RMetaAnnotatedType.RType.name == "Reference" && attr.RMetaAnnotatedType.RType.namespace.toString == "com.rosetta.model.lib.meta") {
return 'address'
} else
return attr.name
Expand All @@ -247,8 +276,7 @@ class RosettaEcoreUtil {
'meta',
null,
emptyList,
provideMetaFieldsType(t),
emptyList,
provideMetaFieldsType(t).withMeta(#[]),
PositiveIntegerInterval.bounded(0, 1),
null,
null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import java.util.HashSet
import com.regnosys.rosetta.generator.java.statement.builder.JavaVariable
import com.regnosys.rosetta.types.RAttribute
import com.regnosys.rosetta.types.RChoiceType
import static extension com.regnosys.rosetta.types.RMetaAnnotatedType.*

class DeepPathUtilGenerator {
@Inject extension ImportManagerExtension
Expand Down Expand Up @@ -54,7 +55,7 @@ class DeepPathUtilGenerator {
val deepFeatures = choiceType.findDeepFeatures
val dependencies = new HashSet<JavaClass<?>>()
val recursiveDeepFeaturesMap = choiceType.allNonOverridenAttributes.toMap([it], [
val attrType = it.RType
val attrType = it.RMetaAnnotatedType.RType
deepFeatures.toMap([it], [
var t = attrType
if (t instanceof RChoiceType) {
Expand Down Expand Up @@ -98,13 +99,12 @@ class DeepPathUtilGenerator {
}

private def JavaStatementBuilder deepFeatureToStatement(RDataType choiceType, JavaVariable inputParameter, RAttribute deepFeature, Map<RAttribute, Map<RAttribute, Boolean>> recursiveDeepFeaturesMap, JavaScope scope) {
val deepFeatureHasMeta = !deepFeature.metaAnnotations.empty
val attrs = choiceType.allNonOverridenAttributes.toList
var JavaStatementBuilder acc = JavaExpression.NULL
for (a : attrs.reverseView) {
val currAcc = acc
acc = inputParameter
.featureCall(choiceType, a, false, scope, true)
.attributeCall(choiceType.withEmptyMeta, a, false, scope)
.declareAsVariable(true, a.name.toFirstLower, scope)
.mapExpression[attrVar|
attrVar.exists(ExistsModifier.NONE, scope)
Expand All @@ -114,7 +114,8 @@ class DeepPathUtilGenerator {
val deepFeatureExpr = if (deepFeature.match(a)) {
attrVar
} else {
var attrType = a.RType
val metaRType = a.RMetaAnnotatedType
var attrType = metaRType.RType
if (attrType instanceof RChoiceType) {
attrType = attrType.asRDataType
}
Expand All @@ -124,7 +125,7 @@ class DeepPathUtilGenerator {
} else {
(attrType as RDataType).allNonOverridenAttributes.findFirst[name.equals(deepFeature.name)]
}
attrVar.featureCall(attrType, actualFeature, needsToGoDownDeeper, scope, !deepFeatureHasMeta)
attrVar.attributeCall(metaRType, actualFeature, needsToGoDownDeeper, scope)
}
new JavaIfThenElseBuilder(it, deepFeatureExpr, currAcc, typeUtil)
]
Expand Down
Loading

0 comments on commit 4da3da3

Please sign in to comment.