• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.networknt.schema;
2 
3 import com.fasterxml.jackson.databind.JsonNode;
4 import com.networknt.schema.i18n.MessageSource;
5 import com.networknt.schema.utils.StringUtils;
6 
7 import java.util.Collections;
8 import java.util.LinkedHashMap;
9 import java.util.Map;
10 import java.util.Objects;
11 
12 public abstract class ValidationMessageHandler {
13     protected final MessageSource messageSource;
14     protected ErrorMessageType errorMessageType;
15 
16     protected SchemaLocation schemaLocation;
17     protected JsonNodePath evaluationPath;
18     protected JsonSchema evaluationParentSchema;
19 
20     protected JsonSchema parentSchema;
21 
22     protected boolean customErrorMessagesEnabled;
23     protected Map<String, String> errorMessage;
24 
25     protected Keyword keyword;
26 
ValidationMessageHandler(ErrorMessageType errorMessageType, boolean customErrorMessagesEnabled, MessageSource messageSource, Keyword keyword, JsonSchema parentSchema, SchemaLocation schemaLocation, JsonNodePath evaluationPath)27     protected ValidationMessageHandler(ErrorMessageType errorMessageType, boolean customErrorMessagesEnabled,
28             MessageSource messageSource, Keyword keyword, JsonSchema parentSchema, SchemaLocation schemaLocation,
29             JsonNodePath evaluationPath) {
30         this.errorMessageType = errorMessageType;
31         this.messageSource = messageSource;
32         this.schemaLocation = Objects.requireNonNull(schemaLocation);
33         this.evaluationPath = Objects.requireNonNull(evaluationPath);
34         this.parentSchema = parentSchema;
35         this.customErrorMessagesEnabled = customErrorMessagesEnabled;
36         updateKeyword(keyword);
37     }
38 
39     /**
40      * Copy constructor.
41      *
42      * @param copy to copy from
43      */
ValidationMessageHandler(ValidationMessageHandler copy)44     protected ValidationMessageHandler(ValidationMessageHandler copy) {
45         this.messageSource = copy.messageSource;
46         this.errorMessageType = copy.errorMessageType;
47         this.schemaLocation = copy.schemaLocation;
48         this.evaluationPath = copy.evaluationPath;
49         this.parentSchema = copy.parentSchema;
50         this.evaluationParentSchema = copy.evaluationParentSchema;
51         this.customErrorMessagesEnabled = copy.customErrorMessagesEnabled;
52         this.errorMessage = copy.errorMessage;
53         this.keyword = copy.keyword;
54     }
55 
message()56     protected MessageSourceValidationMessage.Builder message() {
57         return MessageSourceValidationMessage.builder(this.messageSource, this.errorMessage, (message, failFast) -> {
58             if (failFast) {
59                 throw new FailFastAssertionException(message);
60             }
61         }).code(getErrorMessageType().getErrorCode()).schemaLocation(this.schemaLocation)
62                 .evaluationPath(this.evaluationPath).type(this.keyword != null ? this.keyword.getValue() : null)
63                 .messageKey(getErrorMessageType().getErrorCodeValue());
64     }
65 
66     protected ErrorMessageType getErrorMessageType() {
67         return this.errorMessageType;
68     }
69 
70     protected void parseErrorCode(String errorCodeKey) {
71         if (errorCodeKey != null && this.parentSchema != null) {
72             JsonNode errorCodeNode = this.parentSchema.getSchemaNode().get(errorCodeKey);
73             if (errorCodeNode != null && errorCodeNode.isTextual()) {
74                 String errorCodeText = errorCodeNode.asText();
75                 if (StringUtils.isNotBlank(errorCodeText)) {
76                     this.errorMessageType = CustomErrorMessageType.of(errorCodeText);
77                 }
78             }
79         }
80     }
81 
82     protected void updateValidatorType(ValidatorTypeCode validatorTypeCode) {
83         updateKeyword(validatorTypeCode);
84         updateErrorMessageType(validatorTypeCode);
85     }
86 
87     protected void updateErrorMessageType(ErrorMessageType errorMessageType) {
88         this.errorMessageType = errorMessageType;
89     }
90 
91     protected void updateKeyword(Keyword keyword) {
92         this.keyword = keyword;
93         if (this.keyword != null) {
94             if (this.customErrorMessagesEnabled && keyword != null && parentSchema != null) {
95                 this.errorMessage = getErrorMessage(parentSchema.getSchemaNode(), keyword.getValue());
96             }
97             parseErrorCode(getErrorCodeKey(keyword.getValue()));
98         }
99     }
100 
101     /**
102      * Gets the custom error message to use.
103      *
104      * @param schemaNode the schema node
105      * @param keyword    the keyword
106      * @return the custom error message
107      */
108     protected Map<String, String> getErrorMessage(JsonNode schemaNode, String keyword) {
109         final JsonSchema parentSchema = this.parentSchema;
110         final JsonNode message = getMessageNode(schemaNode, parentSchema, keyword);
111         if (message != null) {
112             JsonNode messageNode = message.get(keyword);
113             if (messageNode != null) {
114                 if (messageNode.isTextual()) {
115                     return Collections.singletonMap("", messageNode.asText());
116                 } else if (messageNode.isObject()) {
117                     Map<String, String> result = new LinkedHashMap<>();
118                     messageNode.fields().forEachRemaining(entry -> {
119                         result.put(entry.getKey(), entry.getValue().textValue());
120                     });
121                     if (!result.isEmpty()) {
122                         return result;
123                     }
124                 }
125             }
126         }
127         return Collections.emptyMap();
128     }
129 
130     protected JsonNode getMessageNode(JsonNode schemaNode, JsonSchema parentSchema, String pname) {
131         if (schemaNode.get("message") != null && schemaNode.get("message").get(pname) != null) {
132             return schemaNode.get("message");
133         }
134         JsonNode messageNode;
135         messageNode = schemaNode.get("message");
136         if (messageNode == null && parentSchema != null) {
137             messageNode = parentSchema.schemaNode.get("message");
138             if (messageNode == null) {
139                 return getMessageNode(parentSchema.schemaNode, parentSchema.getParentSchema(), pname);
140             }
141         }
142         return messageNode;
143     }
144 
145     protected String getErrorCodeKey(String keyword) {
146         if (keyword != null) {
147             return keyword + "ErrorCode";
148         }
149         return null;
150     }
151 }
152