Open for edit for sub nodes of versioned nodes
[gpl/argeo-jcr.git] / org.argeo.cms.jcr / src / org / argeo / cms / jcr / acr / JcrContent.java
index 3cebe44babdfe8d04cc783886920c3fc9b9e281d..880f29eeaebf4c30f87fd850ddd8ab84036b48c1 100644 (file)
@@ -21,7 +21,6 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.UUID;
-import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ForkJoinPool;
 
 import javax.jcr.Binary;
@@ -48,6 +47,7 @@ import org.argeo.api.acr.spi.ProvidedSession;
 import org.argeo.api.cms.CmsConstants;
 import org.argeo.cms.acr.AbstractContent;
 import org.argeo.cms.acr.ContentUtils;
+import org.argeo.cms.util.AsyncPipedOutputStream;
 import org.argeo.jcr.Jcr;
 import org.argeo.jcr.JcrException;
 import org.argeo.jcr.JcrUtils;
@@ -64,8 +64,8 @@ public class JcrContent extends AbstractContent {
 
        /* OPTIMISATIONS */
        /**
-        * While we want to support thread-safe access, it is very likely that only
-        * thread and only one sesssion will be used (typically from a single-threaded
+        * While we want to support thread-safe access, it is very likely that only one
+        * thread and only one session will be used (typically from a single-threaded
         * UI). We therefore cache was long as the same thread is calling.
         */
        private Thread lastRetrievingThread = null;
@@ -290,10 +290,19 @@ public class JcrContent extends AbstractContent {
        @Override
        public Content add(QName name, QName... classes) {
                try {
+                       Node node = openForEdit();
                        Node child;
                        if (classes.length > 0) {
+                               classes: for (int i = 0; i < classes.length; i++) {
+                                       if (classes[i].equals(DName.collection.qName())) {
+                                               List<QName> lst = new ArrayList<>(Arrays.asList(classes));
+                                               lst.add(0, NtType.folder.qName());
+                                               lst.remove(DName.collection.qName());
+                                               classes = lst.toArray(new QName[lst.size()]);
+                                               break classes;
+                                       }
+                               }
                                QName primaryType = classes[0];
-                               Node node = openForEdit();
                                child = Jcr.addNode(node, name.toString(), primaryType.toString());
 
                                for (int i = 1; i < classes.length; i++)
@@ -301,19 +310,12 @@ public class JcrContent extends AbstractContent {
 
                                if (NtType.file.qName().equals(primaryType)) {
                                        // TODO optimise when we have a proper save mechanism
-                                       Node content = child.addNode(Node.JCR_CONTENT, NodeType.NT_UNSTRUCTURED);
-//                                     Binary binary;
-//                                     try (InputStream in = new ByteArrayInputStream(new byte[0])) {
-//                                             binary = content.getSession().getValueFactory().createBinary(in);
-//                                             content.setProperty(Property.JCR_DATA, binary);
-//                                     } catch (IOException e) {
-//                                             throw new UncheckedIOException(e);
-//                                     }
-                                       child.getSession().save();
+                                       child.addNode(Node.JCR_CONTENT, NodeType.NT_UNSTRUCTURED);
                                }
                        } else {
-                               child = Jcr.addNode(getJcrNode(), name.toString(), NodeType.NT_UNSTRUCTURED);
+                               child = Jcr.addNode(node, name.toString(), NodeType.NT_UNSTRUCTURED);
                        }
+                       saveEditedNode(node);
                        return new JcrContent(getSession(), provider, jcrWorkspace, child.getPath());
                } catch (RepositoryException e) {
                        throw new JcrException("Cannot add child to " + jcrPath + " in " + jcrWorkspace, e);
@@ -327,11 +329,7 @@ public class JcrContent extends AbstractContent {
                        lst.add(0, NtType.file.qName());
                        classes = lst.toArray(new QName[lst.size()]);
                }
-               if (attrs.containsKey(DName.collection.qName())) {
-                       List<QName> lst = Arrays.asList(classes);
-                       lst.add(0, NtType.folder.qName());
-                       classes = lst.toArray(new QName[lst.size()]);
-               }
+
                Content child = add(name, classes);
                child.putAll(attrs);
                return child;
@@ -341,12 +339,13 @@ public class JcrContent extends AbstractContent {
        public void remove() {
                Node node = openForEdit();
                Jcr.remove(node);
-               saveJcrSession();
+               saveEditedNode(node);
        }
 
-       private void saveJcrSession() {
+       private void saveEditedNode(Node node) {
                try {
-                       getJcrSession().save();
+                       node.getSession().save();
+                       getJcrSession().refresh(true);
                } catch (RepositoryException e) {
                        throw new JcrException("Cannot persist " + jcrPath + " in " + jcrWorkspace, e);
                }
@@ -363,7 +362,7 @@ public class JcrContent extends AbstractContent {
                                throw new JcrException("Cannot remove property " + key + " from " + getJcrNode(), e);
                        }
                }
-               saveJcrSession();
+               saveEditedNode(node);
        }
 
        @Override
@@ -413,7 +412,7 @@ public class JcrContent extends AbstractContent {
                                node.setProperty(property, newValue);
                        }
                        // FIXME proper edition
-                       saveJcrSession();
+                       saveEditedNode(node);
                        return old;
                } catch (RepositoryException e) {
                        throw new JcrException("Cannot set property " + key + " on " + jcrPath + " in " + jcrWorkspace, e);
@@ -436,7 +435,7 @@ public class JcrContent extends AbstractContent {
                                node.addMixin(nodeType.getName());
                        }
                        // FIXME proper edition
-                       saveJcrSession();
+                       saveEditedNode(node);
                } catch (RepositoryException e) {
                        throw new JcrException(
                                        "Cannot add content classes " + contentClass + " to " + jcrPath + " in " + jcrWorkspace, e);
@@ -509,42 +508,28 @@ public class JcrContent extends AbstractContent {
                try {
                        if (InputStream.class.isAssignableFrom(clss)) {
                                Node node = getJcrNode();
+//                             System.out.println(node.getSession());
                                if (Jcr.isNodeType(node, NodeType.NT_FILE)) {
                                        return (C) JcrUtils.getFileAsStream(node);
                                }
                        } else if (OutputStream.class.isAssignableFrom(clss)) {
-                               Node node = getJcrNode();
+                               Node node = openForEdit();
+//                             System.out.println(node.getSession());
                                if (Jcr.isNodeType(node, NodeType.NT_FILE)) {
                                        Node content = node.getNode(Node.JCR_CONTENT);
-                                       PipedInputStream in = new PipedInputStream();
+                                       AsyncPipedOutputStream out = new AsyncPipedOutputStream();
+
                                        ValueFactory valueFactory = getJcrSession().getValueFactory();
-                                       CompletableFuture<Void> done = CompletableFuture.runAsync(() -> {
+                                       out.asyncRead((in) -> {
                                                try {
                                                        Binary binary = valueFactory.createBinary(in);
                                                        content.setProperty(Property.JCR_DATA, binary);
-                                                       saveJcrSession();
+                                                       saveEditedNode(node);
                                                } catch (RepositoryException e) {
                                                        throw new JcrException(
                                                                        "Cannot create binary in " + jcrPath + " in workspace " + jcrWorkspace, e);
                                                }
                                        });
-                                       PipedOutputStream out = new PipedOutputStream(in) {
-
-                                               @Override
-                                               public void close() throws IOException {
-                                                       super.flush();
-                                                       super.close();
-                                                       done.join();
-//                                                     Binary binary = done.join();
-//                                                     try {
-//                                                             content.setProperty(Property.JCR_DATA, binary);
-//                                                     } catch (RepositoryException e) {
-//                                                             throw new JcrException(
-//                                                                             "Cannot write binary to " + jcrPath + " in workspace " + jcrWorkspace, e);
-//                                                     }
-//                                                     saveJcrSession();
-                                               }
-                                       };
                                        return (C) out;
                                }
                        }
@@ -697,7 +682,14 @@ public class JcrContent extends AbstractContent {
         * COMMON UTILITIES
         */
        protected Session getJcrSession() {
-               return provider.getJcrSession(getSession(), jcrWorkspace);
+               Session s = provider.getJcrSession(getSession(), jcrWorkspace);
+//             if (getSession().isEditing())
+//                     try {
+//                             s.refresh(false);
+//                     } catch (RepositoryException e) {
+//                             throw new JcrException("Cannot refresh session", e);
+//                     }
+               return s;
        }
 
        protected Node getJcrNode() {