Skip to content

Commit a752471

Browse files
Try propagating placeholder values using existing code generators
1 parent 2fffa78 commit a752471

File tree

5 files changed

+54
-20
lines changed

5 files changed

+54
-20
lines changed

java/src/main/kotlin/io/spine/validation/java/CodeGenerator.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import com.squareup.javapoet.CodeBlock
3232
import io.spine.logging.WithLogging
3333
import io.spine.protodata.java.Expression
3434
import io.spine.tools.java.codeBlock
35-
import io.spine.validation.ErrorMessage
3635
import io.spine.validation.Rule.KindCase.COMPOSITE
3736
import io.spine.validation.Rule.KindCase.MESSAGE_WIDE
3837
import io.spine.validation.Rule.KindCase.SIMPLE
@@ -98,7 +97,7 @@ internal abstract class CodeGenerator(
9897
/**
9998
* Forms an error message for the found violation.
10099
*/
101-
abstract fun error(): ErrorMessage
100+
abstract fun error(): Pair<String, Map<Expression<*>, Expression<*>>>
102101

103102
/**
104103
* Constructs code which creates a `ConstrainViolation` and puts it into a list of violations.

java/src/main/kotlin/io/spine/validation/java/DistributingGenerator.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ import io.spine.string.titleCase
4747
import io.spine.tools.java.codeBlock
4848
import io.spine.tools.java.methodSpec
4949
import io.spine.validate.ConstraintViolation
50-
import io.spine.validation.ErrorMessage
5150
import javax.lang.model.element.Modifier
5251

5352
/**
@@ -146,7 +145,7 @@ internal class DistributingGenerator(
146145
return MethodCall(violationsName, "isEmpty")
147146
}
148147

149-
override fun error(): ErrorMessage =
148+
override fun error(): Pair<String, Map<Expression<*>, Expression<*>>> =
150149
delegate.error()
151150

152151
override fun createViolation(): CodeBlock = codeBlock {

java/src/main/kotlin/io/spine/validation/java/ErrorMessages.kt

+13-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import io.spine.protodata.java.call
4141
import io.spine.protodata.java.newBuilder
4242
import io.spine.protodata.ast.isList
4343
import io.spine.protodata.ast.isMap
44+
import io.spine.protodata.java.mapExpression
4445
import io.spine.protodata.java.packToAny
4546
import io.spine.validate.ConstraintViolation
4647
import io.spine.validate.TemplateString
@@ -88,7 +89,7 @@ public fun ErrorMessage.createCompositeViolation(
8889
return addViolation(violation, violationsList)
8990
}
9091

91-
private fun addViolation(
92+
public fun addViolation(
9293
violation: Expression<ConstraintViolation>,
9394
violationsList: Expression<MutableList<ConstraintViolation>>
9495
): CodeBlock = CodeBlock.builder()
@@ -100,9 +101,19 @@ private fun ErrorMessage.buildViolation(
100101
field: Field?,
101102
fieldValue: Expression<*>?,
102103
ignoreCardinality: Boolean = false
104+
) = buildViolation(this.toString(), type, field, fieldValue, ignoreCardinality)
105+
106+
public fun buildViolation(
107+
errorMessage: String,
108+
type: TypeName,
109+
field: Field?,
110+
fieldValue: Expression<*>?,
111+
ignoreCardinality: Boolean = false,
112+
placeholders: Map<Expression<*>, Expression<*>> = emptyMap() // TODO: Fix in ProtoData.
103113
): Expression<ConstraintViolation> {
104114
val message = ClassName(TemplateString::class).newBuilder()
105-
.chainSet("withPlaceholders", Literal(this))
115+
.chainSet("withPlaceholders", Literal(errorMessage))
116+
.chainPutAll("placeholderValue", mapExpression(ClassName(String::class), ClassName(String::class), placeholders))
106117
.chainBuild<TemplateString>()
107118
var violationBuilder = ClassName(ConstraintViolation::class).newBuilder()
108119
.chainSet("message", message)

java/src/main/kotlin/io/spine/validation/java/RequiredOneofGenerator.kt

+14-5
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626

2727
package io.spine.validation.java
2828

29+
import com.squareup.javapoet.CodeBlock
2930
import io.spine.protodata.ast.Cardinality.CARDINALITY_SINGLE
3031
import io.spine.protodata.ast.OneofName
3132
import io.spine.protodata.java.Expression
3233
import io.spine.protodata.java.field
33-
import io.spine.validation.ErrorMessage
3434

3535
/**
3636
* A code generator for the `(is_required)` constraint.
@@ -54,9 +54,18 @@ internal class RequiredOneofGenerator(
5454
return Expression("$numberGetter != 0")
5555
}
5656

57-
override fun error() =
58-
ErrorMessage.forRule(rule.errorMessage)
57+
override fun error() = rule.errorMessage to emptyMap<Expression<*>, Expression<*>>()
5958

60-
override fun createViolation() =
61-
error().createViolation(ctx)
59+
override fun createViolation(): CodeBlock {
60+
val error = error()
61+
val violation = buildViolation(
62+
error.first,
63+
ctx.validatedType,
64+
ctx.fieldFromSimpleRule,
65+
ctx.fieldOrElement,
66+
ignoreCardinality = ctx.isElement,
67+
error.second
68+
)
69+
return addViolation(violation, ctx.violationList)
70+
}
6271
}

java/src/main/kotlin/io/spine/validation/java/SimpleRuleGenerator.kt

+25-9
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ import io.spine.protodata.ast.PrimitiveType.TYPE_STRING
3333
import io.spine.protodata.ast.Type
3434
import io.spine.protodata.ast.isList
3535
import io.spine.protodata.ast.isMap
36+
import io.spine.protodata.ast.qualifiedName
37+
import io.spine.protodata.ast.typeName
3638
import io.spine.protodata.java.ClassName
3739
import io.spine.protodata.java.Expression
40+
import io.spine.protodata.java.StringLiteral
3841
import io.spine.protodata.java.call
3942
import io.spine.protodata.value.Value
4043
import io.spine.string.shortly
@@ -45,7 +48,6 @@ import io.spine.validation.ComparisonOperator.GREATER_THAN
4548
import io.spine.validation.ComparisonOperator.LESS_OR_EQUAL
4649
import io.spine.validation.ComparisonOperator.LESS_THAN
4750
import io.spine.validation.ComparisonOperator.NOT_EQUAL
48-
import io.spine.validation.ErrorMessage
4951
import io.spine.validation.SimpleRule
5052
import io.spine.validation.SimpleRule.OperatorKindCase.CUSTOM_OPERATOR
5153
import io.spine.validation.SimpleRule.OperatorKindCase.OPERATOR
@@ -142,18 +144,32 @@ internal open class SimpleRuleGenerator(ctx: GenerationContext) : CodeGenerator(
142144
PRIMITIVE_COMPARISON_OPS
143145
}
144146

145-
override fun error(): ErrorMessage {
146-
val actualValue = ClassName(String::class)
147+
override fun error(): Pair<String, Map<Expression<*>, Expression<*>>> {
148+
val fieldValue = ClassName(String::class)
147149
.call<String>("valueOf", ctx.fieldOrElement!!)
148-
return ErrorMessage.forRule(
149-
rule.errorMessage,
150-
actualValue.toCode(),
151-
otherValue?.toCode()
150+
val fieldPath = rule.field.value
151+
val fieldType = ctx.simpleRuleField.type.typeName.qualifiedName
152+
val parentType = ctx.validatedType.qualifiedName
153+
return rule.errorMessage to mapOf(
154+
StringLiteral("field.path") to StringLiteral(fieldPath),
155+
StringLiteral("parent.type") to StringLiteral(parentType),
156+
StringLiteral("field.type") to StringLiteral(fieldType),
157+
StringLiteral("field.value") to fieldValue
152158
)
153159
}
154160

155-
override fun createViolation(): CodeBlock =
156-
error().createViolation(ctx)
161+
override fun createViolation(): CodeBlock {
162+
val error = error()
163+
val violation = buildViolation(
164+
error.first,
165+
ctx.validatedType,
166+
ctx.fieldFromSimpleRule,
167+
ctx.fieldOrElement,
168+
ignoreCardinality = ctx.isElement,
169+
error.second
170+
)
171+
return addViolation(violation, ctx.violationList)
172+
}
157173
}
158174

159175
internal fun generatorForSimple(ctx: GenerationContext): CodeGenerator {

0 commit comments

Comments
 (0)