]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.api.acr/src/org/argeo/api/acr/Content.java
Introduce system roles
[lgpl/argeo-commons.git] / org.argeo.api.acr / src / org / argeo / api / 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 * TYPING
94 */
95 List<QName> getTypes();
96
97 /*
98 * DEFAULT METHODS
99 */
100 default <A> A adapt(Class<A> clss) {
101 throw new UnsupportedOperationException("Cannot adapt content " + this + " to " + clss.getName());
102 }
103
104 default <C extends Closeable> C open(Class<C> clss) throws IOException {
105 throw new UnsupportedOperationException("Cannot open content " + this + " as " + clss.getName());
106 }
107
108 default <A> CompletableFuture<A> write(Class<A> clss) {
109 throw new UnsupportedOperationException("Cannot write content " + this + " as " + clss.getName());
110 }
111
112 /*
113 * CONVENIENCE METHODS
114 */
115 // default String attr(String key) {
116 // return get(key, String.class);
117 // }
118 //
119 // default String attr(Object key) {
120 // return key != null ? attr(key.toString()) : attr(null);
121 // }
122 //
123 // default <A> A get(Object key, Class<A> clss) {
124 // return key != null ? get(key.toString(), clss) : get(null, clss);
125 // }
126
127 /*
128 * EXPERIMENTAL UNSUPPORTED
129 */
130 default boolean hasText() {
131 return false;
132 }
133
134 default String getText() {
135 throw new UnsupportedOperationException();
136 }
137
138 }