From 102a4857bf44d2258d9234d4b200e14705961477 Mon Sep 17 00:00:00 2001 From: Anna Shipil Date: Tue, 9 Sep 2025 15:31:07 +0200 Subject: [PATCH 1/4] DEVX-639: adding test for the new rule and the rule itself --- .../validators/DiscriminatedSubtypeRule.kt | 41 +++++++++++++++++++ .../rmf/validators/ValidatorRulesTest.groovy | 10 +++++ .../resources/discriminatorsubtype-rule.raml | 16 ++++++++ 3 files changed, 67 insertions(+) create mode 100644 ctp-validators/src/main/kotlin/com/commercetools/rmf/validators/DiscriminatedSubtypeRule.kt create mode 100644 ctp-validators/src/test/resources/discriminatorsubtype-rule.raml diff --git a/ctp-validators/src/main/kotlin/com/commercetools/rmf/validators/DiscriminatedSubtypeRule.kt b/ctp-validators/src/main/kotlin/com/commercetools/rmf/validators/DiscriminatedSubtypeRule.kt new file mode 100644 index 00000000..be8c66bf --- /dev/null +++ b/ctp-validators/src/main/kotlin/com/commercetools/rmf/validators/DiscriminatedSubtypeRule.kt @@ -0,0 +1,41 @@ +package com.commercetools.rmf.validators + +import io.vrap.rmf.raml.model.types.ObjectType +import org.eclipse.emf.common.util.Diagnostic +import java.util.ArrayList +import java.util.Locale + +@ValidatorSet +class DiscriminatedSubtypeRule(severity: RuleSeverity, options: List? = null) : TypesRule(severity, options) { + + // implement + private val exclude: List = + (options?.filter { ruleOption -> ruleOption.type.lowercase(Locale.getDefault()) == RuleOptionType.EXCLUDE.toString() }?.map { ruleOption -> ruleOption.value }?.plus("") ?: defaultExcludes) + + // implement + override fun caseObjectType(type: ObjectType): List { + val validationResults: MutableList = ArrayList() + + val parent = type.type + if (parent != null && (parent as ObjectType).discriminator != null && type.discriminatorValue == null && exclude.contains(type.name).not()) { + validationResults.add(create(type, + "Discriminator was added to supertype, it should be set to not null for all subtypes. Discriminator is set to null for subtype: {0}, while there is a discriminator for parent type: {1}", + type.name, parent.name)) + } + + return validationResults + } + + companion object : ValidatorFactory { + private val defaultExcludes by lazy { listOf("") } + + @JvmStatic + override fun create(options: List?): DiscriminatedSubtypeRule { + return DiscriminatedSubtypeRule(RuleSeverity.ERROR, options) + } + + @JvmStatic + override fun create(severity: RuleSeverity, options: List?): DiscriminatedSubtypeRule { + return DiscriminatedSubtypeRule(severity, options) + } } +} \ No newline at end of file diff --git a/ctp-validators/src/test/groovy/com/commercetools/rmf/validators/ValidatorRulesTest.groovy b/ctp-validators/src/test/groovy/com/commercetools/rmf/validators/ValidatorRulesTest.groovy index 9e7c78fc..8f25e415 100644 --- a/ctp-validators/src/test/groovy/com/commercetools/rmf/validators/ValidatorRulesTest.groovy +++ b/ctp-validators/src/test/groovy/com/commercetools/rmf/validators/ValidatorRulesTest.groovy @@ -81,6 +81,16 @@ class ValidatorRulesTest extends Specification implements ValidatorFixtures { result.validationResults[0].message == "Discriminator and DiscriminatorValue property defined in the same type: InvalidFooBaz" } + def "discriminator subtype rule"() { + def validators = Arrays.asList(new TypesValidator(Arrays.asList(DiscriminatedSubtypeRule.create(emptyList())))) + def uri = uriFromClasspath("/discriminatorsubtype-rule.raml") + when: + def result = new RamlModelBuilder(validators).buildApi(uri) + then: + result.validationResults.size() == 1 + result.validationResults[0].message == "Discriminator was added to supertype, it should be set to not null for all subtypes. Discriminator is set to null for subtype: InvalidFoo, while there is a discriminator for parent type: Foo" + } + def "filename rule"() { when: def validators = Arrays.asList(new ModulesValidator(Arrays.asList(FilenameRule.create(emptyList())))) diff --git a/ctp-validators/src/test/resources/discriminatorsubtype-rule.raml b/ctp-validators/src/test/resources/discriminatorsubtype-rule.raml new file mode 100644 index 00000000..39d89086 --- /dev/null +++ b/ctp-validators/src/test/resources/discriminatorsubtype-rule.raml @@ -0,0 +1,16 @@ +#%RAML 1.0 +title: discriminator parent rule + +types: + Foo: + type: object + discriminator: type + properties: + type: string + FooBar: + type: Foo + discriminatorValue: foobar + InvalidFoo: + type: Foo + properties: + type: string From b52949c231c4a5a22e4f9efec96ac462e07616ba Mon Sep 17 00:00:00 2001 From: Jens Schulze Date: Thu, 11 Sep 2025 10:29:12 +0200 Subject: [PATCH 2/4] added some more edge case testing to the fixture --- .../test/resources/discriminatorsubtype-rule.raml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ctp-validators/src/test/resources/discriminatorsubtype-rule.raml b/ctp-validators/src/test/resources/discriminatorsubtype-rule.raml index 39d89086..6be0d3ac 100644 --- a/ctp-validators/src/test/resources/discriminatorsubtype-rule.raml +++ b/ctp-validators/src/test/resources/discriminatorsubtype-rule.raml @@ -3,14 +3,26 @@ title: discriminator parent rule types: Foo: + description: Foo type: object discriminator: type properties: type: string FooBar: + description: FooBar type: Foo discriminatorValue: foobar InvalidFoo: + description: FooBar type: Foo properties: type: string + ValidProperty: + type: object + properties: + foo: + type: Foo + description: foo + fooBar: + type: FooBar + description: foobar From 89e371129c669c289956de40f57e3b396a735675 Mon Sep 17 00:00:00 2001 From: Jens Schulze Date: Thu, 11 Sep 2025 10:32:24 +0200 Subject: [PATCH 3/4] also test the discriminator type for resource bodies --- .../src/test/resources/discriminatorsubtype-rule.raml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ctp-validators/src/test/resources/discriminatorsubtype-rule.raml b/ctp-validators/src/test/resources/discriminatorsubtype-rule.raml index 6be0d3ac..1dcd3513 100644 --- a/ctp-validators/src/test/resources/discriminatorsubtype-rule.raml +++ b/ctp-validators/src/test/resources/discriminatorsubtype-rule.raml @@ -26,3 +26,10 @@ types: fooBar: type: FooBar description: foobar + +/test: + post: + body: + application/json: + type: Foo + description: foo From 56c7996b78bafbd5a9792be57e933e301e15ff25 Mon Sep 17 00:00:00 2001 From: Anna Shipil Date: Thu, 11 Sep 2025 12:03:18 +0200 Subject: [PATCH 4/4] DEVX-639: fixing for inline types --- .../commercetools/rmf/validators/DiscriminatedSubtypeRule.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctp-validators/src/main/kotlin/com/commercetools/rmf/validators/DiscriminatedSubtypeRule.kt b/ctp-validators/src/main/kotlin/com/commercetools/rmf/validators/DiscriminatedSubtypeRule.kt index be8c66bf..beade954 100644 --- a/ctp-validators/src/main/kotlin/com/commercetools/rmf/validators/DiscriminatedSubtypeRule.kt +++ b/ctp-validators/src/main/kotlin/com/commercetools/rmf/validators/DiscriminatedSubtypeRule.kt @@ -17,7 +17,7 @@ class DiscriminatedSubtypeRule(severity: RuleSeverity, options: List val validationResults: MutableList = ArrayList() val parent = type.type - if (parent != null && (parent as ObjectType).discriminator != null && type.discriminatorValue == null && exclude.contains(type.name).not()) { + if (!type.isInlineType && parent != null && (parent as ObjectType).discriminator != null && type.discriminatorValue == null && exclude.contains(type.name).not()) { validationResults.add(create(type, "Discriminator was added to supertype, it should be set to not null for all subtypes. Discriminator is set to null for subtype: {0}, while there is a discriminator for parent type: {1}", type.name, parent.name))