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.util.ArrayList;
22 import java.util.Comparator;
23 import java.util.List;
24 import java.util.Optional;
25 import java.util.stream.Collectors;
26
27 import org.apache.logging.log4j.LogManager;
28 import org.apache.logging.log4j.Logger;
29 import org.jdom2.Element;
30 import org.mycore.common.MCRException;
31
32 import com.google.gson.JsonArray;
33 import com.google.gson.JsonObject;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 public class MCRObjectStructure {
62
63 private MCRMetaLinkID parent;
64
65 private final ArrayList<MCRMetaLinkID> children;
66
67 private final ArrayList<MCRMetaEnrichedLinkID> derivates;
68
69 private static final Logger LOGGER = LogManager.getLogger();
70
71
72
73
74
75
76 public MCRObjectStructure() {
77 children = new ArrayList<>();
78 derivates = new ArrayList<>();
79 }
80
81
82
83
84
85 public final void clear() {
86 parent = null;
87 children.clear();
88 derivates.clear();
89 }
90
91
92
93
94 public final void clearChildren() {
95 children.clear();
96 }
97
98
99
100
101 public final void clearDerivates() {
102 derivates.clear();
103 }
104
105
106
107
108
109
110 public final MCRMetaLinkID getParent() {
111 return parent;
112 }
113
114
115
116
117
118
119 public final MCRObjectID getParentID() {
120 if (parent == null) {
121 return null;
122 }
123 return parent.getXLinkHrefID();
124 }
125
126
127
128
129
130
131
132
133 public final void setParent(MCRMetaLinkID parent) {
134 this.parent = parent;
135 }
136
137 public final void setParent(MCRObjectID parentID) {
138 setParent(parentID.toString());
139 }
140
141 public final void setParent(String parentID) {
142 parent = new MCRMetaLinkID();
143 parent.setSubTag("parent");
144 parent.setReference(parentID, null, null);
145 }
146
147
148
149
150 public final void removeParent() {
151 parent = null;
152 }
153
154
155
156
157
158
159
160
161
162
163 public final boolean addChild(MCRMetaLinkID child) {
164 for (MCRMetaLinkID c : children) {
165 if (c.getXLinkHrefID().equals(child.getXLinkHrefID())) {
166 return false;
167 }
168 }
169 children.add(child);
170
171 return true;
172 }
173
174
175
176
177
178
179
180
181
182
183 public final boolean removeChild(MCRObjectID href) {
184 if (LOGGER.isDebugEnabled()) {
185 LOGGER.debug("Remove child ID {}", href);
186 }
187 return removeMetaLink(getChildren(), href);
188 }
189
190
191
192
193
194
195 public final boolean containsChild(MCRObjectID childId) {
196 return getChildren().stream().map(MCRMetaLinkID::getXLinkHrefID).anyMatch(childId::equals);
197 }
198
199
200
201
202
203
204
205
206
207
208 public final boolean removeDerivate(MCRObjectID href) {
209 if (LOGGER.isDebugEnabled()) {
210 LOGGER.debug("Remove derivate ID {}", href);
211 }
212 return removeMetaLink(getDerivates(), href);
213 }
214
215
216
217
218
219
220
221 private boolean removeMetaLink(List<? extends MCRMetaLinkID> list, MCRObjectID href) {
222 final List<MCRMetaLink> toRemove = list.stream()
223 .filter(ml -> ml.getXLinkHrefID().equals(href))
224 .collect(Collectors.toList());
225 return list.removeAll(toRemove);
226 }
227
228
229
230
231 public final List<MCRMetaLinkID> getChildren() {
232 return children;
233 }
234
235
236
237
238
239
240
241
242
243 public final boolean addDerivate(MCRMetaEnrichedLinkID derivate) {
244 MCRObjectID href = derivate.getXLinkHrefID();
245 if (containsDerivate(href)) {
246 return false;
247 }
248 if (!MCRMetadataManager.exists(href)) {
249 LOGGER.warn("Cannot find derivate {}, will add it anyway.", href);
250 }
251 derivates.add(derivate);
252 derivates.sort(Comparator.comparingInt(MCRMetaEnrichedLinkID::getOrder));
253 return true;
254 }
255
256
257
258
259
260
261
262
263 public final boolean addOrUpdateDerivate(MCRMetaEnrichedLinkID derivateLink) {
264 if (derivateLink == null) {
265 return false;
266 }
267 MCRObjectID derivateId = derivateLink.getXLinkHrefID();
268 MCRMetaLinkID oldLink = getDerivateLink(derivateId);
269 if (derivateLink.equals(oldLink)) {
270 return false;
271 }
272 if (oldLink != null) {
273 removeDerivate(oldLink.getXLinkHrefID());
274 }
275 return addDerivate(derivateLink);
276 }
277
278
279
280
281
282
283 public final boolean containsDerivate(MCRObjectID derivateId) {
284 return getDerivateLink(derivateId) != null;
285 }
286
287
288
289
290 public final MCRMetaEnrichedLinkID getDerivateLink(MCRObjectID derivateId) {
291 return getDerivates().stream()
292 .filter(derivate -> derivate.getXLinkHrefID().equals(derivateId))
293 .findAny()
294 .orElse(null);
295 }
296
297
298
299
300 public List<MCRMetaEnrichedLinkID> getDerivates() {
301 return this.derivates;
302 }
303
304
305
306
307
308
309
310
311
312
313 public final void setFromDOM(Element element) {
314 clear();
315 Element subElement = element.getChild("children");
316
317 if (subElement != null) {
318 List<Element> childList = subElement.getChildren();
319
320 for (Element linkElement : childList) {
321 MCRMetaLinkID link = new MCRMetaLinkID();
322 link.setFromDOM(linkElement);
323 children.add(link);
324 }
325 }
326
327
328 subElement = element.getChild("parents");
329
330 if (subElement != null) {
331 parent = new MCRMetaLinkID();
332 parent.setFromDOM(subElement.getChild("parent"));
333 }
334
335
336 subElement = element.getChild("derobjects");
337
338 if (subElement != null) {
339 List<Element> derobjectList = subElement.getChildren();
340
341 for (Element derElement : derobjectList) {
342 addDerivate(MCRMetaEnrichedLinkID.fromDom(derElement));
343 }
344 }
345 }
346
347
348
349
350
351
352
353
354
355 public final Element createXML() throws MCRException {
356 try {
357 validate();
358 } catch (MCRException exc) {
359 throw new MCRException("The content is not valid.", exc);
360 }
361
362 Element elm = new Element("structure");
363
364 if (parent != null) {
365 Element elmm = new Element("parents");
366 elmm.setAttribute("class", "MCRMetaLinkID");
367 elmm.addContent(parent.createXML());
368 elm.addContent(elmm);
369 }
370
371 if (children.size() > 0) {
372 Element elmm = new Element("children");
373 elmm.setAttribute("class", "MCRMetaLinkID");
374 for (MCRMetaLinkID child : getChildren()) {
375 elmm.addContent(child.createXML());
376 }
377 elm.addContent(elmm);
378 }
379
380 if (derivates.size() > 0) {
381 Element elmm = new Element("derobjects");
382 elmm.setAttribute("class", "MCRMetaEnrichedLinkID");
383 for (MCRMetaLinkID derivate : getDerivates()) {
384 elmm.addContent(derivate.createXML());
385 }
386 elm.addContent(elmm);
387 }
388
389 return elm;
390 }
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411 public JsonObject createJSON() {
412 JsonObject structure = new JsonObject();
413
414 Optional.ofNullable(getParent()).ifPresent(link -> structure.add("parent", link.createJSON()));
415
416 JsonArray children = new JsonArray();
417 getChildren().forEach(child -> children.add(child.createJSON()));
418 structure.add("children", children);
419
420 JsonArray derivates = new JsonArray();
421 getDerivates().forEach(derivate -> derivates.add(derivate.createJSON()));
422 structure.add("derivates", derivates);
423 return structure;
424 }
425
426
427
428
429 public final void debug() {
430 if (LOGGER.isDebugEnabled()) {
431 for (MCRMetaLinkID linkID : derivates) {
432 linkID.debug();
433 }
434 if (parent != null) {
435 parent.debug();
436 }
437 for (MCRMetaLinkID linkID : children) {
438 linkID.debug();
439 }
440 }
441 }
442
443
444
445
446
447
448
449 public final boolean isValid() {
450 try {
451 validate();
452 return true;
453 } catch (MCRException exc) {
454 LOGGER.warn("The <structure> part of a <mycoreobject> is invalid.", exc);
455 }
456 return false;
457 }
458
459
460
461
462
463
464
465
466
467
468
469 public void validate() throws MCRException {
470 for (MCRMetaLinkID child : getChildren()) {
471 try {
472 child.validate();
473 } catch (Exception exc) {
474 throw new MCRException("The link to the children '" + child.getXLinkHref() + "' is invalid.", exc);
475 }
476 }
477
478 if (parent != null) {
479 try {
480 parent.validate();
481 } catch (Exception exc) {
482 throw new MCRException("The link to the parent '" + parent.getXLinkHref() + "' is invalid.", exc);
483 }
484 }
485
486 for (MCRMetaLinkID derivate : getDerivates()) {
487 try {
488 derivate.validate();
489 } catch (Exception exc) {
490 throw new MCRException("The link to the derivate '" + derivate.getXLinkHref() + "' is invalid.", exc);
491 }
492 if (!derivate.getXLinkType().equals("locator")) {
493 throw new MCRException("The xlink:type of the derivate link '" + derivate.getXLinkHref()
494 + "' has to be 'locator' and not '" + derivate.getXLinkType() + "'.");
495 }
496
497 String typeId = derivate.getXLinkHrefID().getTypeId();
498 if (!typeId.equals("derivate")) {
499 throw new MCRException("The derivate link '" + derivate.getXLinkHref()
500 + "' is invalid. The _type_ has to be 'derivate' and not '" + typeId + "'.");
501 }
502 }
503 }
504
505 }