1 /*
2 * Copyright (C) 2020-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
3 */
4 package de.powerstat.validation.values;
5
6
7 import java.util.Objects;
8 import java.util.regex.Pattern;
9
10 import de.powerstat.validation.interfaces.IValueObject;
11
12
13 /**
14 * Address Postal code.
15 *
16 * Not DSGVO relevant.
17 *
18 * https://en.wikipedia.org/wiki/List_of_postal_codes
19 * https://de.wikipedia.org/wiki/Liste_der_Postleitsysteme
20 *
21 * TODO Country specific
22 */
23 public final class PostalCode implements Comparable<PostalCode>, IValueObject
24 {
25 /* *
26 * Cache for singletons.
27 */
28 // private static final Map<String, PostalCode> CACHE = new WeakHashMap<>();
29
30 /**
31 * Postal code regexp.
32 */
33 private static final Pattern POSTALCODE_REGEXP = Pattern.compile("^[0-9A-Z -]{3,11}$"); //$NON-NLS-1$
34
35 /**
36 * Postal code.
37 */
38 private final String postalCode;
39
40
41 /**
42 * Constructor.
43 *
44 * @param postalCode Postal code
45 * @throws NullPointerException if postalCode is null
46 * @throws IllegalArgumentException if postalCode is not a correct postalCode
47 */
48 private PostalCode(final String postalCode)
49 {
50 super();
51 Objects.requireNonNull(postalCode, "postalCode"); //$NON-NLS-1$
52 if ((postalCode.length() < 3) || (postalCode.length() > 11))
53 {
54 throw new IllegalArgumentException("postalCode with wrong length"); //$NON-NLS-1$
55 }
56 if (!PostalCode.POSTALCODE_REGEXP.matcher(postalCode).matches())
57 {
58 throw new IllegalArgumentException("postalCode with wrong format"); //$NON-NLS-1$
59 }
60 this.postalCode = postalCode;
61 }
62
63
64 /**
65 * PostalCode factory.
66 *
67 * @param postalCode Postal code
68 * @return PostalCode object
69 */
70 public static PostalCode of(final String postalCode)
71 {
72 /*
73 synchronized (PostalCode.class)
74 {
75 PostalCode obj = PostalCode.CACHE.get(postalCode);
76 if (obj != null)
77 {
78 return obj;
79 }
80 obj = new PostalCode(postalCode);
81 PostalCode.CACHE.put(postalCode, obj);
82 return obj;
83 }
84 */
85 return new PostalCode(postalCode);
86 }
87
88
89 /**
90 * Returns the value of this PostalCode as a string.
91 *
92 * @return The text value represented by this object after conversion to type string.
93 */
94 @Override
95 public String stringValue()
96 {
97 return this.postalCode;
98 }
99
100
101 /**
102 * Calculate hash code.
103 *
104 * @return Hash
105 * @see java.lang.Object#hashCode()
106 */
107 @Override
108 public int hashCode()
109 {
110 return this.postalCode.hashCode();
111 }
112
113
114 /**
115 * Is equal with another object.
116 *
117 * @param obj Object
118 * @return true when equal, false otherwise
119 * @see java.lang.Object#equals(java.lang.Object)
120 */
121 @Override
122 public boolean equals(final Object obj)
123 {
124 if (this == obj)
125 {
126 return true;
127 }
128 if (!(obj instanceof PostalCode))
129 {
130 return false;
131 }
132 final PostalCode other = (PostalCode)obj;
133 return this.postalCode.equals(other.postalCode);
134 }
135
136
137 /**
138 * Returns the string representation of this PostalCode.
139 *
140 * The exact details of this representation are unspecified and subject to change, but the following may be regarded as typical:
141 *
142 * "PostalCode[postalCode=28000]"
143 *
144 * @return String representation of this PostalCode
145 * @see java.lang.Object#toString()
146 */
147 @Override
148 public String toString()
149 {
150 final var builder = new StringBuilder(23);
151 builder.append("PostalCode[postalCode=").append(this.postalCode).append(']'); //$NON-NLS-1$
152 return builder.toString();
153 }
154
155
156 /**
157 * Compare with another object.
158 *
159 * @param obj Object to compare with
160 * @return 0: equal; 1: greater; -1: smaller
161 * @see java.lang.Comparable#compareTo(java.lang.Object)
162 */
163 @Override
164 public int compareTo(final PostalCode obj)
165 {
166 Objects.requireNonNull(obj, "obj"); //$NON-NLS-1$
167 return this.postalCode.compareTo(obj.postalCode);
168 }
169
170 }