]> git.argeo.org Git - lgpl/argeo-commons.git/blob - AbstractContent.java
fd4ef4cfc2c8dddc6870c91d2df8184a4c202289
[lgpl/argeo-commons.git] / AbstractContent.java
1 package org.argeo.cms.acr;
2
3 import java.util.AbstractMap;
4 import java.util.AbstractSet;
5 import java.util.ArrayList;
6 import java.util.Collections;
7 import java.util.Iterator;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Optional;
11 import java.util.Set;
12
13 import javax.xml.namespace.QName;
14
15 import org.argeo.api.acr.Content;
16 import org.argeo.api.acr.CrName;
17 import org.argeo.api.acr.spi.ProvidedContent;
18 import org.argeo.api.acr.spi.ProvidedSession;
19 import org.argeo.util.LangUtils;
20
21 /** Partial reference implementation of a {@link ProvidedContent}. */
22 public abstract class AbstractContent extends AbstractMap<QName, Object> implements ProvidedContent {
23 private final ProvidedSession session;
24
25 public AbstractContent(ProvidedSession session) {
26 this.session = session;
27 }
28
29 /*
30 * ATTRIBUTES OPERATIONS
31 */
32 // protected abstract Iterable<QName> keys();
33 //
34 // protected abstract void removeAttr(QName key);
35
36 @Override
37 public Set<Entry<QName, Object>> entrySet() {
38 Set<Entry<QName, Object>> result = new AttrSet();
39 return result;
40 }
41
42 @Override
43 public Class<?> getType(QName key) {
44 return String.class;
45 }
46
47 @Override
48 public boolean isMultiple(QName key) {
49 return false;
50 }
51
52 @SuppressWarnings("unchecked")
53 @Override
54 public <A> Optional<List<A>> getMultiple(QName key, Class<A> clss) {
55 Object value = get(key);
56 if (value == null)
57 return null;
58 if (value instanceof List) {
59 try {
60 List<A> res = (List<A>) value;
61 return Optional.of(res);
62 } catch (ClassCastException e) {
63 List<A> res = new ArrayList<>();
64 List<?> lst = (List<?>) value;
65 try {
66 for (Object o : lst) {
67 A item = (A) o;
68 res.add(item);
69 }
70 return Optional.of(res);
71 } catch (ClassCastException e1) {
72 return Optional.empty();
73 }
74 }
75 } else {// singleton
76 try {
77 A res = (A) value;
78 return Optional.of(Collections.singletonList(res));
79 } catch (ClassCastException e) {
80 return Optional.empty();
81 }
82 }
83 }
84
85 /*
86 * CONTENT OPERATIONS
87 */
88
89 @Override
90 public String getPath() {
91 List<Content> ancestors = new ArrayList<>();
92 collectAncestors(ancestors, this);
93 StringBuilder path = new StringBuilder();
94 for (Content c : ancestors) {
95 QName name = c.getName();
96 // FIXME
97 if (!CrName.root.qName().equals(name))
98 path.append('/').append(name);
99 }
100 return path.toString();
101 }
102
103 private void collectAncestors(List<Content> ancestors, Content content) {
104 if (content == null)
105 return;
106 ancestors.add(0, content);
107 collectAncestors(ancestors, content.getParent());
108 }
109
110 @Override
111 public int getDepth() {
112 List<Content> ancestors = new ArrayList<>();
113 collectAncestors(ancestors, this);
114 return ancestors.size();
115 }
116
117 @Override
118 public String getSessionLocalId() {
119 return getPath();
120 }
121
122 /*
123 * SESSION
124 */
125
126 @Override
127 public ProvidedSession getSession() {
128 return session;
129 }
130
131 /*
132 * TYPING
133 */
134
135 @Override
136 public List<QName> getContentClasses() {
137 return new ArrayList<>();
138 }
139
140 /*
141 * UTILITIES
142 */
143 protected boolean isDefaultAttrTypeRequested(Class<?> clss) {
144 // check whether clss is Object.class
145 return clss.isAssignableFrom(Object.class);
146 }
147
148 // @Override
149 // public String toString() {
150 // return "content " + getPath();
151 // }
152
153 /*
154 * DEFAULTS
155 */
156 // - no children
157 // - no attributes
158 // - cannot be modified
159 @Override
160 public Iterator<Content> iterator() {
161 return Collections.emptyIterator();
162 }
163
164 @Override
165 public Content add(QName name, QName... classes) {
166 throw new UnsupportedOperationException("Content cannot be added.");
167 }
168
169 @Override
170 public void remove() {
171 throw new UnsupportedOperationException("Content cannot be removed.");
172 }
173
174 protected Iterable<QName> keys() {
175 return Collections.emptySet();
176 }
177
178 @Override
179 public <A> Optional<A> get(QName key, Class<A> clss) {
180 return null;
181 }
182
183 protected void removeAttr(QName key) {
184 throw new UnsupportedOperationException("Attributes cannot be removed.");
185 }
186
187 /*
188 * SUB CLASSES
189 */
190
191 class AttrSet extends AbstractSet<Entry<QName, Object>> {
192
193 @Override
194 public Iterator<Entry<QName, Object>> iterator() {
195 final Iterator<QName> keys = keys().iterator();
196 Iterator<Entry<QName, Object>> it = new Iterator<Map.Entry<QName, Object>>() {
197
198 QName key = null;
199
200 @Override
201 public boolean hasNext() {
202 return keys.hasNext();
203 }
204
205 @Override
206 public Entry<QName, Object> next() {
207 key = keys.next();
208 // TODO check type
209 Optional<?> value = get(key, Object.class);
210 assert !value.isEmpty();
211 AbstractMap.SimpleEntry<QName, Object> entry = new SimpleEntry<>(key, value.get());
212 return entry;
213 }
214
215 @Override
216 public void remove() {
217 if (key != null) {
218 AbstractContent.this.removeAttr(key);
219 } else {
220 throw new IllegalStateException("Iteration has not started");
221 }
222 }
223
224 };
225 return it;
226 }
227
228 @Override
229 public int size() {
230 return LangUtils.size(keys());
231 }
232
233 }
234 }