Skip to content

Commit

Permalink
Runtime type format validation (#560)
Browse files Browse the repository at this point in the history
* Generate TypeFormatValidator

* Fixed null attribute type format checks

* Cleaned

* Added testGenerate goal to rosetta-maven-plugin

* Fixed digits calculation

* cleaned
  • Loading branch information
SimonCockx authored May 31, 2023
1 parent d205353 commit c3d242b
Show file tree
Hide file tree
Showing 23 changed files with 1,237 additions and 196 deletions.
8 changes: 2 additions & 6 deletions documentation/rosetta-modelling-component.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,10 @@ The example below specifies a positive decimal `number` with a precision of 18,
number(digits: 18, fractionalDigits: 17, min: 0, max: 5000)
```

Note that all parameterized arguments are optional. If unspecified, the default arguments for `number` are:

- `digits: 18`
- `fractionalDigits: digits-1` (represents the maximum number of fractional digits)
- there is no `min` or `max` constraint
Note that all parameterized arguments are optional. By default, there are no constraints.

{{< notice info "Note" >}}
The basic type `int` is shorthand for `number(fractionalDigits: 0)`.
The basic type `int` is shorthand for `number(fractionalDigits: 0)`. It also supports specifying the constraints `digits`, `min` and `max`.
{{< /notice >}}

The example below specifies a `string` with 3 to 5 characters that must be alphanumeric.
Expand Down
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<!-- Dependency management -->
<xtext.version>2.27.0</xtext.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
<commons-text.version>1.10.0</commons-text.version>
<junit.version>5.8.2</junit.version>
<mockito-core.version>5.1.1</mockito-core.version>
<xsemantics.version>1.22.0</xsemantics.version>
Expand Down Expand Up @@ -132,6 +133,11 @@
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>${commons-text.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.emf</groupId>
<artifactId>org.eclipse.emf.ecore.xcore</artifactId>
Expand Down
4 changes: 4 additions & 0 deletions rosetta-lang/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@
<groupId>org.eclipse.emf</groupId>
<artifactId>org.eclipse.emf.ecore.xcore.lib</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import com.regnosys.rosetta.generator.java.object.ValidatorsGenerator
import com.regnosys.rosetta.generator.java.rule.DataRuleGenerator
import com.regnosys.rosetta.generator.java.util.ModelNamespaceUtil
import com.regnosys.rosetta.generator.resourcefsa.ResourceAwareFSAFactory
import com.regnosys.rosetta.generator.resourcefsa.TestResourceAwareFSAFactory.TestFolderAwareFsa
import com.regnosys.rosetta.generator.util.RosettaFunctionExtensions
import com.regnosys.rosetta.rosetta.RosettaModel
import com.regnosys.rosetta.rosetta.simple.Data
Expand Down Expand Up @@ -74,10 +73,9 @@ class RosettaGenerator implements IGenerator2 {
try {
lock.getWriteLock(true);
val models = resourceSet.resources
.filter[!TestFolderAwareFsa.isTestResource(it)]
.filter[!ignoredFiles.contains(URI.segments.last)]
.flatMap[contents]
.filter(RosettaModel).toList
.map[contents.head as RosettaModel]
.toList
val version = models.head.version // TODO: find a way to access the version of a project directly

externalGenerators.forEach [ generator |
Expand Down Expand Up @@ -219,10 +217,9 @@ class RosettaGenerator implements IGenerator2 {
backwardCompatibilityGenerator.generate(fsa2)

val models = resourceSet.resources
.filter[!TestFolderAwareFsa.isTestResource(it)]
.filter[!ignoredFiles.contains(URI.segments.last)]
.flatMap[contents]
.filter(RosettaModel).toList
.map[contents.head as RosettaModel]
.toList
val version = models.head.version // TODO: find a way to access the version of a project directly

val namespaceDescriptionMap = modelNamespaceUtil.namespaceToDescriptionMap(models).asMap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ import com.regnosys.rosetta.generator.java.types.JavaTypeTranslator
import com.regnosys.rosetta.types.TypeSystem
import com.regnosys.rosetta.types.REnumType
import com.regnosys.rosetta.rosetta.expression.RosettaNumberLiteral
import org.apache.commons.text.StringEscapeUtils

class ExpressionGenerator {

Expand Down Expand Up @@ -143,7 +144,7 @@ class ExpressionGenerator {
'''«MapperS».of(«Integer».valueOf(«expr.value»))'''
}
RosettaStringLiteral : {
'''«MapperS».of("«expr.value»")'''
'''«MapperS».of("«StringEscapeUtils.escapeJava(expr.value)»")'''
}
RosettaEnumValueReference : {
'''«MapperS».of(«new REnumType(expr.enumeration).toJavaType».«expr.value.convertValues»)'''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ class ModelMetaGenerator {
}

private def StringConcatenationClient metaClassBody(Data c, RootPackage root, String className, String version) {
val dataClass = new RDataType(c).toJavaType
val t = new RDataType(c)
val dataClass = t.toJavaType
val validator = t.toValidatorClass
val typeFormatValidator = t.toTypeFormatValidatorClass
val onlyExistsValidator = t.toOnlyExistsValidatorClass
val context = c.eResource.resourceSet
val qualifierFuncs = qualifyFuncs(c, context.resources.map[contents.head as RosettaModel].toSet)
val dataRules = c.allSuperTypes.map[it.conditionRules(it.conditions)].flatten
Expand Down Expand Up @@ -82,12 +86,17 @@ class ModelMetaGenerator {
@Override
public «Validator»<? super «dataClass»> validator() {
return new «root.typeValidation».«dataClass»Validator();
return new «validator»();
}
@Override
public «Validator»<? super «dataClass»> typeFormatValidator() {
return new «typeFormatValidator»();
}
@Override
public «ValidatorWithArg»<? super «dataClass», «Set»<String>> onlyExistsValidator() {
return new «root.existsValidation».«ValidatorsGenerator.onlyExistsValidatorName(c)»();
return new «onlyExistsValidator»();
}
}
'''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import com.regnosys.rosetta.generator.java.RosettaJavaPackages.RootPackage
import com.regnosys.rosetta.generator.java.types.JavaTypeTranslator
import com.regnosys.rosetta.types.RDataType
import com.regnosys.rosetta.types.TypeSystem
import com.regnosys.rosetta.generator.java.types.JavaType

class ModelObjectGenerator {

Expand Down Expand Up @@ -68,22 +67,22 @@ class ModelObjectGenerator {
«FOR attribute : d.expandedAttributes»
«javadoc(attribute.definition, attribute.docReferences, null)»
«attribute.toJavaType» get«attribute.name.toFirstUpper»();
«attribute.toMultiMetaOrRegularJavaType» get«attribute.name.toFirstUpper»();
«ENDFOR»
final static «metaType» «metaDataIdentifier» = new «metaType»();
@Override
default «RosettaMetaData»<? extends «d.name»> metaData() {
default «RosettaMetaData»<? extends «javaType»> metaData() {
return «metaDataIdentifier»;
}
static «javaType.toBuilderType» builder() {
return new «javaType.toBuilderImplType»();
}
default Class<? extends «d.name»> getType() {
return «d.name».class;
default Class<? extends «javaType»> getType() {
return «javaType».class;
}
«FOR pt :interfaces.filter(JavaParametrizedType).filter[baseType.simpleName=="ReferenceWithMeta" || baseType.simpleName=="FieldWithMeta"]»
Expand Down Expand Up @@ -165,7 +164,7 @@ class ModelObjectGenerator {
val javaType = new RDataType(c).toJavaType
'''
«FOR attribute : expandedAttributes»
private final «attribute.toJavaType» «scope.createIdentifier(attribute, attribute.name)»;
private final «attribute.toMultiMetaOrRegularJavaType» «scope.createIdentifier(attribute, attribute.name)»;
«ENDFOR»
protected «javaType»Impl(«javaType.toBuilderType» builder) {
Expand All @@ -179,7 +178,7 @@ class ModelObjectGenerator {
«FOR attribute : expandedAttributes»
@Override
public «attribute.toJavaType» get«attribute.name.toFirstUpper»() {
public «attribute.toMultiMetaOrRegularJavaType» get«attribute.name.toFirstUpper»() {
return «scope.getIdentifierOrThrow(attribute)»;
}
Expand Down Expand Up @@ -207,20 +206,6 @@ class ModelObjectGenerator {
'''
}

private def JavaType toJavaType(ExpandedAttribute attribute) {
val singleType = attribute.toMetaOrRegularJavaType
if (attribute.isMultiple) {
if (attribute.dataType || attribute.hasMetas) {
singleType.toPolymorphicList
} else {
new JavaParametrizedType(JavaClass.from(List), singleType)
}
}
else {
singleType
}
}

private def StringConcatenationClient attributeFromBuilder(ExpandedAttribute attribute) {
if(attribute.isDataType || attribute.hasMetas) {
if (attribute.cardinalityIsListValue)
Expand Down
Loading

0 comments on commit c3d242b

Please sign in to comment.