11package org.evomaster.core.search.gene.jsonpatch
22
3+ import org.evomaster.core.output.OutputFormat
34import org.evomaster.core.search.gene.Gene
45import org.evomaster.core.search.gene.root.CompositeFixedGene
56import org.evomaster.core.search.gene.utils.GeneUtils
@@ -10,6 +11,10 @@ import org.evomaster.core.search.service.mutator.genemutation.SubsetGeneMutation
1011/* *
1112 * Base class for all JSON Patch operation genes.
1213 * Each operation gene knows its operation name (op) and carries the relevant field genes.
14+ *
15+ * Serialization for all subtypes lives here: the when(this) block is intentional — this is a
16+ * closed hierarchy with exactly three known subtypes, so the parent knowing their structure
17+ * keeps all printing logic in one place.
1318 */
1419abstract class JsonPatchOperationGene (
1520 name : String ,
@@ -26,21 +31,38 @@ abstract class JsonPatchOperationGene(
2631 const val OP_TEST = " test"
2732 }
2833
29- /* * A single field in a JSON Patch operation, with its serialized value.
30- * [quoted] controls whether the value is wrapped in quotes in JSON output
31- * (true for string fields like path/from; false for typed fields like value). */
32- protected data class OpField (val name : String , val value : String , val quoted : Boolean = true )
33-
34- protected fun formatOperation (mode : GeneUtils .EscapeMode ? , vararg fields : OpField ): String {
35- return if (mode == GeneUtils .EscapeMode .XML ) {
36- val inner = fields.joinToString(" " ) { " <${it.name} >${it.value} </${it.name} >" }
37- " <operation><op>$operationName </op>$inner </operation>"
38- } else {
39- val parts = fields.joinToString(" ," ) { f ->
40- if (f.quoted) " \" ${f.name} \" :\" ${f.value} \" " else " \" ${f.name} \" :${f.value} "
34+ override fun getValueAsPrintableString (
35+ previousGenes : List <Gene >,
36+ mode : GeneUtils .EscapeMode ? ,
37+ targetFormat : OutputFormat ? ,
38+ extraCheck : Boolean
39+ ): String {
40+ val fields = when (this ) {
41+ is JsonPatchPathOnlyGene -> {
42+ val path = pathGene.getValueAsPrintableString(previousGenes, mode, targetFormat, extraCheck)
43+ if (mode == GeneUtils .EscapeMode .XML ) " <path>$path </path>"
44+ else " \" path\" :\" $path \" "
45+ }
46+ is JsonPatchFromPathGene -> {
47+ val from = fromGene.getValueAsPrintableString(previousGenes, mode, targetFormat, extraCheck)
48+ val path = pathGene.getValueAsPrintableString(previousGenes, mode, targetFormat, extraCheck)
49+ if (mode == GeneUtils .EscapeMode .XML ) " <from>$from </from><path>$path </path>"
50+ else " \" from\" :\" $from \" ,\" path\" :\" $path \" "
51+ }
52+ is JsonPatchPathValueGene -> {
53+ val pair = pathValueChoice.activeGene()
54+ val path = pair.first.getValueAsPrintableString(previousGenes, mode, targetFormat, extraCheck)
55+ // value is unquoted in JSON since it can be any type (string, number, boolean, etc.)
56+ val value = pair.second.getValueAsPrintableString(previousGenes, mode, targetFormat, extraCheck)
57+ if (mode == GeneUtils .EscapeMode .XML ) " <path>$path </path><value>$value </value>"
58+ else " \" path\" :\" $path \" ,\" value\" :$value "
4159 }
42- " { \" op \" : \" $operationName \" , $parts } "
60+ else -> throw IllegalStateException ( " Unknown JsonPatchOperationGene subtype: ${ this :: class } " )
4361 }
62+ return if (mode == GeneUtils .EscapeMode .XML )
63+ " <operation><op>$operationName </op>$fields </operation>"
64+ else
65+ " {\" op\" :\" $operationName \" ,$fields }"
4466 }
4567
4668 override fun checkForLocallyValidIgnoringChildren () = true
0 commit comments