ACR compatible with Android.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / acr / AbstractContent.java
diff --git a/org.argeo.cms/src/org/argeo/cms/acr/AbstractContent.java b/org.argeo.cms/src/org/argeo/cms/acr/AbstractContent.java
new file mode 100644 (file)
index 0000000..b614a14
--- /dev/null
@@ -0,0 +1,168 @@
+package org.argeo.cms.acr;
+
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import javax.xml.namespace.QName;
+
+import org.argeo.api.acr.Content;
+import org.argeo.api.acr.CrName;
+import org.argeo.api.acr.spi.ProvidedContent;
+
+/** Partial reference implementation of a {@link ProvidedContent}. */
+public abstract class AbstractContent extends AbstractMap<QName, Object> implements ProvidedContent {
+
+       /*
+        * ATTRIBUTES OPERATIONS
+        */
+       protected abstract Iterable<QName> keys();
+
+       protected abstract void removeAttr(QName key);
+
+       @Override
+       public Set<Entry<QName, Object>> entrySet() {
+               Set<Entry<QName, Object>> result = new AttrSet();
+               return result;
+       }
+
+       @Override
+       public Class<?> getType(QName key) {
+               return String.class;
+       }
+
+       @Override
+       public boolean isMultiple(QName key) {
+               return false;
+       }
+
+       @SuppressWarnings("unchecked")
+       @Override
+       public <A> Optional<List<A>> getMultiple(QName key, Class<A> clss) {
+               Object value = get(key);
+               if (value == null)
+                       return null;
+               if (value instanceof List) {
+                       try {
+                               List<A> res = (List<A>) value;
+                               return Optional.of(res);
+                       } catch (ClassCastException e) {
+                               List<A> res = new ArrayList<>();
+                               List<?> lst = (List<?>) value;
+                               try {
+                                       for (Object o : lst) {
+                                               A item = (A) o;
+                                               res.add(item);
+                                       }
+                                       return Optional.of(res);
+                               } catch (ClassCastException e1) {
+                                       return Optional.empty();
+                               }
+                       }
+               } else {// singleton
+                       try {
+                               A res = (A) value;
+                               return Optional.of(Collections.singletonList(res));
+                       } catch (ClassCastException e) {
+                               return Optional.empty();
+                       }
+               }
+       }
+
+       /*
+        * CONTENT OPERATIONS
+        */
+
+       @Override
+       public String getPath() {
+               List<Content> ancestors = new ArrayList<>();
+               collectAncestors(ancestors, this);
+               StringBuilder path = new StringBuilder();
+               for (Content c : ancestors) {
+                       QName name = c.getName();
+                       // FIXME
+                       if (!CrName.ROOT.get().equals(name))
+                               path.append('/').append(name);
+               }
+               return path.toString();
+       }
+
+       private void collectAncestors(List<Content> ancestors, Content content) {
+               if (content == null)
+                       return;
+               ancestors.add(0, content);
+               collectAncestors(ancestors, content.getParent());
+       }
+
+       /*
+        * UTILITIES
+        */
+       protected boolean isDefaultAttrTypeRequested(Class<?> clss) {
+               // check whether clss is Object.class
+               return clss.isAssignableFrom(Object.class);
+       }
+
+//     @Override
+//     public String toString() {
+//             return "content " + getPath();
+//     }
+
+       /*
+        * SUB CLASSES
+        */
+
+       class AttrSet extends AbstractSet<Entry<QName, Object>> {
+
+               @Override
+               public Iterator<Entry<QName, Object>> iterator() {
+                       final Iterator<QName> keys = keys().iterator();
+                       Iterator<Entry<QName, Object>> it = new Iterator<Map.Entry<QName, Object>>() {
+
+                               QName key = null;
+
+                               @Override
+                               public boolean hasNext() {
+                                       return keys.hasNext();
+                               }
+
+                               @Override
+                               public Entry<QName, Object> next() {
+                                       key = keys.next();
+                                       // TODO check type
+                                       Optional<?> value = get(key, Object.class);
+                                       assert !value.isEmpty();
+                                       AbstractMap.SimpleEntry<QName, Object> entry = new SimpleEntry<>(key, value.get());
+                                       return entry;
+                               }
+
+                               @Override
+                               public void remove() {
+                                       if (key != null) {
+                                               AbstractContent.this.removeAttr(key);
+                                       } else {
+                                               throw new IllegalStateException("Iteration has not started");
+                                       }
+                               }
+
+                       };
+                       return it;
+               }
+
+               @Override
+               public int size() {
+
+                       int count = 0;
+                       for (Iterator<QName> it = keys().iterator(); it.hasNext();) {
+                               count++;
+                       }
+                       return count;
+               }
+
+       }
+}