1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.opencastproject.metadata.dublincore;
23
24 import org.apache.commons.lang3.StringUtils;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 import java.text.SimpleDateFormat;
29 import java.util.ArrayList;
30 import java.util.Map;
31 import java.util.TimeZone;
32
33
34
35
36
37 public class MetadataField {
38
39 private static final Logger logger = LoggerFactory.getLogger(MetadataField.class);
40
41
42 public static final String CONFIG_COLLECTION_ID_KEY = "collectionID";
43 private static final String CONFIG_PATTERN_KEY = "pattern";
44 private static final String CONFIG_DELIMITER_KEY = "delimiter";
45 public static final String CONFIG_INPUT_ID_KEY = "inputID";
46 public static final String CONFIG_LABEL_KEY = "label";
47 public static final String CONFIG_LIST_PROVIDER_KEY = "listprovider";
48 private static final String CONFIG_NAMESPACE_KEY = "namespace";
49 private static final String CONFIG_ORDER_KEY = "order";
50 private static final String CONFIG_OUTPUT_ID_KEY = "outputID";
51 public static final String CONFIG_PROPERTY_PREFIX = "property";
52 public static final String CONFIG_READ_ONLY_KEY = "readOnly";
53 public static final String CONFIG_REQUIRED_KEY = "required";
54 public static final String CONFIG_TYPE_KEY = "type";
55
56
57
58
59
60 public enum Type {
61 BOOLEAN, DATE, DURATION, ITERABLE_TEXT, MIXED_TEXT, ORDERED_TEXT, LONG, START_DATE, START_TIME, TEXT, TEXT_LONG
62 }
63
64
65 private String collectionID;
66
67 private String pattern;
68
69 private String delimiter;
70
71 private final String inputID;
72
73 private final String label;
74
75 private final String listprovider;
76
77 private final String namespace;
78
79
80
81
82 private final Integer order;
83
84 private final String outputID;
85
86 private boolean readOnly;
87
88 private final boolean required;
89
90 private Type type;
91
92 private Object value;
93 private Boolean translatable;
94 private boolean updated = false;
95 private Map<String, String> collection;
96
97
98 private Boolean hasDifferentValues = null;
99
100
101
102
103
104
105
106 public MetadataField(final MetadataField other) {
107 this.inputID = other.inputID;
108 this.outputID = other.outputID;
109 this.label = other.label;
110 this.readOnly = other.readOnly;
111 this.required = other.required;
112 this.value = other.value;
113 this.translatable = other.translatable;
114 this.hasDifferentValues = other.hasDifferentValues;
115 this.type = other.type;
116 this.collection = other.collection;
117 this.collectionID = other.collectionID;
118 this.order = other.order;
119 this.namespace = other.namespace;
120 this.updated = other.updated;
121 this.pattern = other.pattern;
122 this.delimiter = other.delimiter;
123 this.listprovider = other.listprovider;
124 }
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 public MetadataField(
154 final String inputID,
155 final String outputID,
156 final String label,
157 final boolean readOnly,
158 final boolean required,
159 final Object value,
160 final Boolean translatable,
161 final Type type,
162 final Map<String, String> collection,
163 final String collectionID,
164 final Integer order,
165 final String namespace,
166 final String listprovider,
167 final String pattern,
168 final String delimiter) throws IllegalArgumentException {
169 if (StringUtils.isBlank(inputID)) {
170 throw new IllegalArgumentException("The metadata input id must not be null.");
171 }
172 if (StringUtils.isBlank(label)) {
173 throw new IllegalArgumentException("The metadata label must not be null.");
174 }
175 if (type == null) {
176 throw new IllegalArgumentException("The metadata type must not be null.");
177 }
178 this.inputID = inputID;
179 this.outputID = outputID;
180 this.label = label;
181 this.readOnly = readOnly;
182 this.required = required;
183 this.value = value;
184 this.translatable = translatable;
185 this.type = type;
186 this.collection = collection;
187 this.collectionID = collectionID;
188 this.order = order;
189 this.namespace = namespace;
190 this.listprovider = listprovider;
191 this.pattern = pattern;
192 this.delimiter = delimiter;
193 }
194
195
196
197
198
199
200
201 public void setCollection(final Map<String, String> collection) {
202 this.collection = collection;
203 }
204
205 public Map<String, String> getCollection() {
206 return collection;
207 }
208
209 public Object getValue() {
210 return value;
211 }
212
213 public Boolean isTranslatable() {
214 return translatable;
215 }
216
217 public boolean isUpdated() {
218 return updated;
219 }
220
221 public void setValue(final Object value) {
222 setValue(value, true);
223 }
224
225 public void setValue(final Object value, final boolean setUpdated) {
226 this.value = value;
227
228 if (setUpdated) {
229 this.updated = true;
230 }
231 }
232
233 public void setIsTranslatable(final Boolean translatable) {
234 this.translatable = translatable;
235 }
236
237 public static SimpleDateFormat getSimpleDateFormatter(final String pattern) {
238 final SimpleDateFormat dateFormat;
239 if (StringUtils.isNotBlank(pattern)) {
240 dateFormat = new SimpleDateFormat(pattern);
241 } else {
242 dateFormat = new SimpleDateFormat();
243 }
244 dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
245 return dateFormat;
246 }
247
248 public static MetadataField createMetadataField(final Map<String,String> configuration) {
249 final String inputID = configuration.get(CONFIG_INPUT_ID_KEY);
250 final String label = configuration.get(CONFIG_LABEL_KEY);
251
252 final String collectionID = configuration.get(CONFIG_COLLECTION_ID_KEY);
253 final String delimiter = configuration.get(CONFIG_DELIMITER_KEY);
254 final String outputID = configuration.get(CONFIG_OUTPUT_ID_KEY);
255 final String listprovider = configuration.get(CONFIG_LIST_PROVIDER_KEY);
256 final String namespace = configuration.get(CONFIG_NAMESPACE_KEY);
257
258 final Type type = configuration.containsKey(CONFIG_TYPE_KEY)
259 ? Type.valueOf(configuration.get(CONFIG_TYPE_KEY).toUpperCase()) : null;
260 final boolean required = configuration.containsKey(CONFIG_REQUIRED_KEY) && Boolean
261 .parseBoolean(configuration.get(CONFIG_REQUIRED_KEY).toUpperCase());
262 final boolean readOnly = configuration.containsKey(CONFIG_READ_ONLY_KEY) && Boolean
263 .parseBoolean(configuration.get(CONFIG_READ_ONLY_KEY).toUpperCase());
264
265 final String pattern = configuration.getOrDefault(CONFIG_PATTERN_KEY, "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
266
267 Integer order = null;
268 if (configuration.containsKey(CONFIG_ORDER_KEY)) {
269 try {
270 order = Integer.parseInt(configuration.get(CONFIG_ORDER_KEY));
271 } catch (final NumberFormatException e) {
272 logger.warn("Unable to parse order value {} of metadata field {}", configuration.get(CONFIG_ORDER_KEY),
273 inputID, e);
274 }
275 }
276
277 if (type == null) {
278 throw new IllegalArgumentException("type is null");
279 }
280
281 switch (type) {
282 case BOOLEAN:
283 return new MetadataField(
284 inputID,
285 outputID,
286 label,
287 readOnly,
288 required,
289 null,
290 null,
291 type,
292 null,
293 null,
294 order,
295 namespace,
296 listprovider,
297 null,
298 null);
299 case DATE:
300 return new MetadataField(
301 inputID,
302 outputID,
303 label,
304 readOnly,
305 required,
306 null,
307 null,
308 type,
309 null,
310 null,
311 order,
312 namespace,
313 listprovider,
314 StringUtils.isNotBlank(pattern) ? pattern : null,
315 null);
316 case DURATION:
317 case TEXT:
318 case ORDERED_TEXT:
319 case TEXT_LONG:
320 return new MetadataField(
321 inputID,
322 outputID,
323 label,
324 readOnly,
325 required,
326 "",
327 null,
328 type,
329 null,
330 collectionID,
331 order,
332 namespace,
333 listprovider,
334 null,
335 null);
336 case ITERABLE_TEXT:
337 case MIXED_TEXT:
338 return new MetadataField(
339 inputID,
340 outputID,
341 label,
342 readOnly,
343 required,
344 new ArrayList<>(),
345 null,
346 type,
347 null,
348 collectionID,
349 order,
350 namespace,
351 listprovider,
352 null,
353 delimiter);
354 case LONG:
355 return new MetadataField(
356 inputID,
357 outputID,
358 label,
359 readOnly,
360 required,
361 0L,
362 null,
363 Type.LONG,
364 null,
365 collectionID,
366 order,
367 namespace,
368 listprovider,
369 null, null);
370 case START_DATE:
371 case START_TIME:
372 if (StringUtils.isBlank(pattern)) {
373 throw new IllegalArgumentException(
374 "For temporal metadata field " + inputID + " of type " + type + " there needs to be a pattern.");
375 }
376
377 return new MetadataField(
378 inputID,
379 outputID,
380 label,
381 readOnly,
382 required,
383 null,
384 null,
385 type,
386 null,
387 null,
388 order,
389 namespace,
390 listprovider,
391 pattern,
392 null);
393 default:
394 throw new IllegalArgumentException("Unknown metadata type! " + type);
395 }
396 }
397
398 public String getCollectionID() {
399 return collectionID;
400 }
401
402 public void setCollectionID(final String collectionID) {
403 this.collectionID = collectionID;
404 }
405
406 public String getInputID() {
407 return inputID;
408 }
409
410 public String getLabel() {
411 return label;
412 }
413
414 public String getListprovider() {
415 return listprovider;
416 }
417
418 public String getNamespace() {
419 return namespace;
420 }
421
422 public Integer getOrder() {
423 return order;
424 }
425
426
427
428
429 public String getOutputID() {
430 if (outputID != null) {
431 return outputID;
432 }
433 return inputID;
434 }
435
436 public String getPattern() {
437 return pattern;
438 }
439
440 public void setPattern(final String pattern) {
441 this.pattern = pattern;
442 }
443
444 public String getDelimiter() {
445 return delimiter;
446 }
447
448 public void setDelimiter(final String delimiter) {
449 this.delimiter = delimiter;
450 }
451
452 public void setReadOnly(final boolean readOnly) {
453 this.readOnly = readOnly;
454 }
455
456 public boolean isReadOnly() {
457 return readOnly;
458 }
459
460 public boolean isRequired() {
461 return required;
462 }
463
464 public void setUpdated(final boolean updated) {
465 this.updated = updated;
466 }
467
468 public Type getType() {
469 return type;
470 }
471
472 public void setType(final Type type) {
473 this.type = type;
474 }
475
476 public void setDifferentValues() {
477 value = null;
478 hasDifferentValues = true;
479 }
480
481 public Boolean hasDifferentValues() {
482 return hasDifferentValues;
483 }
484
485 public MetadataField readOnlyCopy() {
486 final MetadataField metadataField = new MetadataField(this);
487 metadataField.setReadOnly(true);
488 return metadataField;
489 }
490 }