1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.opencastproject.metadata.dublincore;
24
25 import com.entwinemedia.fn.data.Opt;
26
27 import org.joda.time.Duration;
28 import org.joda.time.format.ISODateTimeFormat;
29 import org.joda.time.format.ISOPeriodFormat;
30
31 import java.text.SimpleDateFormat;
32 import java.util.Date;
33 import java.util.HashMap;
34 import java.util.Map;
35 import java.util.TimeZone;
36 import java.util.regex.Matcher;
37 import java.util.regex.Pattern;
38
39
40
41
42 public final class EncodingSchemeUtils {
43
44 private static final Map<Precision, String> formats = new HashMap<Precision, String>();
45
46 static {
47 formats.put(Precision.Year, "yyyy");
48 formats.put(Precision.Month, "yyyy-MM");
49 formats.put(Precision.Day, "yyyy-MM-dd");
50 formats.put(Precision.Minute, "yyyy-MM-dd'T'HH:mm'Z'");
51 formats.put(Precision.Second, "yyyy-MM-dd'T'HH:mm:ss'Z'");
52 formats.put(Precision.Fraction, "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
53 }
54
55
56 private EncodingSchemeUtils() {
57 }
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 public static DublinCoreValue encodeDate(Date date, Precision precision) {
76 if (date == null)
77 throw new IllegalArgumentException("The date must not be null");
78 if (precision == null)
79 throw new IllegalArgumentException("The precision must not be null");
80
81 return DublinCoreValue.mk(formatDate(date, precision), DublinCore.LANGUAGE_UNDEFINED, Opt.some(DublinCore.ENC_SCHEME_W3CDTF));
82 }
83
84 public static String formatDate(Date date, Precision precision) {
85 SimpleDateFormat f = new SimpleDateFormat(formats.get(precision));
86 if (precision == Precision.Minute || precision == Precision.Second || precision == Precision.Fraction)
87 f.setTimeZone(TimeZone.getTimeZone("UTC"));
88 return f.format(date);
89 }
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 public static DublinCoreValue encodePeriod(DCMIPeriod period, Precision precision) {
108 if (period == null)
109 throw new IllegalArgumentException("The period must not be null");
110 if (precision == null)
111 throw new IllegalArgumentException("The precision must not be null");
112
113 StringBuilder b = new StringBuilder();
114 if (period.hasStart()) {
115 b.append("start=").append(formatDate(period.getStart(), precision)).append(";");
116 }
117 if (period.hasEnd()) {
118 if (b.length() > 0)
119 b.append(" ");
120 b.append("end=").append(formatDate(period.getEnd(), precision)).append(";");
121 }
122 if (period.hasName()) {
123 b.append(" ").append("name=").append(period.getName().replace(";", "")).append(";");
124 }
125 b.append(" ").append("scheme=W3C-DTF;");
126 return DublinCoreValue.mk(b.toString(), DublinCore.LANGUAGE_UNDEFINED, Opt.some(DublinCore.ENC_SCHEME_PERIOD));
127 }
128
129
130
131
132
133
134
135
136
137
138
139
140 public static DublinCoreValue encodeDuration(long duration) {
141 return DublinCoreValue.mk(ISOPeriodFormat.standard().print(new Duration(duration).toPeriod()),
142 DublinCore.LANGUAGE_UNDEFINED, Opt.some(DublinCore.ENC_SCHEME_ISO8601));
143 }
144
145
146
147
148
149
150
151
152
153
154
155
156 public static Long decodeDuration(String value) {
157 try {
158 return ISOPeriodFormat.standard().parsePeriod(value).toStandardDuration().getMillis();
159 } catch (IllegalArgumentException ignore) {
160 }
161
162 String[] parts = value.split(":");
163 try {
164 if (parts.length == 1)
165 return Long.parseLong(parts[0]) * 1000;
166 if (parts.length == 2)
167 return Long.parseLong(parts[0]) * 1000 * 60 + Long.parseLong(parts[1]) * 1000;
168 if (parts.length == 3)
169 return Long.parseLong(parts[0]) * 1000 * 60 * 60 + Long.parseLong(parts[1]) * 1000 * 60
170 + Long.parseLong(parts[2]) * 1000;
171 } catch (NumberFormatException ignore) {
172 }
173 return null;
174 }
175
176
177
178
179
180
181
182
183 public static Long decodeDuration(DublinCoreValue value) {
184 if (!value.hasEncodingScheme() || value.getEncodingScheme().get().equals(DublinCore.ENC_SCHEME_ISO8601)) {
185 return decodeDuration(value.getValue());
186 }
187 return null;
188 }
189
190 public static Long decodeMandatoryDuration(String value) {
191 Long l = decodeDuration(value);
192 if (l == null)
193 throw new IllegalArgumentException("Cannot decode duration: " + value);
194 return l;
195 }
196
197
198
199
200
201
202 public static Date decodeDate(DublinCoreValue value) {
203 if (!value.hasEncodingScheme() || value.getEncodingScheme().get().equals(DublinCore.ENC_SCHEME_W3CDTF)) {
204 try {
205 return parseW3CDTF(value.getValue());
206 } catch (IllegalArgumentException ignore) {
207 }
208 }
209
210
211 try {
212 long timestamp = Long.parseLong(value.getValue());
213 Date decoded = new java.util.Date(timestamp);
214 return decoded;
215 } catch (NumberFormatException nfe) {
216 }
217
218 return null;
219 }
220
221
222
223
224
225
226 public static Date decodeDate(String value) {
227 try {
228 return parseW3CDTF(value);
229 } catch (IllegalArgumentException ignore) {
230 }
231
232
233 try {
234 long timestamp = Long.parseLong(value);
235 Date decoded = new java.util.Date(timestamp);
236 return decoded;
237 } catch (NumberFormatException nfe) {
238 }
239
240 return null;
241 }
242
243
244
245
246
247
248
249
250
251
252 public static Date decodeMandatoryDate(DublinCoreValue value) {
253 Date date = decodeDate(value);
254 if (date == null)
255 throw new IllegalArgumentException("Cannot decode to Date: " + value);
256 return date;
257 }
258
259
260
261
262
263
264
265
266 public static Date decodeMandatoryDate(String value) {
267 Date date = decodeDate(value);
268 if (date == null)
269 throw new IllegalArgumentException("Cannot decode to Date: " + value);
270 return date;
271 }
272
273 private static final Pattern DCMI_PERIOD = Pattern.compile("(start|end|name)\\s*=\\s*(.*?)(?:;|\\s*$)");
274 private static final Pattern DCMI_PERIOD_SCHEME = Pattern.compile("scheme\\s*=\\s*(.*?)(?:;|\\s*$)");
275
276
277
278
279
280
281
282 public static DCMIPeriod decodePeriod(DublinCoreValue value) {
283 return decodePeriod(value.getValue());
284 }
285
286
287
288
289
290
291
292 public static DCMIPeriod decodePeriod(String value) {
293
294 Matcher schemeMatcher = DCMI_PERIOD_SCHEME.matcher(value);
295 boolean mayBeW3CDTFEncoded = true;
296 if (schemeMatcher.find()) {
297 String schemeString = schemeMatcher.group(1);
298 if (!"W3C-DTF".equalsIgnoreCase(schemeString) && !"W3CDTF".equalsIgnoreCase(schemeString)) {
299 mayBeW3CDTFEncoded = false;
300 }
301 }
302 try {
303 if (mayBeW3CDTFEncoded) {
304
305 Date start = null;
306 Date end = null;
307 String name = null;
308
309 Matcher m = DCMI_PERIOD.matcher(value);
310 while (m.find()) {
311 String field = m.group(1);
312 String fieldValue = m.group(2);
313 if ("start".equals(field)) {
314 if (start != null)
315 return null;
316 start = parseW3CDTF(fieldValue);
317 } else if ("end".equals(field)) {
318 if (end != null)
319 return null;
320 end = parseW3CDTF(fieldValue);
321 } else if ("name".equals(field)) {
322 if (name != null)
323 return null;
324 name = fieldValue;
325 }
326 }
327 if (start == null && end == null)
328 return null;
329 return new DCMIPeriod(start, end, name);
330 }
331 } catch (IllegalArgumentException ignore) {
332
333 }
334 return null;
335 }
336
337
338
339
340
341
342
343
344 public static DCMIPeriod decodeMandatoryPeriod(DublinCoreValue value) {
345 return decodeMandatoryPeriod(value.getValue());
346 }
347
348
349
350
351
352
353
354
355
356 public static DCMIPeriod decodeMandatoryPeriod(String value) {
357 DCMIPeriod period = decodePeriod(value);
358 if (period == null)
359 throw new IllegalArgumentException("Cannot decode to DCMIPeriod: " + value);
360
361 return period;
362 }
363
364
365
366
367
368
369
370
371
372 public static Temporal decodeTemporal(DublinCoreValue value) {
373
374 Date instant = decodeDate(value);
375 if (instant != null)
376 return Temporal.instant(instant);
377 DCMIPeriod period = decodePeriod(value);
378 if (period != null)
379 return Temporal.period(period);
380 Long duration = decodeDuration(value);
381 if (duration != null)
382 return Temporal.duration(duration);
383 return null;
384 }
385
386
387
388
389
390
391
392
393
394 public static Temporal decodeMandatoryTemporal(DublinCoreValue value) {
395 Temporal temporal = decodeTemporal(value);
396 if (value == null)
397 throw new IllegalArgumentException("Cannot decode to either Date or DCMIPeriod: " + value);
398
399 return temporal;
400 }
401
402
403
404
405
406 private static Date parseW3CDTF(String value) {
407 return ISODateTimeFormat.dateTimeParser().parseDateTime(value).toDate();
408 }
409
410 }