1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.forgerock.api.jackson;
18
19 import static org.forgerock.api.jackson.JacksonUtils.validateEnum;
20 import static org.forgerock.api.util.ValidationUtil.isEmpty;
21
22 import com.fasterxml.jackson.annotation.JsonProperty;
23 import com.fasterxml.jackson.module.jsonSchema.jakarta.types.StringSchema;
24 import jakarta.mail.internet.AddressException;
25 import jakarta.mail.internet.InternetAddress;
26 import jakarta.validation.ValidationException;
27 import java.net.URI;
28 import java.time.LocalDate;
29 import java.time.LocalDateTime;
30 import java.time.format.DateTimeParseException;
31 import java.util.Collections;
32 import java.util.List;
33 import java.util.Map;
34 import org.forgerock.api.enums.ReadPolicy;
35 import org.forgerock.api.enums.WritePolicy;
36 import org.forgerock.json.JsonValue;
37 import org.wrensecurity.guava.common.net.InetAddresses;
38 import org.wrensecurity.guava.common.net.InternetDomainName;
39
40
41
42
43 class CrestStringSchema extends StringSchema implements CrestReadWritePoliciesSchema, OrderedFieldSchema, EnumSchema,
44 ValidatableSchema, PropertyFormatSchema, WithExampleSchema<String> {
45 private WritePolicy writePolicy;
46 private ReadPolicy readPolicy;
47 private Boolean errorOnWritePolicyFailure;
48 private Boolean returnOnDemand;
49 private Integer propertyOrder;
50 private String propertyFormat;
51 @JsonProperty
52 private Map<String, List<String>> options;
53 private String example;
54
55 @Override
56 public WritePolicy getWritePolicy() {
57 return writePolicy;
58 }
59
60 @Override
61 public void setWritePolicy(WritePolicy policy) {
62 this.writePolicy = policy;
63 }
64
65 @Override
66 public ReadPolicy getReadPolicy() {
67 return readPolicy;
68 }
69
70 @Override
71 public void setReadPolicy(ReadPolicy readPolicy) {
72 this.readPolicy = readPolicy;
73 }
74
75 @Override
76 public Boolean getErrorOnWritePolicyFailure() {
77 return errorOnWritePolicyFailure;
78 }
79
80 @Override
81 public void setErrorOnWritePolicyFailure(Boolean errorOnWritePolicyFailure) {
82 this.errorOnWritePolicyFailure = errorOnWritePolicyFailure;
83 }
84
85 @Override
86 public Boolean getReturnOnDemand() {
87 return returnOnDemand;
88 }
89
90 @Override
91 public void setReturnOnDemand(Boolean returnOnDemand) {
92 this.returnOnDemand = returnOnDemand;
93 }
94
95 @Override
96 public Integer getPropertyOrder() {
97 return propertyOrder;
98 }
99
100 @Override
101 public void setPropertyOrder(Integer order) {
102 this.propertyOrder = order;
103 }
104
105 @Override
106 public List<String> getEnumTitles() {
107 return options == null ? null : options.get(ENUM_TITLES);
108 }
109
110 @Override
111 public void setEnumTitles(List<String> titles) {
112 this.options = Collections.singletonMap(ENUM_TITLES, titles);
113 }
114
115 @Override
116 public void validate(JsonValue object) throws ValidationException {
117 if (!object.isString()) {
118 throw new ValidationException("Expected string but got: " + object.getObject());
119 }
120 String s = object.asString();
121 validateEnum(enums, s);
122 if (!isEmpty(propertyFormat)) {
123 validateFormat(s);
124 }
125 }
126
127
128
129
130
131
132
133
134 private void validateFormat(final String s) throws ValidationException {
135 switch (propertyFormat) {
136 case "date-time":
137
138 try {
139 LocalDateTime.parse(s);
140 } catch (DateTimeParseException e) {
141 throw new ValidationException("Expected date-time format, but got " + s, e);
142 }
143 return;
144 case "date":
145 case "full-date":
146
147
148 try {
149 LocalDate.parse(s);
150 } catch (DateTimeParseException e) {
151 throw new ValidationException("Expected date/full-date format, but got " + s, e);
152 }
153 return;
154 case "email":
155
156 try {
157 new InternetAddress(s).validate();
158 } catch (AddressException e) {
159 throw new ValidationException("Expected email, but got " + s, e);
160 }
161 return;
162 case "hostname":
163
164 if (!InternetDomainName.isValid(s)) {
165 throw new ValidationException("Expected host-name, but got " + s);
166 }
167 return;
168 case "ipv4":
169
170 if (!InetAddresses.isInetAddress(s) || s.indexOf(':') != -1) {
171 throw new ValidationException("Expected ipv4, but got " + s);
172 }
173 return;
174 case "ipv6":
175
176 if (!InetAddresses.isInetAddress(s) || s.indexOf(':') == -1) {
177 throw new ValidationException("Expected ipv6, but got " + s);
178 }
179 return;
180 case "uri":
181
182 try {
183 URI.create(s);
184 } catch (IllegalArgumentException e) {
185 throw new ValidationException("Expected URI format, but got " + s, e);
186 }
187 return;
188 }
189 }
190
191
192 @JsonProperty("format")
193 @Override
194 public String getPropertyFormat() {
195 if (!isEmpty(propertyFormat)) {
196 return propertyFormat;
197 }
198
199 return format == null ? null : format.toString();
200 }
201
202 @Override
203 public void setPropertyFormat(String propertyFormat) {
204 this.propertyFormat = propertyFormat;
205 }
206
207 @Override
208 public String getExample() {
209 return example;
210 }
211
212 @Override
213 public void setExample(String example) {
214 this.example = example;
215 }
216 }