1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.opencastproject.metadata.dublincore;
22
23 import static com.entwinemedia.fn.Stream.$;
24 import static org.opencastproject.metadata.dublincore.DublinCore.LANGUAGE_ANY;
25 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_AUDIENCE;
26 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_CONTRIBUTOR;
27 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_CREATED;
28 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_CREATOR;
29 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_DESCRIPTION;
30 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_EXTENT;
31 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_IDENTIFIER;
32 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_ISSUED;
33 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_IS_PART_OF;
34 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_LANGUAGE;
35 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_LICENSE;
36 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_PUBLISHER;
37 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_RIGHTS_HOLDER;
38 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_SOURCE;
39 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_SPATIAL;
40 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_TEMPORAL;
41 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_TITLE;
42 import static org.opencastproject.metadata.dublincore.DublinCore.PROPERTY_TYPE;
43
44 import org.opencastproject.mediapackage.EName;
45 import org.opencastproject.metadata.dublincore.Temporal.Match;
46
47 import com.entwinemedia.fn.Fn;
48 import com.entwinemedia.fn.Stream;
49 import com.entwinemedia.fn.Unit;
50 import com.entwinemedia.fn.data.Opt;
51 import com.entwinemedia.fn.fns.Strings;
52
53 import org.apache.commons.lang3.StringUtils;
54
55 import java.util.Date;
56 import java.util.List;
57 import java.util.Locale;
58 import java.util.MissingResourceException;
59
60 import javax.annotation.Nonnull;
61 import javax.annotation.ParametersAreNonnullByDefault;
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 @ParametersAreNonnullByDefault
77 public abstract class OpencastDctermsDublinCore {
78 protected final DublinCoreCatalog dc;
79
80 private OpencastDctermsDublinCore(DublinCoreCatalog dc) {
81 this.dc = dc;
82 }
83
84
85 public DublinCoreCatalog getCatalog() {
86 return dc;
87 }
88
89
90
91 @Nonnull public List<String> getPublishers() {
92 return get(PROPERTY_PUBLISHER);
93 }
94
95 public void setPublishers(List<String> publishers) {
96 set(PROPERTY_PUBLISHER, publishers);
97 }
98
99 public void addPublisher(String publisher) {
100 add(PROPERTY_PUBLISHER, publisher);
101 }
102
103 public void removePublishers() {
104 dc.remove(PROPERTY_PUBLISHER);
105 }
106
107
108
109 @Nonnull public List<String> getRightsHolders() {
110 return get(PROPERTY_RIGHTS_HOLDER);
111 }
112
113 public void setRightsHolders(List<String> rightsHolders) {
114 set(PROPERTY_RIGHTS_HOLDER, rightsHolders);
115 }
116
117 public void addRightsHolder(String rightsHolder) {
118 add(PROPERTY_RIGHTS_HOLDER, rightsHolder);
119 }
120
121 public void removeRightsHolders() {
122 dc.remove(PROPERTY_RIGHTS_HOLDER);
123 }
124
125
126
127 @Nonnull public Opt<String> getLicense() {
128 return getFirst(PROPERTY_LICENSE);
129 }
130
131 public void setLicense(String license) {
132 set(PROPERTY_LICENSE, license);
133 }
134
135 public void removeLicense() {
136 dc.remove(PROPERTY_LICENSE);
137 }
138
139
140
141
142 @Nonnull public Opt<String> getDcIdentifier() {
143 return getFirst(PROPERTY_IDENTIFIER);
144 }
145
146
147 public void setDcIdentifier(String id) {
148 set(PROPERTY_IDENTIFIER, id);
149 }
150
151
152 public void updateDcIdentifier(Opt<String> id) {
153 update(PROPERTY_IDENTIFIER, id);
154 }
155
156
157 public void removeDcIdentifier() {
158 dc.remove(PROPERTY_IDENTIFIER);
159 }
160
161
162
163
164 @Nonnull public Opt<String> getTitle() {
165 return getFirst(PROPERTY_TITLE);
166 }
167
168
169 public void setTitle(String title) {
170 set(PROPERTY_TITLE, title);
171 }
172
173
174 public void updateTitle(Opt<String> title) {
175 update(PROPERTY_TITLE, title);
176 }
177
178
179 public void removeTitle() {
180 dc.remove(PROPERTY_TITLE);
181 }
182
183
184
185
186 @Nonnull public Opt<String> getDescription() {
187 return getFirst(PROPERTY_DESCRIPTION);
188 }
189
190
191 public void setDescription(String description) {
192 set(PROPERTY_DESCRIPTION, description);
193 }
194
195
196 public void updateDescription(Opt<String> description) {
197 update(PROPERTY_DESCRIPTION, description);
198 }
199
200
201 public void removeDescription() {
202 dc.remove(PROPERTY_DESCRIPTION);
203 }
204
205
206
207
208 @Nonnull public List<String> getAudiences() {
209 return get(PROPERTY_AUDIENCE);
210 }
211
212
213 public void setAudiences(List<String> audiences) {
214 set(PROPERTY_AUDIENCE, audiences);
215 }
216
217
218 public void setAudience(String audience) {
219 set(PROPERTY_AUDIENCE, audience);
220 }
221
222
223 public void addAudience(String audience) {
224 add(PROPERTY_AUDIENCE, audience);
225 }
226
227
228 public void updateAudience(Opt<String> audience) {
229 update(PROPERTY_AUDIENCE, audience);
230 }
231
232
233 public void removeAudiences() {
234 dc.remove(PROPERTY_AUDIENCE);
235 }
236
237
238
239
240 @Nonnull public Opt<Temporal> getCreated() {
241 return getFirstVal(PROPERTY_CREATED).map(OpencastMetadataCodec.decodeTemporal);
242 }
243
244
245 public void setCreated(Date date) {
246
247
248
249 if (getTemporal().isNone()) {
250 setDate(PROPERTY_CREATED, date, Precision.Day);
251 }
252 }
253
254
255 public void setCreated(Temporal t) {
256
257
258
259 if (getTemporal().isNone()) {
260 t.fold(new Match<Unit>() {
261 @Override public Unit period(DCMIPeriod period) {
262 setCreated(period.getStart());
263 return Unit.unit;
264 }
265
266 @Override public Unit instant(Date instant) {
267 setCreated(instant);
268 return Unit.unit;
269 }
270
271 @Override public Unit duration(long duration) {
272 return Unit.unit;
273 }
274 });
275 }
276 }
277
278
279 public void removeCreated() {
280 dc.remove(PROPERTY_CREATED);
281 }
282
283
284
285
286 @Nonnull public List<String> getCreators() {
287 return get(PROPERTY_CREATOR);
288 }
289
290
291 public void setCreators(List<String> creators) {
292 set(PROPERTY_CREATOR, creators);
293 }
294
295
296 public void setCreator(String creator) {
297 set(PROPERTY_CREATOR, creator);
298 }
299
300
301 public void addCreator(String name) {
302 add(PROPERTY_CREATOR, name);
303 }
304
305
306 public void updateCreator(Opt<String> name) {
307 update(PROPERTY_CREATOR, name);
308 }
309
310
311 public void removeCreators() {
312 dc.remove(PROPERTY_CREATOR);
313 }
314
315
316
317
318 @Nonnull public Opt<Long> getExtent() {
319 return getFirst(PROPERTY_EXTENT).map(OpencastMetadataCodec.decodeDuration);
320 }
321
322
323 public void setExtent(Long extent) {
324 dc.set(PROPERTY_EXTENT, OpencastMetadataCodec.encodeDuration(extent));
325 }
326
327
328 public void removeExtent() {
329 dc.remove(PROPERTY_EXTENT);
330 }
331
332
333
334
335 @Nonnull public Opt<Date> getIssued() {
336 return getFirst(PROPERTY_ISSUED).map(OpencastMetadataCodec.decodeDate);
337 }
338
339
340 public void setIssued(Date date) {
341 setDate(PROPERTY_ISSUED, date, Precision.Day);
342 }
343
344
345 public void updateIssued(Opt<Date> date) {
346 updateDate(PROPERTY_ISSUED, date, Precision.Day);
347 }
348
349
350 public void removeIssued() {
351 dc.remove(PROPERTY_ISSUED);
352 }
353
354
355
356
357 @Nonnull public Opt<String> getLanguage() {
358 return getFirst(PROPERTY_LANGUAGE);
359 }
360
361
362
363
364
365
366 public void setLanguage(String lang) {
367 if (StringUtils.isNotBlank(lang)) {
368 String doLang = lang;
369 if (lang.length() == 2) {
370 try {
371 doLang = new Locale(lang).getISO3Language();
372 } catch (MissingResourceException ignore) {
373 }
374 }
375 set(PROPERTY_LANGUAGE, doLang);
376 }
377 }
378
379
380 public void removeLanguage() {
381 dc.remove(PROPERTY_LANGUAGE);
382 }
383
384
385
386
387 @Nonnull public Opt<String> getSpatial() {
388 return getFirst(PROPERTY_SPATIAL);
389 }
390
391
392 public void setSpatial(String spatial) {
393 set(PROPERTY_SPATIAL, spatial);
394 }
395
396
397 public void updateSpatial(Opt<String> spatial) {
398 update(PROPERTY_SPATIAL, spatial);
399 }
400
401
402 public void removeSpatial() {
403 dc.remove(PROPERTY_SPATIAL);
404 }
405
406
407
408
409 @Nonnull public Opt<String> getSource() {
410 return getFirst(PROPERTY_SOURCE);
411 }
412
413
414 public void setSource(String source) {
415 set(PROPERTY_SOURCE, source);
416 }
417
418
419 public void removeSource() {
420 dc.remove(PROPERTY_SOURCE);
421 }
422
423
424
425
426 @Nonnull public List<String> getContributors() {
427 return get(PROPERTY_CONTRIBUTOR);
428 }
429
430
431 public void setContributors(List<String> contributors) {
432 set(PROPERTY_CONTRIBUTOR, contributors);
433 }
434
435
436 public void setContributor(String contributor) {
437 set(PROPERTY_CONTRIBUTOR, contributor);
438 }
439
440
441 public void addContributor(String contributor) {
442 add(PROPERTY_CONTRIBUTOR, contributor);
443 }
444
445
446 public void updateContributor(Opt<String> contributor) {
447 update(PROPERTY_CONTRIBUTOR, contributor);
448 }
449
450
451 public void removeContributors() {
452 dc.remove(PROPERTY_CONTRIBUTOR);
453 }
454
455
456
457
458 @Nonnull public Opt<Temporal> getTemporal() {
459 return getFirstVal(PROPERTY_TEMPORAL).map(OpencastMetadataCodec.decodeTemporal);
460 }
461
462
463
464
465
466 public void setTemporal(Date from, Date to) {
467 setPeriod(PROPERTY_TEMPORAL, from, to, Precision.Second);
468
469
470 setDate(PROPERTY_CREATED, from, Precision.Day);
471 }
472
473
474 public void removeTemporal() {
475 dc.remove(PROPERTY_TEMPORAL);
476 }
477
478
479
480
481 @Nonnull public Opt<Stream<String>> getType() {
482 return getFirst(PROPERTY_TYPE).map(Strings.split("/"));
483 }
484
485
486 @Nonnull public Opt<String> getTypeCombined() {
487 return getFirst(PROPERTY_TYPE);
488 }
489
490
491
492
493
494 public void setType(String type, String subtype) {
495 set(PROPERTY_TYPE, type + "/" + subtype);
496 }
497
498
499 public void setType(String type) {
500 set(PROPERTY_TYPE, type);
501 }
502
503
504 public void removeType() {
505 dc.remove(PROPERTY_TYPE);
506 }
507
508
509
510 public static final class Episode extends OpencastDctermsDublinCore {
511
512 public Episode(DublinCoreCatalog dc) {
513 super(dc);
514 }
515
516
517 @Nonnull public Opt<String> getIsPartOf() {
518 return getFirst(PROPERTY_IS_PART_OF);
519 }
520
521
522 public void setIsPartOf(String seriesID) {
523 set(PROPERTY_IS_PART_OF, seriesID);
524 }
525
526
527 public void updateIsPartOf(Opt<String> seriesID) {
528 update(PROPERTY_IS_PART_OF, seriesID);
529 }
530
531
532 public void removeIsPartOf() {
533 dc.remove(PROPERTY_IS_PART_OF);
534 }
535
536 }
537
538
539
540 public static final class Series extends OpencastDctermsDublinCore {
541 public Series(DublinCoreCatalog dc) {
542 super(dc);
543 }
544 }
545
546
547
548 protected void setDate(EName property, Date date, Precision p) {
549 dc.set(property, OpencastMetadataCodec.encodeDate(date, p));
550 }
551
552 protected void updateDate(EName property, Opt<Date> date, Precision p) {
553 for (Date d : date) {
554 setDate(property, d, p);
555 }
556 }
557
558
559 protected void setPeriod(EName property, Date from, Date to, Precision p) {
560 dc.set(property, OpencastMetadataCodec.encodePeriod(from, to, p));
561 }
562
563 protected List<String> get(EName property) {
564 return dc.get(property, LANGUAGE_ANY);
565 }
566
567
568 protected Opt<String> getFirst(EName property) {
569 return Opt.nul(dc.getFirst(property));
570 }
571
572
573 protected Opt<DublinCoreValue> getFirstVal(EName property) {
574 return Opt.nul(dc.getFirstVal(property));
575 }
576
577 public void set(EName property, String value) {
578 if (StringUtils.isNotBlank(value)) {
579 dc.set(property, value);
580 }
581 }
582
583 public void set(EName property, List<String> values) {
584 final List<DublinCoreValue> valuesFiltered = $(values).filter(Strings.isNotBlank).map(mkValue).toList();
585 if (!valuesFiltered.isEmpty()) {
586 dc.remove(property);
587 dc.set(property, valuesFiltered);
588 }
589 }
590
591 protected void add(EName property, String value) {
592 if (StringUtils.isNotBlank(value)) {
593 dc.add(property, value);
594 }
595 }
596
597 protected void update(EName property, Opt<String> value) {
598 for (String v : value) {
599 set(property, v);
600 }
601 }
602
603 private final Fn<String, DublinCoreValue> mkValue = new Fn<String, DublinCoreValue>() {
604 @Override public DublinCoreValue apply(String v) {
605 return DublinCoreValue.mk(v);
606 }
607 };
608 }