1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.datamodel.classifications2;
20
21 import java.io.Serializable;
22 import java.text.MessageFormat;
23 import java.util.Locale;
24 import java.util.StringTokenizer;
25 import java.util.regex.Pattern;
26
27 import org.mycore.common.MCRException;
28
29 import com.fasterxml.jackson.annotation.JsonCreator;
30 import com.fasterxml.jackson.annotation.JsonFormat;
31 import com.fasterxml.jackson.annotation.JsonValue;
32
33 import jakarta.persistence.Access;
34 import jakarta.persistence.AccessType;
35 import jakarta.persistence.Basic;
36 import jakarta.persistence.Column;
37 import jakarta.persistence.Embeddable;
38 import jakarta.persistence.Transient;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 @Embeddable
54 @Access(AccessType.FIELD)
55 @JsonFormat(shape = JsonFormat.Shape.STRING)
56 public class MCRCategoryID implements Serializable {
57
58 private static final long serialVersionUID = -5672923571406252855L;
59
60 private static final Pattern VALID_ID = Pattern.compile("[^:$\\{\\}]+");
61
62 private static final int ROOT_ID_LENGTH = 32;
63
64 private static final int CATEG_ID_LENGTH = 128;
65
66 @Basic
67 @Column(name = "ClassID", length = ROOT_ID_LENGTH, nullable = false, updatable = false)
68 private String rootID;
69
70 @Basic
71 @Column(name = "CategID", length = CATEG_ID_LENGTH, updatable = false)
72 private String id;
73
74 private MCRCategoryID() {
75 super();
76 }
77
78
79
80
81
82
83
84 public MCRCategoryID(String rootID, String id) {
85 this();
86 setID(id);
87 setRootID(rootID);
88 }
89
90 public static MCRCategoryID rootID(String rootID) {
91 return new MCRCategoryID(rootID, "");
92 }
93
94
95
96
97
98 @JsonCreator(mode = JsonCreator.Mode.DELEGATING)
99 public static MCRCategoryID fromString(String categoryId) {
100 StringTokenizer tok = new StringTokenizer(categoryId, ":");
101 String rootId = tok.nextToken();
102 if (!tok.hasMoreTokens()) {
103 return rootID(rootId);
104 }
105 String categId = tok.nextToken();
106 if (tok.hasMoreTokens()) {
107 throw new IllegalArgumentException("CategoryId is ambiguous: " + categoryId);
108 }
109 return new MCRCategoryID(rootId, categId);
110 }
111
112 @Transient
113 public boolean isRootID() {
114 return id == null || id.equals("");
115 }
116
117
118
119
120
121
122 @Override
123 public int hashCode() {
124 final int prime = 31;
125 int result = 1;
126 result = prime * result + (id == null || id.isEmpty() ? 0 : id.hashCode());
127 result = prime * result + (rootID == null ? 0 : rootID.hashCode());
128 return result;
129 }
130
131
132
133
134
135
136 @Override
137 public boolean equals(Object obj) {
138 if (this == obj) {
139 return true;
140 }
141 if (obj == null) {
142 return false;
143 }
144 if (getClass() != obj.getClass()) {
145 return false;
146 }
147 final MCRCategoryID other = (MCRCategoryID) obj;
148 if (id == null) {
149 if (other.id != null && other.id.length() > 0) {
150 return false;
151 }
152 } else if (!id.equals(other.id) && (id.length() > 0 || other.id != null && other.id.length() >= 0)) {
153 return false;
154 }
155 if (rootID == null) {
156 return other.rootID == null;
157 } else {
158 return rootID.equals(other.rootID);
159 }
160 }
161
162
163
164
165 public String getID() {
166 return id == null ? "" : id;
167 }
168
169
170
171
172
173 private void setID(String id) {
174 if (id != null && id.length() > 0) {
175 if (!VALID_ID.matcher(id).matches()) {
176 throw new MCRException("category ID '" + id + "' is invalid and does not match: " + VALID_ID);
177 }
178 if (id.length() > CATEG_ID_LENGTH) {
179 throw new MCRException(
180 new MessageFormat("category ID ''{0}'' is more than {1} characters long: {2}", Locale.ROOT)
181 .format(new Object[] { id, CATEG_ID_LENGTH, id.length() }));
182 }
183 }
184 this.id = id;
185 }
186
187
188
189
190
191
192 public static boolean isValid(String id) {
193 try {
194 MCRCategoryID.fromString(id);
195 return true;
196 } catch (Exception e) {
197 return false;
198 }
199 }
200
201
202
203
204 public String getRootID() {
205 return rootID;
206 }
207
208
209
210
211
212 private void setRootID(String rootID) {
213 if (!VALID_ID.matcher(rootID).matches()) {
214 throw new MCRException(
215 new MessageFormat("classification ID ''{0}'' is invalid and does not match: {1}", Locale.ROOT)
216 .format(new Object[] { rootID, VALID_ID }));
217 }
218 if (rootID.length() > ROOT_ID_LENGTH) {
219 throw new MCRException(String.format(Locale.ENGLISH,
220 "classification ID ''%s'' is more than %d chracters long: %d", rootID, ROOT_ID_LENGTH,
221 rootID.length()));
222 }
223 this.rootID = rootID.intern();
224 }
225
226
227
228
229
230
231 @Override
232 @JsonValue
233 public String toString() {
234 if (id == null || id.length() == 0) {
235 return rootID;
236 }
237 return rootID + ':' + id;
238 }
239
240 }