1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package ca.uhn.hl7v2.validation.builder;
27
28 import java.io.Serializable;
29 import java.util.Arrays;
30 import java.util.Collection;
31 import java.util.regex.Pattern;
32
33 import ca.uhn.hl7v2.validation.ValidationException;
34
35
36
37
38
39
40
41 @SuppressWarnings("serial")
42 public abstract class BuilderSupport implements Serializable {
43
44 protected BuilderSupport() {
45 }
46
47
48
49
50
51
52 public Predicate isEqual(Object expected) {
53 return new EqualsPredicate(expected);
54 }
55
56
57
58
59
60
61 public Predicate isEqualIgnoreCase(Object expected) {
62 return new EqualsPredicate(expected, true);
63 }
64
65
66
67
68
69 public Predicate empty() {
70 return new EmptyPredicate();
71 }
72
73
74
75
76
77
78 public Predicate./../../../../ca/uhn/hl7v2/validation/builder/Predicate.html#Predicate">Predicate emptyOr(Predicate predicate) {
79 return anyOf(empty(), predicate);
80 }
81
82
83
84
85
86
87 public Predicate matches(String regex) {
88 return new MatchesPredicate(regex);
89 }
90
91
92
93
94
95
96
97 public Predicate matches(String regex, String description) {
98 return new MatchesPredicate(regex, description);
99 }
100
101
102
103
104
105
106 public Predicate startsWith(String prefix) {
107 return matches("^" + prefix + ".*", "starts with " + prefix);
108 }
109
110
111
112
113
114 public Predicate nonNegativeInteger() {
115 return matches("\\d*", "a non-negative integer (0,1,2,...)");
116 }
117
118
119
120
121
122 public Predicate number() {
123 return matches("(\\+|\\-)?\\d*\\.?\\d*", "a number with optional decimal digits");
124 }
125
126
127
128
129
130 public Predicate date() {
131 return matches("(\\d{4}([01]\\d(\\d{2})?)?)?", "a date string (YYYY[MM[DD]])");
132 }
133
134
135
136
137
138 public Predicate time() {
139 return matches("([012]\\d([0-5]\\d([0-5]\\d(\\.\\d(\\d(\\d(\\d)?)?)?)?)?)?)?([\\+\\-]\\d{4})?",
140 "a HL7 time string");
141 }
142
143
144
145
146
147 public Predicate dateTime() {
148 return matches("(\\d{4}([01]\\d(\\d{2}([012]\\d[0-5]\\d([0-5]\\d(\\.\\d(\\d(\\d(\\d)?)?)?)?)?)?)?)?)?([\\+\\-]\\d{4})?",
149 "a HL7 datetime string");
150 }
151
152
153
154
155
156 public Predicate dateTime25() {
157 return matches("(\\d{4}([01]\\d(\\d{2}([012]\\d([0-5]\\d([0-5]\\d(\\.\\d(\\d(\\d(\\d)?)?)?)?)?)?)?)?)?)?([\\+\\-]\\d{4})?",
158 "a HL7 datetime string");
159 }
160
161
162
163
164
165 public Predicate usPhoneNumber() {
166 return matches("(\\d{1,2} )?(\\(\\d{3}\\))?\\d{3}-\\d{4}(X\\d{1,5})?(B\\d{1,5})?(C.*)?",
167 "a US phone number");
168 }
169
170
171
172
173
174 public Predicate oid() {
175 return matches("[0-2](\\.(0|([1-9][0-9]*)))+",
176 "an Object Identifier (OID)");
177 }
178
179
180
181
182
183 public Predicate uuid() {
184 return matches("\\p{XDigit}{8}-\\p{XDigit}{4}-\\p{XDigit}{4}-\\p{XDigit}{4}-\\p{XDigit}{12}",
185 "a Unique Universal Identifier (UUID)");
186 }
187
188
189
190
191
192
193
194 public Predicate matches(String regex, int flags) {
195 return new MatchesPredicate(regex, flags);
196 }
197
198
199
200
201
202
203
204
205 public Predicate in(Object... allowed) {
206 return new InPredicate(Arrays.asList(allowed));
207 }
208
209
210
211
212
213
214 public Predicate in(Collection<?> allowed) {
215 return new InPredicate(allowed);
216 }
217
218
219
220
221
222
223 public Predicate anyOf(Iterable<Predicate> predicates) {
224 return new AnyOfPredicate(predicates);
225 }
226
227
228
229
230
231
232 public Predicate allOf(Iterable<Predicate> predicates) {
233 return new AllOfPredicate(predicates);
234 }
235
236
237
238
239
240
241 public Predicate anyOf(Predicate... predicates) {
242 return anyOf(Arrays.asList(predicates));
243 }
244
245
246
247
248
249
250 public Predicate allOf(Predicate... predicates) {
251 return allOf(Arrays.asList(predicates));
252 }
253
254
255
256
257
258
259 public Predicatef="../../../../../ca/uhn/hl7v2/validation/builder/Predicate.html#Predicate">Predicate not(Predicate predicate) {
260 return new NotPredicate(predicate);
261 }
262
263
264
265
266
267
268 public Predicate maxLength(int maxSize) {
269 return new MaxLengthPredicate(maxSize);
270 }
271
272
273
274
275
276 public Predicate withdrawn() {
277 return new WithdrawnPredicate();
278 }
279
280
281
282
283 public Predicate always(boolean b) {
284 return new AlwaysPredicate(b);
285 }
286
287
288
289
290 public Predicate alwaysFails() {
291 return always(false);
292 }
293
294 static private String join(Iterable<?> list, String conjunction) {
295 StringBuilder sb = new StringBuilder();
296 boolean first = true;
297 for (Object item : list) {
298 if (first)
299 first = false;
300 else
301 sb.append(conjunction);
302 sb.append(item);
303 }
304 return sb.toString();
305 }
306
307 private static class AlwaysPredicate implements Predicate {
308
309 private final boolean b;
310
311 AlwaysPredicate(boolean b) {
312 this.b = b;
313 }
314
315 public boolean evaluate(Object data) {
316 return b;
317 }
318
319 public String getDescription() {
320 return b ? "anything" : "nothing";
321 }
322
323 }
324
325 private static class MaxLengthPredicate implements Predicate {
326
327 private final int maxLength;
328
329 public MaxLengthPredicate(int maxSize) {
330 this.maxLength = maxSize;
331 }
332
333 public boolean evaluate(Object data) {
334 return (data == null || data.toString().length() <= maxLength);
335 }
336
337 public String getDescription() {
338 return "shorter than " + maxLength + " characters";
339 }
340
341 }
342
343 private static class InPredicate implements Predicate {
344
345 private final Collection<?> allowed;
346
347 InPredicate(Collection<?> allowed) {
348 this.allowed = allowed;
349 }
350
351 public boolean evaluate(Object data) {
352 return allowed.contains(data);
353 }
354
355 public String getDescription() {
356 return "in [" + join(allowed, ",") + "]";
357 }
358
359 }
360
361 private static class WithdrawnPredicate extends MaxLengthPredicate {
362
363 public WithdrawnPredicate() {
364 super(0);
365 }
366
367 @Override
368 public String getDescription() {
369 return "empty because it is withdrawn from the current HL7 version and should not be used";
370 }
371
372 }
373
374 private static class NotPredicate implements Predicate {
375
376 private final Predicate delegate;
377
378 public NotPredicate(Predicate delegate) {
379 this.delegate = delegate;
380 }
381
382 public boolean evaluate(Object data) {
383 try {
384 return !delegate.evaluate(data);
385 } catch (ValidationException e) {
386 return true;
387 }
388 }
389
390 public String getDescription() {
391 return "not " + delegate.getDescription();
392 }
393
394 }
395
396 private static class EqualsPredicate implements Predicate {
397
398 private final Object expected;
399 private final boolean ignoresCase;
400
401 public EqualsPredicate(Object expected) {
402 this(expected, false);
403 }
404
405 EqualsPredicate(Object expected, boolean ignoresCase) {
406 super();
407 this.expected = expected;
408 this.ignoresCase = ignoresCase;
409 }
410
411 public boolean evaluate(Object data) {
412 if (ignoresCase)
413 return (data == null && expected == null)
414 || (data != null && data.toString().equalsIgnoreCase(expected.toString()));
415 return (data == null && expected == null) || (data != null && data.equals(expected));
416 }
417
418 public String getDescription() {
419 return "equal to " + expected;
420 }
421
422 }
423
424 private static class EmptyPredicate implements Predicate {
425
426 public EmptyPredicate() {
427 }
428
429 public boolean evaluate(Object data) {
430 return data == null || "".equals(data) || "\"\"".equals(data);
431 }
432
433 public String getDescription() {
434 return "empty";
435 }
436
437 }
438
439 private static class MatchesPredicate implements Predicate {
440
441 private final Pattern p;
442 private final String description;
443
444 public MatchesPredicate(String regex) {
445 this(regex, "matching with " + regex);
446 }
447
448 public MatchesPredicate(String regex, String description) {
449 p = Pattern.compile(regex);
450 this.description = description;
451 }
452
453 public MatchesPredicate(String regex, int flags) {
454 this(regex, flags, "matching with " + regex);
455 }
456
457 public MatchesPredicate(String regex, int flags, String description) {
458 p = Pattern.compile(regex);
459 this.description = description;
460 }
461
462 public boolean evaluate(Object data) {
463 return (data != null && p.matcher(data.toString()).matches());
464 }
465
466 public String getDescription() {
467 return description;
468 }
469
470 }
471
472 private static class AnyOfPredicate implements Predicate {
473
474 private final Iterable<Predicate> predicates;
475
476 public AnyOfPredicate(Iterable<Predicate> predicates) {
477 super();
478 this.predicates = predicates;
479 }
480
481 public boolean evaluate(Object data) throws ValidationException {
482 for (Predicate p : predicates) {
483 if (p.evaluate(data)) {
484 return true;
485 }
486 }
487 return false;
488 }
489
490 public String getDescription() {
491 String or = " or ";
492 StringBuilder b = new StringBuilder();
493 for (Predicate p : predicates) {
494 b.append(p.getDescription()).append(or);
495 }
496 return b.substring(0, b.length() - or.length());
497 }
498
499 }
500
501 private static class AllOfPredicate implements Predicate {
502
503 private final Iterable<Predicate> predicates;
504
505 public AllOfPredicate(Iterable<Predicate> predicates) {
506 super();
507 this.predicates = predicates;
508 }
509
510 public boolean evaluate(Object data) throws ValidationException {
511 for (Predicate p : predicates) {
512 if (!p.evaluate(data)) {
513 return false;
514 }
515 }
516 return true;
517 }
518
519 public String getDescription() {
520 String and = " and ";
521 StringBuilder b = new StringBuilder();
522 for (Predicate p : predicates) {
523 b.append(p.getDescription()).append(and);
524 }
525 return b.substring(0, b.length() - and.length());
526 }
527
528 }
529
530 }