Skip to content

Commit

Permalink
Merge pull request #592 from REGnosys/conversion-operations
Browse files Browse the repository at this point in the history
Support for conversion operations
  • Loading branch information
SimonCockx authored Jul 6, 2023
2 parents 25917a2 + 3941981 commit 4f5b18c
Show file tree
Hide file tree
Showing 23 changed files with 1,352 additions and 729 deletions.
35 changes: 29 additions & 6 deletions documentation/rosetta-modelling-component.md
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,27 @@ The `distinct` operator is useful to remove duplicate elements from a list. It c
owner -> drivingLicense -> countryofIssuance distinct count = 1
```

### Conversion operators

Rosetta provides five conversion operators: `to-enum`, `to-string`, `to-number`, `to-int`, and `to-time`. Here are examples of their usage.

Given the following enum
```
enum Foo:
VALUE1
VALUE2 displayName "Value 2"
```
- `Foo -> VALUE1 to-string` will result in the string `"VALUE1"`,
- `Foo -> VALUE2 to-string` will result in the string `"Value 2"`, (note that the display name is used if present)
- `"VALUE1" to-enum Foo" will result in the enum value `Foo -> VALUE1`,
- `"Value 2" to-enum Foo" will result in the enum value `Foo -> VALUE2`, (again, the display name is used if present)
- `"-3.14" to-number` will result in the number 3.14,
- `"17:05:33" to-time` will result in a value representing the local time 17 hours, 5 minutes and 33 seconds.

If the conversion fails, the result is an empty value. For example,
- `"VALUE2" to-enum Foo` results in an empty value, (because `Foo -> VALUE2` has a display name "Value 2", this conversion fails)
- `"3.14" to-int` results in an empty value.

## Data Validation Component

**Data integrity is supported by validation components that are associated to each data type** in the Rosetta DSL. There are two types of validation components:
Expand Down Expand Up @@ -1831,6 +1852,7 @@ A report is specified using the following syntax:

``` Haskell
report <Authority> <Corpus1> <Corpus2> <...> in <TimingRule>
from <InputType>
when <EligibilityRule1> and <EligibilityRule2> and <...>
with type <ReportType>
```
Expand All @@ -1848,6 +1870,7 @@ An example is given below.

``` Haskell
report EuropeanParliament EmissionPerformanceStandardsEU in real-time
from ReportableEvent
when EuroStandardsCoverage
with type EmissionPerformanceStandardsReport
```
Expand Down Expand Up @@ -1891,7 +1914,7 @@ To provide transparency and auditability to the reporting process, the Rosetta D
The syntax of a reporting rule is as follows:

``` Haskell
<ruleType> rule <RuleName>:
<ruleType> rule <RuleName> from <InputType>:
[ regulatoryReference <Body> <Corpus>
<Segment1>
<Segment2>
Expand All @@ -1907,7 +1930,7 @@ The functional expression of reporting rules uses the same [logical expression](
Functional expressions are composable, so a rule can also call another rule. When multiple rules may need to be applied for a single field or eligibility criteria, those rules can be specified in brackets separated by a comma, as illustrated below. Each of `Euro1Standard`, ..., `Euro6Standard` are themselves reporting rules.

``` Haskell
reporting rule EuroEmissionStandard:
reporting rule EuroEmissionStandard from ReportableEvent:
[regulatoryReference EuropeanCommission StandardEmissionsEuro6 article "1"
provision "Regulation (EC) No 715/2007 is amended as follows:..."]
(
Expand Down Expand Up @@ -2042,7 +2065,7 @@ For example, in the CFTC Part 45 regulations, fields 33-35 require the reporting
In the example below, the `repeatable` keyword in reporting rule `NotionalAmountScheduleLeg1` specifies that the extracted list of quantity notional schedule steps should be reported as a repeating set of data. The rules specified within the brackets define the fields that should be reported for each repeating step.

``` Haskell
reporting rule NotionalAmountScheduleLeg1 <"Notional Amount Schedule">
reporting rule NotionalAmountScheduleLeg1 from ReportableEvent: <"Notional Amount Schedule">
[regulatoryReference CFTC Part45 appendix "1" item "33-35" field "Notional Amount Schedule"
provision "Fields 33-35 are repeatable and shall be populated in the case of derivatives involving notional amount schedules"]
TradeForEvent then
Expand All @@ -2054,17 +2077,17 @@ reporting rule NotionalAmountScheduleLeg1 <"Notional Amount Schedule">
NotionalAmountScheduleLeg1EffectiveDate
)

reporting rule NotionalAmountScheduleLeg1Amount <"Notional amount in effect on associated effective date of leg 1">
reporting rule NotionalAmountScheduleLeg1Amount from ReportableEvent: <"Notional amount in effect on associated effective date of leg 1">
[regulatoryReference CFTC Part45 appendix "1" item "33" field "Notional amount in effect on associated effective date of leg 1"]
CDENotionalAmountScheduleAmount
as "33/35-$ 33 Notional amount leg 1"

reporting rule NotionalAmountScheduleLeg1EffectiveDate <"Effective date of the notional amount of leg 1">
reporting rule NotionalAmountScheduleLeg1EffectiveDate from ReportableEvent: <"Effective date of the notional amount of leg 1">
[regulatoryReference CFTC Part45 appendix "1" item "34" field "Effective date of the notional amount of leg 1"]
CDENotionalAmountScheduleEffectiveDate
as "33/35-$ 34 Effective date leg 1"

reporting rule NotionalAmountScheduleLeg1EndDate <"End date of the notional amount of leg 1">
reporting rule NotionalAmountScheduleLeg1EndDate from ReportableEvent: <"End date of the notional amount of leg 1">
[regulatoryReference CFTC Part45 appendix "1" item "35" field "End date of the notional amount of leg 1"]
CDENotionalAmountScheduleEndDate
as "33/35-$ 35 End date leg 1"
Expand Down
1 change: 0 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
<maven-core.version>3.6.0</maven-core.version>
<maven-plugin-annotations.version>3.6.0</maven-plugin-annotations.version>
<slf4j.version>2.0.7</slf4j.version>
<log4j-over-slf4j.version>2.0.7</log4j-over-slf4j.version>
<logback.version>1.4.7</logback.version>

<!-- test -->
Expand Down
11 changes: 10 additions & 1 deletion rosetta-ide/rosetta.tmLanguage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1159,8 +1159,17 @@ repository:
match: '{{identifier}}'
- name: punctuation.separator.member.rosetta
match: ','
- name: meta.to-enum.rosetta
begin: '{{wordStart}}to-enum{{wordEnd}}'
beginCaptures:
0: { name: keyword.operator.word.rosetta }
end: '{{identifier}}'
endCaptures:
0: { name: entity.name.type.enum.rosetta }
patterns:
- include: '#comment'
- name: keyword.operator.word.rosetta
match: '{{listOperationWord}}|{{wordStart}}(any|all|or|and|contains|disjoint|join|only|exists|as-key|one-of|as){{wordEnd}}'
match: '{{listOperationWord}}|{{wordStart}}(any|all|or|and|contains|disjoint|join|only|exists|as-key|one-of|as|to-number|to-int|to-time|to-string){{wordEnd}}'
- name: keyword.operator.rosetta
match: =|<>|>=|<=|>|<|\+|-|\*|\/
- name: variable.rosetta # Need semantic tokens to specify variable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ class ContentAssistTest extends AbstractRosettaLanguageServerTest {
sort -> sort [[9, 14] .. [9, 14]]
sum -> sum [[9, 14] .. [9, 14]]
then -> then [[9, 14] .. [9, 14]]
to-enum -> to-enum [[9, 14] .. [9, 14]]
to-int -> to-int [[9, 14] .. [9, 14]]
to-number -> to-number [[9, 14] .. [9, 14]]
to-string -> to-string [[9, 14] .. [9, 14]]
to-time -> to-time [[9, 14] .. [9, 14]]
) -> ) [[9, 14] .. [9, 14]]
* -> * [[9, 14] .. [9, 14]]
+ -> + [[9, 14] .. [9, 14]]
Expand Down Expand Up @@ -151,6 +156,11 @@ class ContentAssistTest extends AbstractRosettaLanguageServerTest {
sum -> sum [[7, 27] .. [7, 27]]
synonym -> synonym [[7, 27] .. [7, 27]]
then -> then [[7, 27] .. [7, 27]]
to-enum -> to-enum [[7, 27] .. [7, 27]]
to-int -> to-int [[7, 27] .. [7, 27]]
to-number -> to-number [[7, 27] .. [7, 27]]
to-string -> to-string [[7, 27] .. [7, 27]]
to-time -> to-time [[7, 27] .. [7, 27]]
type -> type [[7, 27] .. [7, 27]]
typeAlias -> typeAlias [[7, 27] .. [7, 27]]
) -> ) [[7, 27] .. [7, 27]]
Expand Down Expand Up @@ -221,6 +231,11 @@ class ContentAssistTest extends AbstractRosettaLanguageServerTest {
sort -> sort [[6, 25] .. [6, 25]]
sum -> sum [[6, 25] .. [6, 25]]
then -> then [[6, 25] .. [6, 25]]
to-enum -> to-enum [[6, 25] .. [6, 25]]
to-int -> to-int [[6, 25] .. [6, 25]]
to-number -> to-number [[6, 25] .. [6, 25]]
to-string -> to-string [[6, 25] .. [6, 25]]
to-time -> to-time [[6, 25] .. [6, 25]]
) -> ) [[6, 25] .. [6, 25]]
* -> * [[6, 25] .. [6, 25]]
+ -> + [[6, 25] .. [6, 25]]
Expand Down Expand Up @@ -377,6 +392,11 @@ class ContentAssistTest extends AbstractRosettaLanguageServerTest {
single -> single [[19, 2] .. [19, 2]]
sort -> sort [[19, 2] .. [19, 2]]
sum -> sum [[19, 2] .. [19, 2]]
to-enum -> to-enum [[19, 2] .. [19, 2]]
to-int -> to-int [[19, 2] .. [19, 2]]
to-number -> to-number [[19, 2] .. [19, 2]]
to-string -> to-string [[19, 2] .. [19, 2]]
to-time -> to-time [[19, 2] .. [19, 2]]
True -> True [[19, 2] .. [19, 2]]
( -> ( [[19, 2] .. [19, 2]]
* -> * [[19, 2] .. [19, 2]]
Expand Down
4 changes: 0 additions & 4 deletions rosetta-lang/model/Rosetta.xcore
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ interface RosettaTyped {
}
}

abstract class WithCardinality {
contains RosettaCardinality card
}

class RosettaFeature extends RosettaNamed {
/**
* @return The name or 'value' if it's <code>null</code>
Expand Down
20 changes: 20 additions & 0 deletions rosetta-lang/model/RosettaExpression.xcore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package com.regnosys.rosetta.rosetta.expression

import java.util.regex.Pattern

import com.regnosys.rosetta.rosetta.RosettaEnumeration
import com.regnosys.rosetta.rosetta.RosettaNamed
import com.regnosys.rosetta.rosetta.RosettaSymbol
import com.regnosys.rosetta.rosetta.RosettaFeature
Expand Down Expand Up @@ -319,6 +320,25 @@ class ChoiceOperation extends RosettaUnaryOperation {
refers Attribute[] attributes
}

class ToStringOperation extends RosettaUnaryOperation {
}

interface ParseOperation extends RosettaUnaryOperation {
}

class ToNumberOperation extends ParseOperation {
}

class ToIntOperation extends ParseOperation {
}

class ToTimeOperation extends ParseOperation {
}

class ToEnumOperation extends ParseOperation {
refers RosettaEnumeration enumeration
}

/**
* Functional operations
*/
Expand Down
5 changes: 3 additions & 2 deletions rosetta-lang/model/RosettaSimple.xcore
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import com.regnosys.rosetta.rosetta.RosettaRootElement
import com.regnosys.rosetta.rosetta.RosettaSynonym
import com.regnosys.rosetta.rosetta.RosettaType
import com.regnosys.rosetta.rosetta.RosettaTypedFeature
import com.regnosys.rosetta.rosetta.WithCardinality
import com.regnosys.rosetta.rosetta.RosettaBlueprint
import org.eclipse.emf.common.util.BasicEList
import com.regnosys.rosetta.rosetta.expression.RosettaExpression
import com.regnosys.rosetta.rosetta.RosettaAttributeReferenceSegment
import com.regnosys.rosetta.rosetta.RosettaCardinality

abstract class RootElement extends RosettaRootElement, RosettaNamed, RosettaDefinable, Annotated {
}
Expand Down Expand Up @@ -51,8 +51,9 @@ interface AssignPathRoot extends RosettaSymbol {
}


class Attribute extends RosettaTypedFeature, RosettaDefinable, Annotated, AssignPathRoot, WithCardinality, References {
class Attribute extends RosettaTypedFeature, RosettaDefinable, Annotated, AssignPathRoot, References {
boolean override
contains RosettaCardinality card
contains RosettaSynonym[] synonyms
contains RosettaRuleReference ruleReference
}
Expand Down
15 changes: 15 additions & 0 deletions rosetta-lang/src/main/java/com/regnosys/rosetta/Rosetta.xtext
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,11 @@ ListOperation returns RosettaExpression:
|({SumOperation.argument=current} operator='sum')
|({OneOfOperation.argument=current} operator='one-of')
|({ChoiceOperation.argument=current} necessity=Necessity operator='choice' attributes+=[Attribute|ValidID] =>(',' attributes+=[Attribute|ValidID])*)
|({ToStringOperation.argument=current} operator='to-string')
|({ToNumberOperation.argument=current} operator='to-number')
|({ToIntOperation.argument=current} operator='to-int')
|({ToTimeOperation.argument=current} operator='to-time')
|({ToEnumOperation.argument=current} operator='to-enum' enumeration=[RosettaEnumeration])
)
| =>(
({SortOperation.argument=current} operator='sort')
Expand Down Expand Up @@ -666,6 +671,11 @@ ListOperation returns RosettaExpression:
|({SumOperation} operator='sum')
|({OneOfOperation} operator='one-of')
|({ChoiceOperation} necessity=Necessity operator='choice' attributes+=[Attribute|ValidID] =>(',' attributes+=[Attribute|ValidID])*)
|({ToStringOperation} operator='to-string')
|({ToNumberOperation} operator='to-number')
|({ToIntOperation} operator='to-int')
|({ToTimeOperation} operator='to-time')
|({ToEnumOperation} operator='to-enum' enumeration=[RosettaEnumeration])
)
| (
({SortOperation} operator='sort')
Expand Down Expand Up @@ -694,6 +704,11 @@ ListOperation returns RosettaExpression:
|({SumOperation.argument=current} operator='sum')
|({OneOfOperation.argument=current} operator='one-of')
|({ChoiceOperation.argument=current} necessity=Necessity operator='choice' attributes+=[Attribute|ValidID] =>(',' attributes+=[Attribute|ValidID])*)
|({ToStringOperation.argument=current} operator='to-string')
|({ToNumberOperation.argument=current} operator='to-number')
|({ToIntOperation.argument=current} operator='to-int')
|({ToTimeOperation.argument=current} operator='to-time')
|({ToEnumOperation.argument=current} operator='to-enum' enumeration=[RosettaEnumeration])
)
| =>(
({SortOperation.argument=current} operator='sort')
Expand Down
Loading

0 comments on commit 4f5b18c

Please sign in to comment.