package org.argeo.api.acr; import static org.argeo.api.acr.NamespaceUtils.unqualified; import java.util.ArrayList; import java.util.List; import java.util.Optional; import javax.xml.namespace.QName; /** A {@link StructuredData} whose attributes have qualified keys. */ public interface QualifiedData> extends StructuredData { QName getName(); CHILD getParent(); /* * ATTRIBUTES OPERATIONS */ Optional get(QName key, Class clss); Class getType(QName key); boolean isMultiple(QName key); List getMultiple(QName key, Class clss); /* * PATH */ char getPathSeparator(); /* * ATTRIBUTES OPERATION HELPERS */ default boolean containsKey(QNamed key) { return containsKey(key.qName()); } default Optional get(QNamed key, Class clss) { return get(key.qName(), clss); } default Object get(QNamed key) { return get(key.qName()); } default Object put(QNamed key, Object value) { return put(key.qName(), value); } default Object remove(QNamed key) { return remove(key.qName()); } // TODO do we really need the helpers below? default Object get(String key) { return get(unqualified(key)); } default Object put(String key, Object value) { return put(unqualified(key), value); } default Object remove(String key) { return remove(unqualified(key)); } @SuppressWarnings("unchecked") default List getMultiple(QName key) { Class type; try { type = (Class) getType(key); } catch (ClassCastException e) { throw new IllegalArgumentException("Requested type is not the default type"); } List res = getMultiple(key, type); return res; } /* * CHILDREN */ default boolean hasChild(QName name) { for (CHILD child : this) { if (child.getName().equals(name)) return true; } return false; } default boolean hasChild(QNamed name) { return hasChild(name.qName()); } /** Any child with this name, or null if there is none */ default CHILD anyChild(QName name) { for (CHILD child : this) { if (child.getName().equals(name)) return child; } return null; } default List children(QName name) { List res = new ArrayList<>(); for (CHILD child : this) { if (child.getName().equals(name)) res.add(child); } return res; } default List children(QNamed name) { return children(name.qName()); } default Optional soleChild(QNamed name) { return soleChild(name.qName()); } default Optional soleChild(QName name) { List res = children(name); if (res.isEmpty()) return Optional.empty(); if (res.size() > 1) throw new IllegalStateException(this + " has multiple children with name " + name); return Optional.of(res.get(0)); } default CHILD child(QName name) { return soleChild(name).orElseThrow(); } default CHILD child(QNamed name) { return child(name.qName()); } /* * ATTR AS STRING */ /** * Convenience method returning an attribute as a {@link String}. * * @param key the attribute name * @return the attribute value as a {@link String} or null. * * @see Object#toString() */ default String attr(QName key) { return get(key, String.class).orElse(null); } /** * Convenience method returning an attribute as a {@link String}. * * @param key the attribute name * @return the attribute value as a {@link String} or null. * * @see Object#toString() */ default String attr(QNamed key) { return attr(key.qName()); } /** * Convenience method returning an attribute as a {@link String}. * * @param key the attribute name * @return the attribute value as a {@link String} or null. * * @see Object#toString() */ default String attr(String key) { return attr(unqualified(key)); } /* * SIBLINGS */ default int getSiblingIndex() { return 1; } }