package org.argeo.api.gcr.spi; 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.gcr.Content; import org.argeo.api.gcr.CrName; public abstract class AbstractContent extends AbstractMap implements Content { /* * ATTRIBUTES OPERATIONS */ protected abstract Iterable keys(); protected abstract void removeAttr(QName key); @Override public Set> entrySet() { Set> result = new AttrSet(); return result; } @Override public Class getType(QName key) { return String.class; } @Override public boolean isMultiple(QName key) { return false; } @Override public Optional> getMultiple(QName key, Class clss) { Object value = get(key); if (value == null) return null; if (value instanceof List) { try { List res = (List) value; return Optional.of(res); } catch (ClassCastException e) { List 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 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 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> { @Override public Iterator> iterator() { final Iterator keys = keys().iterator(); Iterator> it = new Iterator>() { QName key = null; @Override public boolean hasNext() { return keys.hasNext(); } @Override public Entry next() { key = keys.next(); // TODO check type Optional value = get(key, Object.class); assert !value.isEmpty(); AbstractMap.SimpleEntry 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 (QName key : keys()) { count++; } return count; } } }