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