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