Improve ACR
[lgpl/argeo-commons.git] / org.argeo.api.acr / src / org / argeo / api / acr / Content.java
index edcfaea10de9199dd9b6ffb128216766578c60c2..3cdf8d7dbec044f6a3a0c7a40fbe092b407a2b86 100644 (file)
@@ -1,8 +1,12 @@
 package org.argeo.api.acr;
 
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
 
 import javax.xml.XMLConstants;
 import javax.xml.namespace.QName;
@@ -48,6 +52,7 @@ public interface Content extends Iterable<Content>, Map<QName, Object> {
 
        <A> Optional<List<A>> getMultiple(QName key, Class<A> clss);
 
+       @SuppressWarnings("unchecked")
        default <A> List<A> getMultiple(QName key) {
                Class<A> type;
                try {
@@ -68,6 +73,13 @@ public interface Content extends Iterable<Content>, Map<QName, Object> {
        /*
         * CONTENT OPERATIONS
         */
+//     default CompletionStage<Content> edit(Consumer<Content> work) {
+//             return CompletableFuture.supplyAsync(() -> {
+//                     work.accept(this);
+//                     return this;
+//             }).minimalCompletionStage();
+//     }
+
        Content add(QName name, QName... classes);
 
        default Content add(String name, QName... classes) {
@@ -78,23 +90,104 @@ public interface Content extends Iterable<Content>, Map<QName, Object> {
 
        void remove();
 
+       /*
+        * TYPING
+        */
+       List<QName> getContentClasses();
+
+       default void addContentClasses(QName... contentClass) {
+               throw new UnsupportedOperationException("Adding content classes to " + getPath() + " is not supported");
+       }
+
+       /** AND */
+       default boolean isContentClass(QName... contentClass) {
+               List<QName> contentClasses = getContentClasses();
+               for (QName cClass : contentClass) {
+                       if (!contentClasses.contains(cClass))
+                               return false;
+               }
+               return true;
+       }
+
+       /** OR */
+       default boolean hasContentClass(QName... contentClass) {
+               List<QName> contentClasses = getContentClasses();
+               for (QName cClass : contentClass) {
+                       if (contentClasses.contains(cClass))
+                               return true;
+               }
+               return false;
+       }
+
+       /*
+        * SIBLINGS
+        */
+
+       default int getSiblingIndex() {
+               return 1;
+       }
+
        /*
         * DEFAULT METHODS
         */
-       default <A> A adapt(Class<A> clss) throws IllegalArgumentException {
-               throw new IllegalArgumentException("Cannot adapt content " + this + " to " + clss.getName());
+       default <A> A adapt(Class<A> clss) {
+               throw new UnsupportedOperationException("Cannot adapt content " + this + " to " + clss.getName());
+       }
+
+       default <C extends Closeable> C open(Class<C> clss) throws IOException {
+               throw new UnsupportedOperationException("Cannot open content " + this + " as " + clss.getName());
        }
 
-       default <C extends AutoCloseable> C open(Class<C> clss) throws Exception, IllegalArgumentException {
-               throw new IllegalArgumentException("Cannot open content " + this + " as " + clss.getName());
+       default <A> CompletableFuture<A> write(Class<A> clss) {
+               throw new UnsupportedOperationException("Cannot write content " + this + " as " + clss.getName());
+       }
+
+       /*
+        * CHILDREN
+        */
+
+       default boolean hasChild(QName name) {
+               for (Content child : this) {
+                       if (child.getName().equals(name))
+                               return true;
+               }
+               return false;
+       }
+
+       default Content anyOrAddChild(QName name, QName... classes) {
+               Content child = anyChild(name);
+               if (child != null)
+                       return child;
+               return this.add(name, classes);
+       }
+
+       /** Any child with this name, or null if there is none */
+       default Content anyChild(QName name) {
+               for (Content child : this) {
+                       if (child.getName().equals(name))
+                               return child;
+               }
+               return null;
        }
 
        /*
         * CONVENIENCE METHODS
         */
-//     default String attr(String key) {
-//             return get(key, String.class);
-//     }
+       default String attr(String key) {
+               Object obj = get(key);
+               if (obj == null)
+                       return null;
+               return obj.toString();
+
+       }
+
+       default String attr(QName key) {
+               Object obj = get(key);
+               if (obj == null)
+                       return null;
+               return obj.toString();
+
+       }
 //
 //     default String attr(Object key) {
 //             return key != null ? attr(key.toString()) : attr(null);