@@ -12,16 +12,11 @@ import dev.harrel.jsonschema.FormatEvaluatorFactory
1212import dev.harrel.jsonschema.JsonNode
1313import dev.harrel.jsonschema.providers.OrgJsonNode
1414
15- import java.util.regex.Pattern
16- import java.util.regex.Matcher
17-
18- import static nextflow.validation.utils.Common.getValueFromJsonPointer
19- import static nextflow.validation.utils.Common.findAllKeys
20- import static nextflow.validation.utils.Common.kebabToCamel
21- import static nextflow.validation.utils.Types.isInteger
2215import nextflow.validation.config.ValidationConfig
2316import nextflow.validation.exceptions.SchemaValidationException
2417import nextflow.validation.validators.evaluators.CustomEvaluatorFactory
18+ import nextflow.validation.validators.ValidationResult
19+ import static nextflow.validation.utils.Common.getValueFromJsonPointer
2520
2621/**
2722 * @author : nvnieuwk <[email protected] > @@ -31,7 +26,6 @@ import nextflow.validation.validators.evaluators.CustomEvaluatorFactory
3126public class JsonSchemaValidator {
3227
3328 private ValidatorFactory validator
34- private Pattern uriPattern = Pattern . compile(' ^#/(\\ d*)?/?(.*)$' )
3529 private ValidationConfig config
3630
3731 JsonSchemaValidator (ValidationConfig config ) {
@@ -42,10 +36,12 @@ public class JsonSchemaValidator {
4236 this . config = config
4337 }
4438
45- private Tuple2< List< String > , List< String > > validateObject (JsonNode input , String validationType , Object rawJson , String schemaFileName ) {
39+ private ValidationResult validateObject (JsonNode input , Object rawJson , String schemaFileName ) {
4640 def JSONObject schema
41+ def String schemaString
4742 try {
48- schema = new JSONObject (Files . readString(Path . of(schemaFileName)))
43+ schemaString = Files . readString(Path . of(schemaFileName))
44+ schema = new JSONObject (schemaString)
4945 } catch (org.json.JSONException e) {
5046 throw new SchemaValidationException (""" Failed to load JSON schema (${ schemaFileName} ):
5147 ${ e.message}
@@ -64,106 +60,13 @@ public class JsonSchemaValidator {
6460 """ )
6561 throw new SchemaValidationException (" " , [])
6662 }
67-
6863 def Validator.Result result = this . validator. validate(schema, input)
69- def List<String > errors = []
70- result. getErrors(). each { error ->
71- def String errorString = error. getError()
72-
73- // Skip double error in the parameter schema
74- if (errorString. startsWith(" Value does not match against the schemas at indexes" ) && validationType == " parameter" ) {
75- return
76- }
77-
78- def String instanceLocation = error. getInstanceLocation()
79- def String value = getValueFromJsonPointer(instanceLocation, rawJson)
80- if (config. maxErrValSize >= 1 && value. size() > config. maxErrValSize) {
81- value = " ${ value[0..(config.maxErrValSize/2-1)]} ...${ value[-config.maxErrValSize/2..-1]} " as String
82- }
83-
84- // Return a standard error message for object validation
85- if (validationType == " object" ) {
86- errors. add(" ${ instanceLocation ? instanceLocation + ' ' : ''} (${ value} ): ${ errorString} " as String )
87- return
88- }
89-
90- // Get the custom errorMessage if there is one and the validation errors are not about the content of the file
91- def String schemaLocation = error. getSchemaLocation(). replaceFirst(/ ^[^#]+/ , " " )
92- def String customError = " "
93- if (! errorString. startsWith(" Validation of file failed:" )) {
94- customError = getValueFromJsonPointer(" ${ schemaLocation} /errorMessage" , schema) as String
95- }
96-
97- // Change some error messages to make them more clear
98- def String keyword = error. getKeyword()
99- if (keyword == " required" ) {
100- def Matcher matcher = errorString =~ ~/ \[\[ ([^\[\] ]*)\]\] $/
101- def String missingKeywords = matcher. findAll(). flatten(). last()
102- errorString = " Missing required ${ validationType} (s): ${ missingKeywords} "
103- }
104-
105- def List<String > locationList = instanceLocation. split(" /" ). findAll { it != " " } as List
106-
107- def String printableError = " ${ validationType == 'field' ? '->' : '*'} ${ errorString} " as String
108- if (locationList. size() > 0 && isInteger(locationList[0 ]) && validationType == " field" ) {
109- def Integer entryInteger = locationList[0 ] as Integer
110- def String entryString = " Entry ${ entryInteger + 1} " as String
111- def String fieldError = " ${ errorString} " as String
112- if (locationList. size() > 1 ) {
113- fieldError = " Error for ${ validationType} '${ locationList[1..-1].join("/")} ' (${ value} ): ${ errorString} "
114- }
115- printableError = " -> ${ entryString} : ${ fieldError} " as String
116- } else if (validationType == " parameter" ) {
117- def String fieldName = locationList. join(" ." )
118- if (fieldName != " " ) {
119- printableError = " * --${ fieldName} (${ value} ): ${ errorString} " as String
120- }
121- }
122-
123- if (customError != " " ) {
124- printableError = printableError + " (${ customError} )"
125- }
126-
127- errors. add(printableError)
128-
129- }
130- def List<String > unevaluated = []
131- if (errors. size() == 0 ) {
132- unevaluated = getUnevaluated(result, rawJson)
133- }
134- return Tuple . tuple(errors, unevaluated)
135- }
136-
137- public Tuple2<List<String > ,List<String > > validate (JSONArray input , String schemaFileName ) {
138- def JsonNode jsonInput = new OrgJsonNode.Factory (). wrap(input)
139- return this . validateObject(jsonInput, " field" , input, schemaFileName)
64+ return new ValidationResult (result, rawJson, schemaString, config)
14065 }
14166
142- public Tuple2< List< String > , List< String > > validate (JSONObject input , String schemaFileName ) {
67+ public ValidationResult validate (Object input , String schemaFileName ) {
14368 def JsonNode jsonInput = new OrgJsonNode.Factory (). wrap(input)
144- return this . validateObject(jsonInput, " parameter " , input, schemaFileName)
69+ return this . validateObject(jsonInput, input, schemaFileName)
14570 }
14671
147- public Tuple2<List<String > ,List<String > > validateObj (Object input , String schemaFileName ) {
148- def JsonNode jsonInput = new OrgJsonNode.Factory (). wrap(input)
149- return this . validateObject(jsonInput, " object" , input, schemaFileName)
150- }
151-
152- public static List<String > getUnevaluated (Validator.Result result , Object rawJson ) {
153- def Set<String > evaluated = []
154- result. getAnnotations(). each{ anno ->
155- if (anno. keyword in [" properties" , " patternProperties" , " additionalProperties" ]){
156- evaluated. addAll(
157- anno. annotation. collect{ it ->
158- " ${ anno.instanceLocation.toString()} /${ it.toString()} " . replaceAll(" ^/+" , " " )
159- }
160- )
161- }
162- }
163- def Set<String > all_keys = []
164- findAllKeys(rawJson, null , all_keys, ' /' )
165- def unevaluated_ = all_keys - evaluated
166- def unevaluated = unevaluated_. collect{ it -> ! evaluated. contains(kebabToCamel(it)) ? it : null }
167- return unevaluated - null
168- }
16972}
0 commit comments