]> git.argeo.org Git - lgpl/argeo-commons.git/blob - acr/Content.java
Prepare next development cycle
[lgpl/argeo-commons.git] / acr / Content.java
1 package org.argeo.api.acr;
2
3 import java.io.Closeable;
4 import java.io.IOException;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.Optional;
8 import java.util.concurrent.CompletableFuture;
9
10 import javax.xml.XMLConstants;
11 import javax.xml.namespace.QName;
12
13 /**
14 * A semi-structured content, with attributes, within a hierarchical structure.
15 */
16 public interface Content extends Iterable<Content>, Map<QName, Object> {
17
18 QName getName();
19
20 String getPath();
21
22 Content getParent();
23
24 /*
25 * ATTRIBUTES OPERATIONS
26 */
27
28 <A> Optional<A> get(QName key, Class<A> clss);
29
30 default Object get(String key) {
31 if (key.indexOf(':') >= 0)
32 throw new IllegalArgumentException("Name " + key + " has a prefix");
33 return get(new QName(XMLConstants.NULL_NS_URI, key, XMLConstants.DEFAULT_NS_PREFIX));
34 }
35
36 default Object put(String key, Object value) {
37 if (key.indexOf(':') >= 0)
38 throw new IllegalArgumentException("Name " + key + " has a prefix");
39 return put(new QName(XMLConstants.NULL_NS_URI, key, XMLConstants.DEFAULT_NS_PREFIX), value);
40 }
41
42 default Object remove(String key) {
43 if (key.indexOf(':') >= 0)
44 throw new IllegalArgumentException("Name " + key + " has a prefix");
45 return remove(new QName(XMLConstants.NULL_NS_URI, key, XMLConstants.DEFAULT_NS_PREFIX));
46 }
47
48 Class<?> getType(QName key);
49
50 boolean isMultiple(QName key);
51
52 <A> Optional<List<A>> getMultiple(QName key, Class<A> clss);
53
54 @SuppressWarnings("unchecked")
55 default <A> List<A> getMultiple(QName key) {
56 Class<A> type;
57 try {
58 type = (Class<A>) getType(key);
59 } catch (ClassCastException e) {
60 throw new IllegalArgumentException("Requested type is not the default type");
61 }
62 Optional<List<A>> res = getMultiple(key, type);
63 if (res == null)
64 return null;
65 else {
66 if (res.isEmpty())
67 throw new IllegalStateException("Metadata " + key + " is not availabel as list of type " + type);
68 return res.get();
69 }
70 }
71
72 /*
73 * CONTENT OPERATIONS
74 */
75 // default CompletionStage<Content> edit(Consumer<Content> work) {
76 // return CompletableFuture.supplyAsync(() -> {
77 // work.accept(this);
78 // return this;
79 // }).minimalCompletionStage();
80 // }
81
82 Content add(QName name, QName... classes);
83
84 default Content add(String name, QName... classes) {
85 if (name.indexOf(':') >= 0)
86 throw new IllegalArgumentException("Name " + name + " has a prefix");
87 return add(new QName(XMLConstants.NULL_NS_URI, name, XMLConstants.DEFAULT_NS_PREFIX), classes);
88 }
89
90 void remove();
91
92 /*
93 * DEFAULT METHODS
94 */
95 default <A> A adapt(Class<A> clss) throws IllegalArgumentException {
96 throw new UnsupportedOperationException("Cannot adapt content " + this + " to " + clss.getName());
97 }
98
99 default <C extends Closeable> C open(Class<C> clss) throws IOException {
100 throw new UnsupportedOperationException("Cannot open content " + this + " as " + clss.getName());
101 }
102
103 default <A> CompletableFuture<A> write(Class<A> clss) {
104 throw new UnsupportedOperationException("Cannot write content " + this + " as " + clss.getName());
105 }
106
107 /*
108 * CONVENIENCE METHODS
109 */
110 // default String attr(String key) {
111 // return get(key, String.class);
112 // }
113 //
114 // default String attr(Object key) {
115 // return key != null ? attr(key.toString()) : attr(null);
116 // }
117 //
118 // default <A> A get(Object key, Class<A> clss) {
119 // return key != null ? get(key.toString(), clss) : get(null, clss);
120 // }
121
122 /*
123 * EXPERIMENTAL UNSUPPORTED
124 */
125 default boolean hasText() {
126 return false;
127 }
128
129 default String getText() {
130 throw new UnsupportedOperationException();
131 }
132
133 }