]>
git.argeo.org Git - lgpl/argeo-commons.git/blob - org/argeo/api/acr/Content.java
1 package org
.argeo
.api
.acr
;
3 import static org
.argeo
.api
.acr
.NamespaceUtils
.unqualified
;
5 import java
.io
.Closeable
;
6 import java
.io
.IOException
;
7 import java
.util
.ArrayList
;
10 import java
.util
.Optional
;
11 import java
.util
.concurrent
.CompletableFuture
;
13 import javax
.xml
.namespace
.QName
;
16 * A semi-structured content, with attributes, within a hierarchical structure.
18 public interface Content
extends Iterable
<Content
>, Map
<QName
, Object
> {
19 /** The base of a repository path. */
20 String ROOT_PATH
= "/";
29 * ATTRIBUTES OPERATIONS
32 <A
> Optional
<A
> get(QName key
, Class
<A
> clss
);
34 Class
<?
> getType(QName key
);
36 boolean isMultiple(QName key
);
38 <A
> List
<A
> getMultiple(QName key
, Class
<A
> clss
);
41 * ATTRIBUTES OPERATION HELPERS
43 default boolean containsKey(QNamed key
) {
44 return containsKey(key
.qName());
47 default <A
> Optional
<A
> get(QNamed key
, Class
<A
> clss
) {
48 return get(key
.qName(), clss
);
51 default Object
get(QNamed key
) {
52 return get(key
.qName());
55 default Object
put(QNamed key
, Object value
) {
56 return put(key
.qName(), value
);
59 default Object
remove(QNamed key
) {
60 return remove(key
.qName());
63 // TODO do we really need the helpers below?
65 default Object
get(String key
) {
66 return get(unqualified(key
));
69 default Object
put(String key
, Object value
) {
70 return put(unqualified(key
), value
);
73 default Object
remove(String key
) {
74 return remove(unqualified(key
));
77 @SuppressWarnings("unchecked")
78 default <A
> List
<A
> getMultiple(QName key
) {
81 type
= (Class
<A
>) getType(key
);
82 } catch (ClassCastException e
) {
83 throw new IllegalArgumentException("Requested type is not the default type");
85 List
<A
> res
= getMultiple(key
, type
);
92 /** Adds a new empty {@link Content} to this {@link Content}. */
93 Content
add(QName name
, QName
... classes
);
96 * Adds a new {@link Content} to this {@link Content}, setting the provided
97 * attributes. The provided attributes can be used as hints by the
98 * implementation. In particular, setting {@link DName#getcontenttype} will
99 * imply that this content has a file semantic.
101 default Content
add(QName name
, Map
<QName
, Object
> attrs
, QName
... classes
) {
102 Content child
= add(name
, classes
);
107 default Content
add(String name
, QName
... classes
) {
108 return add(unqualified(name
), classes
);
111 default Content
add(String name
, Map
<QName
, Object
> attrs
, QName
... classes
) {
112 return add(unqualified(name
), attrs
, classes
);
120 List
<QName
> getContentClasses();
122 default void addContentClasses(QName
... contentClass
) {
123 throw new UnsupportedOperationException("Adding content classes to " + getPath() + " is not supported");
127 default boolean isContentClass(QName
... contentClass
) {
128 List
<QName
> contentClasses
= getContentClasses();
129 for (QName cClass
: contentClass
) {
130 if (!contentClasses
.contains(cClass
))
137 default boolean isContentClass(QNamed
... contentClass
) {
138 List
<QName
> lst
= new ArrayList
<>();
139 for (QNamed qNamed
: contentClass
)
140 lst
.add(qNamed
.qName());
141 return isContentClass(lst
.toArray(new QName
[lst
.size()]));
145 default boolean hasContentClass(QName
... contentClass
) {
146 List
<QName
> contentClasses
= getContentClasses();
147 for (QName cClass
: contentClass
) {
148 if (contentClasses
.contains(cClass
))
155 default boolean hasContentClass(QNamed
... contentClass
) {
156 List
<QName
> lst
= new ArrayList
<>();
157 for (QNamed qNamed
: contentClass
)
158 lst
.add(qNamed
.qName());
159 return hasContentClass(lst
.toArray(new QName
[lst
.size()]));
166 default int getSiblingIndex() {
173 default <A
> A
adapt(Class
<A
> clss
) {
174 throw new UnsupportedOperationException("Cannot adapt content " + this + " to " + clss
.getName());
177 default <C
extends Closeable
> C
open(Class
<C
> clss
) throws IOException
{
178 throw new UnsupportedOperationException("Cannot open content " + this + " as " + clss
.getName());
181 default <A
> CompletableFuture
<A
> write(Class
<A
> clss
) {
182 throw new UnsupportedOperationException("Cannot write content " + this + " as " + clss
.getName());
189 default boolean hasChild(QName name
) {
190 for (Content child
: this) {
191 if (child
.getName().equals(name
))
197 default boolean hasChild(QNamed name
) {
198 return hasChild(name
.qName());
201 default Content
anyOrAddChild(QName name
, QName
... classes
) {
202 Content child
= anyChild(name
);
205 return this.add(name
, classes
);
208 default Content
anyOrAddChild(String name
, QName
... classes
) {
209 return anyOrAddChild(unqualified(name
), classes
);
212 /** Any child with this name, or null if there is none */
213 default Content
anyChild(QName name
) {
214 for (Content child
: this) {
215 if (child
.getName().equals(name
))
221 default List
<Content
> children(QName name
) {
222 List
<Content
> res
= new ArrayList
<>();
223 for (Content child
: this) {
224 if (child
.getName().equals(name
))
230 default List
<Content
> children(QNamed name
) {
231 return children(name
.qName());
234 default Optional
<Content
> soleChild(QNamed name
) {
235 return soleChild(name
.qName());
238 default Optional
<Content
> soleChild(QName name
) {
239 List
<Content
> res
= children(name
);
241 return Optional
.empty();
243 throw new IllegalStateException(this + " has multiple children with name " + name
);
244 return Optional
.of(res
.get(0));
247 default Content
soleOrAddChild(QName name
, QName
... classes
) {
248 return soleChild(name
).orElseGet(() -> this.add(name
, classes
));
251 default Content
child(QName name
) {
252 return soleChild(name
).orElseThrow();
255 default Content
child(QNamed name
) {
256 return child(name
.qName());
263 * Convenience method returning an attribute as a {@link String}.
265 * @param key the attribute name
266 * @return the attribute value as a {@link String} or <code>null</code>.
268 * @see Object#toString()
270 default String
attr(QName key
) {
271 return get(key
, String
.class).orElse(null);
275 * Convenience method returning an attribute as a {@link String}.
277 * @param key the attribute name
278 * @return the attribute value as a {@link String} or <code>null</code>.
280 * @see Object#toString()
282 default String
attr(QNamed key
) {
283 return attr(key
.qName());
287 * Convenience method returning an attribute as a {@link String}.
289 * @param key the attribute name
290 * @return the attribute value as a {@link String} or <code>null</code>.
292 * @see Object#toString()
294 default String
attr(String key
) {
295 return attr(unqualified(key
));
302 * A content within this repository
304 * @param path either an absolute path or a path relative to this content
306 Optional
<Content
> getContent(String path
);
309 * EXPERIMENTAL UNSUPPORTED
311 default boolean hasText() {
315 default String
getText() {
316 throw new UnsupportedOperationException();