1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sourceforge.domian.specification;
17
18
19 import java.text.ParseException;
20 import java.text.SimpleDateFormat;
21 import java.util.Calendar;
22 import java.util.Date;
23 import java.util.Locale;
24
25 import org.apache.commons.lang.builder.HashCodeBuilder;
26
27 import static java.lang.Boolean.FALSE;
28 import static org.apache.commons.lang.StringUtils.isBlank;
29 import static org.apache.commons.lang.StringUtils.isEmpty;
30 import static org.apache.commons.lang.StringUtils.isNumeric;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 final class DateStringSpecification extends AbstractSpecification<String> implements ValueBoundSpecification<String> {
47
48 private final SimpleDateFormat simpleDateFormat;
49
50 DateStringSpecification(final String datePattern) {
51 if (datePattern == null) { throw new IllegalArgumentException("Date pattern parameter cannot be null"); }
52 if (isEmpty(datePattern)) { throw new IllegalArgumentException("Date pattern parameter cannot be empty"); }
53 if (isBlank(datePattern)) { throw new IllegalArgumentException("Date pattern parameter cannot be blank"); }
54 try {
55 this.simpleDateFormat = new SimpleDateFormat(datePattern, Locale.getDefault());
56 this.simpleDateFormat.setLenient(false);
57
58 } catch (IllegalArgumentException e) {
59 throw new IllegalArgumentException("\"" + datePattern + "\" is not a valid date pattern");
60 }
61 }
62
63
64 @Override
65 public String getValue() {
66 return this.simpleDateFormat.toPattern();
67 }
68
69 @Override
70 public Boolean isSatisfiedBy(final String candidate) {
71 if (candidate == null) {
72 return FALSE;
73 }
74 if (candidate.length() != this.simpleDateFormat.toPattern().length()) {
75 return FALSE;
76 }
77 try {
78 Date date = this.simpleDateFormat.parse(candidate);
79
80
81 return isNumeric(candidate) || !lengthOfYearStringIsNotEqualToLengthOfYearPatternString(date, this.simpleDateFormat);
82
83 } catch (ParseException e) {
84 return FALSE;
85 }
86 }
87
88 @Override
89 public int hashCode() {
90 return new HashCodeBuilder(423, 19843).append(this.simpleDateFormat).toHashCode();
91 }
92
93 @Override
94 public boolean equals(final Object otherObject) {
95 if (otherObject == null) { return false; }
96 if (!(otherObject instanceof DateStringSpecification)) { return false; }
97 return this.simpleDateFormat.equals(((DateStringSpecification) otherObject).simpleDateFormat);
98 }
99
100
101 private static boolean lengthOfYearStringIsNotEqualToLengthOfYearPatternString(final Date date, final SimpleDateFormat datePattern) {
102 final Calendar calendar = Calendar.getInstance();
103 calendar.setLenient(false);
104 calendar.setTime(date);
105 final String yearAsString = String.valueOf(calendar.get(Calendar.YEAR));
106
107 final String datePatternString = datePattern.toPattern();
108 final String yearDatePatternString = datePatternString.substring(datePatternString.indexOf('y'), datePatternString.lastIndexOf('y') + 1);
109
110 return yearAsString.length() != yearDatePatternString.length();
111 }
112 }