1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.datamodel.metadata;
20
21 import java.nio.file.Files;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Objects;
27
28 import org.apache.logging.log4j.LogManager;
29 import org.apache.logging.log4j.Logger;
30 import org.jdom2.Element;
31 import org.mycore.common.MCRException;
32 import org.mycore.common.MCRPersistenceException;
33 import org.mycore.datamodel.niofs.MCRPath;
34
35
36
37
38
39
40
41
42 public class MCRObjectDerivate {
43
44 private static final Logger LOGGER = LogManager.getLogger();
45
46
47 private MCRMetaLinkID linkmeta;
48
49 private final ArrayList<MCRMetaLink> externals;
50
51 private MCRMetaIFS internals;
52
53 private final ArrayList<MCRMetaLangText> titles;
54
55 private final ArrayList<MCRMetaClassification> classifications;
56
57 private String derivateURN;
58
59 private List<MCRFileMetadata> files;
60
61 private MCRObjectID derivateID;
62
63
64
65
66
67 public MCRObjectDerivate(MCRObjectID derivateID) {
68 linkmeta = null;
69 externals = new ArrayList<>();
70 internals = null;
71 titles = new ArrayList<>();
72 classifications = new ArrayList<>();
73 files = Collections.emptyList();
74 this.derivateID = derivateID;
75 }
76
77 public MCRObjectDerivate(MCRObjectID derivateID, Element derivate) {
78 this(derivateID);
79 setFromDOM(derivate);
80 }
81
82
83
84
85
86
87
88
89 private void setFromDOM(Element derivate) {
90
91 Element linkmetaElement = derivate.getChild("linkmetas").getChild("linkmeta");
92 MCRMetaLinkID link = new MCRMetaLinkID();
93 link.setFromDOM(linkmetaElement);
94 linkmeta = link;
95
96
97 Element externalsElement = derivate.getChild("externals");
98 externals.clear();
99 if (externalsElement != null) {
100 List<Element> externalList = externalsElement.getChildren();
101 for (Element externalElement : externalList) {
102 MCRMetaLink eLink = new MCRMetaLink();
103 eLink.setFromDOM(externalElement);
104 externals.add(eLink);
105 }
106 }
107
108
109 Element internalsElement = derivate.getChild("internals");
110 if (internalsElement != null) {
111 Element internalElement = internalsElement.getChild("internal");
112 if (internalElement != null) {
113 internals = new MCRMetaIFS();
114 internals.setFromDOM(internalElement);
115 }
116 }
117
118
119 Element titlesElement = derivate.getChild("titles");
120 titles.clear();
121 if (titlesElement != null) {
122 List<Element> titleList = titlesElement.getChildren();
123 for (Element titleElement : titleList) {
124 MCRMetaLangText text = new MCRMetaLangText();
125 text.setFromDOM(titleElement);
126 if (text.isValid()) {
127 titles.add(text);
128 }
129 }
130 }
131
132
133 Element classificationElement = derivate.getChild("classifications");
134 classifications.clear();
135 if (classificationElement != null) {
136 final List<Element> classificationList = classificationElement.getChildren();
137 classificationList.stream().map((classElement) -> {
138 MCRMetaClassification clazzObject = new MCRMetaClassification();
139 clazzObject.setFromDOM(classElement);
140 return clazzObject;
141 }).forEach(classifications::add);
142 }
143
144
145 Element filesetElements = derivate.getChild("fileset");
146 if (filesetElements != null) {
147 String mainURN = filesetElements.getAttributeValue("urn");
148 if (mainURN != null) {
149 this.derivateURN = mainURN;
150 }
151 List<Element> filesInList = filesetElements.getChildren();
152 if (!filesInList.isEmpty()) {
153 files = new ArrayList<>(filesInList.size());
154 for (Element file : filesInList) {
155 files.add(new MCRFileMetadata(file));
156 }
157 }
158 }
159 }
160
161
162
163
164
165
166 public MCRMetaLinkID getMetaLink() {
167 return linkmeta;
168 }
169
170
171
172
173
174
175
176 public final void setLinkMeta(MCRMetaLinkID link) {
177 linkmeta = link;
178 }
179
180
181
182
183 public final int getExternalSize() {
184 return externals.size();
185 }
186
187
188
189
190
191
192
193
194 public final MCRMetaLink getExternal(int index) throws IndexOutOfBoundsException {
195 if ((index < 0) || (index > externals.size())) {
196 throw new IndexOutOfBoundsException("Index error in getExternal(" + index + ").");
197 }
198
199 return externals.get(index);
200 }
201
202
203
204
205 public final int getTitleSize() {
206 return titles.size();
207 }
208
209
210
211
212
213
214
215
216 public final MCRMetaLangText getTitle(int index) throws IndexOutOfBoundsException {
217 if ((index < 0) || (index > titles.size())) {
218 throw new IndexOutOfBoundsException("Index error in getTitle(" + index + ").");
219 }
220
221 return titles.get(index);
222 }
223
224
225
226
227
228
229 public final MCRMetaIFS getInternals() {
230 return internals;
231 }
232
233
234
235
236
237
238
239 public MCRFileMetadata getOrCreateFileMetadata(MCRPath file, String urn) {
240 return getOrCreateFileMetadata(file, urn, null);
241 }
242
243 public MCRFileMetadata getOrCreateFileMetadata(MCRPath file, String urn, String handle) {
244 Objects.requireNonNull(file, "File may not be null");
245 String path = "/" + file.subpathComplete();
246 return getOrCreateFileMetadata(path, urn, handle);
247 }
248
249
250
251
252
253
254
255 private MCRFileMetadata getOrCreateFileMetadata(String path, String urn, String handle) {
256 if (path == null) {
257 throw new NullPointerException("path may not be null");
258 }
259 int fileCount = files.size();
260 for (int i = 0; i < fileCount; i++) {
261 MCRFileMetadata fileMetadata = files.get(i);
262 int compare = fileMetadata.getName().compareTo(path);
263 if (compare == 0) {
264 return fileMetadata;
265 } else if (compare > 0) {
266
267 MCRFileMetadata newFileMetadata = createFileMetadata(path, urn, handle);
268 files.add(i, newFileMetadata);
269 return newFileMetadata;
270 }
271 }
272
273 if (files.isEmpty()) {
274 files = new ArrayList<>();
275 }
276 MCRFileMetadata newFileMetadata = createFileMetadata(path, urn, handle);
277 files.add(newFileMetadata);
278 return newFileMetadata;
279 }
280
281 public final MCRFileMetadata getOrCreateFileMetadata(String path) {
282 return getOrCreateFileMetadata(MCRPath.getPath(derivateID.toString(), path), null, null);
283 }
284
285 public MCRFileMetadata getOrCreateFileMetadata(MCRPath file) {
286 return getOrCreateFileMetadata(file, null, null);
287 }
288
289
290
291
292
293
294
295 private MCRFileMetadata createFileMetadata(String path, String urn, String handle) {
296 MCRPath mcrFile = MCRPath.getPath(derivateID.toString(), path);
297 if (!Files.exists(mcrFile)) {
298 throw new MCRPersistenceException("File does not exist: " + mcrFile);
299 }
300 return new MCRFileMetadata(path, urn, handle, null);
301 }
302
303 public List<MCRFileMetadata> getFileMetadata() {
304 return Collections.unmodifiableList(files);
305 }
306
307
308
309
310 public void removeFileMetadata() {
311 this.files = Collections.emptyList();
312 this.derivateURN = null;
313 }
314
315
316
317
318
319
320 public boolean deleteFileMetaData(String path) {
321 Iterator<MCRFileMetadata> it = files.iterator();
322 while (it.hasNext()) {
323 MCRFileMetadata metadata = it.next();
324 if (metadata.getName().equals(path)) {
325 it.remove();
326 return true;
327 }
328 }
329 return false;
330 }
331
332
333
334
335
336
337
338 public final void setInternals(MCRMetaIFS ifs) {
339 if (ifs == null) {
340 return;
341 }
342
343 internals = ifs;
344 }
345
346
347
348
349
350
351
352
353 public final Element createXML() throws MCRException {
354 try {
355 validate();
356 } catch (MCRException exc) {
357 throw new MCRException("The content is not valid.", exc);
358 }
359 Element elm = new Element("derivate");
360
361 Element linkmetas = new Element("linkmetas");
362 linkmetas.setAttribute("class", "MCRMetaLinkID");
363 linkmetas.setAttribute("heritable", "false");
364 linkmetas.addContent(linkmeta.createXML());
365 elm.addContent(linkmetas);
366
367 if (externals.size() != 0) {
368 Element extEl = new Element("externals");
369 extEl.setAttribute("class", "MCRMetaLink");
370 extEl.setAttribute("heritable", "false");
371 for (MCRMetaLink external : externals) {
372 extEl.addContent(external.createXML());
373 }
374 elm.addContent(extEl);
375 }
376
377 if (internals != null) {
378 Element intEl = new Element("internals");
379 intEl.setAttribute("class", "MCRMetaIFS");
380 intEl.setAttribute("heritable", "false");
381 intEl.addContent(internals.createXML());
382 elm.addContent(intEl);
383 }
384
385 if (titles.size() != 0) {
386 Element titEl = new Element("titles");
387 titEl.setAttribute("class", "MCRMetaLangText");
388 titEl.setAttribute("heritable", "false");
389 titles.stream()
390 .map(MCRMetaLangText::createXML)
391 .forEach(titEl::addContent);
392 elm.addContent(titEl);
393 }
394
395 if (classifications.size() > 0) {
396 Element clazzElement = new Element("classifications");
397 clazzElement.setAttribute("class", "MCRMetaClassification");
398 clazzElement.setAttribute("heritable", "false");
399
400 classifications.stream()
401 .map(MCRMetaClassification::createXML)
402 .forEach(clazzElement::addContent);
403 elm.addContent(clazzElement);
404 }
405
406 if (this.derivateURN != null || !files.isEmpty()) {
407 Element fileset = new Element("fileset");
408
409 if (this.derivateURN != null) {
410 fileset.setAttribute("urn", this.derivateURN);
411 }
412 Collections.sort(files);
413 for (MCRFileMetadata file : files) {
414 fileset.addContent(file.createXML());
415 }
416 elm.addContent(fileset);
417 }
418
419 return elm;
420 }
421
422
423
424
425
426
427
428
429
430
431
432 public final boolean isValid() {
433 try {
434 validate();
435 return true;
436 } catch (MCRException exc) {
437 LOGGER.warn("The <derivate> part of the mycorederivate '{}' is invalid.", derivateID, exc);
438 }
439 return false;
440 }
441
442
443
444
445
446
447
448
449
450
451
452 public void validate() throws MCRException {
453 if (linkmeta == null) {
454 throw new MCRException("linkmeta == null");
455 }
456 if (!linkmeta.getXLinkType().equals("locator")) {
457 throw new MCRException("linkmeta type != locator");
458 }
459 if ((internals == null) && (externals.size() == 0)) {
460 throw new MCRException("(internals == null) && (externals.size() == 0)");
461 }
462 }
463
464 public void setURN(String urn) {
465 derivateURN = urn;
466 }
467
468 public String getURN() {
469 return derivateURN;
470 }
471
472 void setDerivateID(MCRObjectID id) {
473 this.derivateID = id;
474 }
475
476 public ArrayList<MCRMetaClassification> getClassifications() {
477 return classifications;
478 }
479
480 public ArrayList<MCRMetaLangText> getTitles() {
481 return titles;
482 }
483 }