Skip to content

Commit

Permalink
Merge branch 'commercetools:main' into feat/go-add-404
Browse files Browse the repository at this point in the history
  • Loading branch information
demeyerthom authored Dec 15, 2023
2 parents a076cf5 + f0512fe commit 68d2b46
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.commercetools.rmf.validators

import com.commercetools.rmf.diff.resource
import io.vrap.rmf.raml.model.resources.HttpMethod
import io.vrap.rmf.raml.model.resources.Method
import io.vrap.rmf.raml.model.resources.Resource
import io.vrap.rmf.raml.model.resources.ResourceType
import org.eclipse.emf.common.util.Diagnostic
import java.util.*

@ValidatorSet
class MethodResponseRule(severity: RuleSeverity, options: List<RuleOption>? = null) : ResolvedResourcesRule(severity, options) {

private val exclude: List<String> =
(options?.filter { ruleOption -> ruleOption.type.lowercase(Locale.getDefault()) == RuleOptionType.EXCLUDE.toString() }?.map { ruleOption -> ruleOption.value }?.plus("") ?: defaultExcludes)

override fun caseMethod(method: Method): List<Diagnostic> {
val validationResults: MutableList<Diagnostic> = ArrayList()

if (method.eContainer() is ResourceType) {
return validationResults
}
if (method.responses.isEmpty() && exclude.contains("${method.method.name} ${(method.eContainer() as Resource).fullUri.template}").not()) {
validationResults.add(error(method, "Method \"{0} {1}\" must have at least one response defined", method.method.name, (method.eContainer() as Resource).fullUri.template))
}
return validationResults
}

companion object : ValidatorFactory<MethodResponseRule> {
private val defaultExcludes by lazy { listOf("") }

@JvmStatic
override fun create(options: List<RuleOption>?): MethodResponseRule {
return MethodResponseRule(RuleSeverity.ERROR, options)
}

@JvmStatic
override fun create(severity: RuleSeverity, options: List<RuleOption>?): MethodResponseRule {
return MethodResponseRule(severity, options)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ package com.commercetools.rmf.validators
annotation class ValidatorSets(val value: Array<ValidatorSet>)

@JvmRepeatable(ValidatorSets::class)
annotation class ValidatorSet(val name: String = "default", val severity: RuleSeverity = RuleSeverity.INFO)
annotation class ValidatorSet(val name: String = "default", val severity: RuleSeverity = RuleSeverity.ERROR)
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import java.lang.reflect.Modifier
class ValidatorSetup {
companion object {
@JvmStatic
fun setup(config: File): List<RamlValidator> {
return setup(config.inputStream())
fun setup(config: File, verbose: Boolean = false): List<RamlValidator> {
return setup(config.inputStream(), verbose)
}

fun setup(config: InputStream): List<RamlValidator> {
fun setup(config: InputStream, verbose: Boolean = false): List<RamlValidator> {
val mapper = XmlMapper.builder(XmlFactory(WstxInputFactory(), WstxOutputFactory())).defaultUseWrapper(false)
.enable(SerializationFeature.INDENT_OUTPUT)
.enable(SerializationFeature.WRAP_ROOT_VALUE)
Expand All @@ -46,6 +46,9 @@ class ValidatorSetup {
}
}

if (verbose) {
validators.filterIsInstance(DiagnosticsAware::class.java).forEach { validator -> println("${validator::class.java}: ${validator.severity}") }
}
return listOf(
ResolvedResourcesValidator(validators.filterIsInstance( ResolvedResourcesRule::class.java )),
ResourcesValidator(validators.filterIsInstance( ResourcesRule::class.java )),
Expand All @@ -58,7 +61,7 @@ class ValidatorSetup {
var checks = setOne
setTwo.forEach { (checkName, check) ->
if (checks.containsKey(checkName)) {
checks = checks.plus(checkName to Rule(checkName, check.severity, checks[checkName]!!.options?.plus(check.options ?: listOf()) ?: check.options, check.enabled && checks[checkName]!!.enabled))
checks = checks.plus(checkName to Rule(checkName, check.severity ?: checks[checkName]!!.severity, checks[checkName]!!.options?.plus(check.options ?: listOf()) ?: check.options, check.enabled && checks[checkName]!!.enabled))
} else {
checks = checks.plus(checkName to check)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.commercetools.rmf.validators

import io.vrap.rmf.raml.model.RamlModelBuilder
import org.eclipse.emf.common.util.Diagnostic
import spock.lang.Specification
import static java.util.Collections.emptyList

Expand Down Expand Up @@ -101,6 +102,17 @@ class ValidatorRulesTest extends Specification implements ValidatorFixtures {
result.validationResults[1].message == "Method \"HEAD /invalid-all\" must not have body type defined"
}

def "method response rule"() {
when:
def validators = Arrays.asList(new ResourcesValidator(Arrays.asList(MethodResponseRule.create(emptyList()))))
def uri = uriFromClasspath("/method-response-rule.raml")
def result = new RamlModelBuilder(validators).buildApi(uri)
then:
result.validationResults.size == 1
result.validationResults[0].message == "Method \"HEAD /invalid\" must have at least one response defined"
result.validationResults[0].severity == Diagnostic.ERROR
}

// def "named body type rule"() {
// when:
// def validators = Arrays.asList(new ResourcesValidator(Arrays.asList(new NamedBodyTypeRule())))
Expand Down
20 changes: 20 additions & 0 deletions ctp-validators/src/test/resources/method-response-rule.raml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#%RAML 1.0
title: method responses

resourceTypes:
test:
get?:
responses:
200:
post?:
/carts:
get:
description: test
responses:
200:
head:
responses:
200:
404:
/invalid:
head:
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.vrap.codegen.languages.javalang.client.builder.producers

import com.google.common.collect.Lists
import io.vrap.codegen.languages.extensions.isPatternProperty
import io.vrap.codegen.languages.extensions.toComment
import io.vrap.codegen.languages.java.base.JavaSubTemplates
Expand All @@ -12,10 +13,8 @@ import io.vrap.rmf.codegen.rendering.utils.keepIndentation
import io.vrap.rmf.codegen.types.VrapArrayType
import io.vrap.rmf.codegen.types.VrapObjectType
import io.vrap.rmf.codegen.types.VrapTypeProvider
import io.vrap.rmf.raml.model.types.BooleanInstance
import io.vrap.rmf.raml.model.types.ObjectType
import io.vrap.rmf.raml.model.types.Property
import io.vrap.rmf.raml.model.types.UnionType
import io.vrap.rmf.raml.model.types.*
import io.vrap.rmf.raml.model.types.Annotation


class JavaModelClassFileProducer constructor(override val vrapTypeProvider: VrapTypeProvider, @AllObjectTypes private val allObjectTypes: List<ObjectType>) : JavaObjectTypeExtensions, JavaEObjectTypeExtensions, FileProducer {
Expand All @@ -28,6 +27,17 @@ class JavaModelClassFileProducer constructor(override val vrapTypeProvider: Vrap

val vrapType = vrapTypeProvider.doSwitch(type).toJavaVType() as VrapObjectType

val implements = Lists.newArrayList(vrapType.simpleClassName, "ModelBase")
.plus(
when (val ex = type.getAnnotation("java-impl-implements") ) {
is Annotation -> {
(ex.value as StringInstance).value.escapeAll()
}
else -> null
}
)
.filterNotNull()

val content = """
|package ${vrapType.`package`.toJavaPackage()};
|
Expand All @@ -47,13 +57,15 @@ class JavaModelClassFileProducer constructor(override val vrapTypeProvider: Vrap
|import com.fasterxml.jackson.annotation.JsonProperty;
|import org.apache.commons.lang3.builder.EqualsBuilder;
|import org.apache.commons.lang3.builder.HashCodeBuilder;
|import org.apache.commons.lang3.builder.ToStringBuilder;
|import org.apache.commons.lang3.builder.ToStringStyle;
|
|/**
|${type.toComment(" * ${vrapType.simpleClassName}").escapeAll()}
| */
|<${JavaSubTemplates.generatedAnnotation}>${if (type.markDeprecated()) """
|@Deprecated""" else ""}
|public class ${vrapType.simpleClassName}Impl implements ${vrapType.simpleClassName}, ModelBase {
|public class ${vrapType.simpleClassName}Impl implements ${implements.joinToString(separator = ", ")} {
|
| <${type.beanFields().escapeAll()}>
|
Expand All @@ -65,6 +77,7 @@ class JavaModelClassFileProducer constructor(override val vrapTypeProvider: Vrap
|
| <${type.equalsMethod().escapeAll()}>
|
| <${type.getAnnotation("java-impl-mixin")?.value?.value?.let { (it as String).escapeAll()} ?: ""}>
|}
""".trimMargin().keepIndentation()
return TemplateFile(
Expand Down Expand Up @@ -116,26 +129,43 @@ class JavaModelClassFileProducer constructor(override val vrapTypeProvider: Vrap
| <${this.allProperties.filterNot { it.deprecated() }.joinToString("\n") { it.hashMethod() }}>
| .toHashCode();
|}
|
|@Override
|public String toString() {
| return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
| <${this.allProperties.filterNot { it.deprecated() }.joinToString("\n") { it.toStringMethod() }}>
| .build();
|}
""".trimMargin().keepIndentation()
}

private fun Property.equalsMethod(): String {
if (this.isPatternProperty()) {
return ".append(values, that.values)"
return if (this.isPatternProperty()) {
".append(values, that.values)"
} else if (this.name.equals("interface")) {
return ".append(_interface, that._interface)"
".append(_interface, that._interface)"
} else {
return ".append(${this.name.lowerCamelCase()}, that.${this.name.lowerCamelCase()})"
".append(${this.name.lowerCamelCase()}, that.${this.name.lowerCamelCase()})"
}
}

private fun Property.hashMethod(): String {
if (this.isPatternProperty()) {
return ".append(values)"
return if (this.isPatternProperty()) {
".append(values)"
} else if (this.name.equals("interface")) {
".append(_interface)"
} else {
".append(${this.name.lowerCamelCase()})"
}
}

private fun Property.toStringMethod(): String {
return if (this.isPatternProperty()) {
".append(\"values\", values)"
} else if (this.name.equals("interface")) {
return ".append(_interface)"
".append(\"interface\", _interface)"
} else {
return ".append(${this.name.lowerCamelCase()})"
".append(\"${this.name.lowerCamelCase()}\", ${this.name.lowerCamelCase()})"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ export function buildRelativeUri(commonRequest: ClientRequest): string {
var uri: string = commonRequest.uriTemplate as string
for (const param in pathMap) {
uri = uri.replace(`{${'$'}{param}}`, `${'$'}{pathMap[param]}`)
const value = encodeURIComponent(`${'$'}{pathMap[param]}`)
uri = uri.replace(`{${'$'}{param}}`, `${'$'}{value}`)
}
const resQuery = formatQueryString(commonRequest.queryParams || {})
Expand Down
2 changes: 1 addition & 1 deletion node/rmf-codegen/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@commercetools-docs/rmf-codegen",
"version": "13.29.0",
"version": "13.30.0",
"description": "Provides RMF-Codegen to javascript projects",
"license": "MIT",
"homepage": "https://github.com/commercetools/rmf-codegen",
Expand Down
2 changes: 1 addition & 1 deletion scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

set -e

CODEGEN_VERSION=${VRAP_VERSION:-"1.0.0-20231012134051"}
CODEGEN_VERSION=${VRAP_VERSION:-"1.0.0-20231113134915"}
CLI_HOME=~/.rmf-cli
LIB_FOLDER=$CLI_HOME/lib
JAR_FILE_PATH=$LIB_FOLDER/codegen-cli-${CODEGEN_VERSION}.jar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ class ValidateSubcommand : Callable<Int> {
@CommandLine.Option(names = ["--list-rules"], description = ["Show all rules"])
var listRules: Boolean = false

@CommandLine.Option(names = ["-v", "--verbose"], description = ["Verbose"])
var verbose: Boolean = false;

lateinit var modelBuilder: RamlModelBuilder

private fun linkURI(): java.net.URI {
Expand All @@ -97,7 +100,7 @@ class ValidateSubcommand : Callable<Int> {
return 0
}
val tmpDir = tempFile?.toAbsolutePath()?.normalize() ?: Paths.get(".tmp")
modelBuilder = setupValidators()
modelBuilder = setupValidators(verbose)
val res = safeRun { validate(tmpDir)}
if (watch) {
val watchDir = ramlFileLocation.toRealPath().toAbsolutePath().parent
Expand Down Expand Up @@ -182,9 +185,9 @@ class ValidateSubcommand : Callable<Int> {
return modelResult.validationResults.any { result -> result.severity >= checkSeverity.value }.let { b -> if(b) 1 else 0 }
}

private fun setupValidators(): RamlModelBuilder {
private fun setupValidators(verbose: Boolean = false): RamlModelBuilder {
val ruleset = rulesetFile?.toFile()?.inputStream() ?: ValidateSubcommand::class.java.getResourceAsStream("/ruleset.xml")
return RamlModelBuilder(ValidatorSetup.setup(ruleset))
return RamlModelBuilder(ValidatorSetup.setup(ruleset, verbose))
}

private fun diagnosticFormatter(printer: OutputFormat, filePath: Path, linkUri: java.net.URI): FormatPrinter {
Expand Down

0 comments on commit 68d2b46

Please sign in to comment.