Centralise configure script
[lgpl/argeo-commons.git] / jcr / org.argeo.cms.jcr / src / org / argeo / cms / jcr / acr / JcrContentUtils.java
index 702f4d6ba36fc91d6bbe6ea6a5252c5bbca79509..25e54b302678b602c334cd22f7bb3ce78e9a8b7a 100644 (file)
@@ -4,16 +4,23 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.PipedInputStream;
 import java.io.PipedOutputStream;
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
 import javax.jcr.RepositoryException;
+import javax.jcr.Value;
 import javax.jcr.nodetype.NodeType;
 import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
 import javax.xml.namespace.QName;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -24,6 +31,7 @@ import javax.xml.transform.dom.DOMSource;
 import org.argeo.api.acr.Content;
 import org.argeo.api.acr.ContentName;
 import org.argeo.api.acr.CrName;
+import org.argeo.api.acr.DName;
 import org.argeo.api.acr.NamespaceUtils;
 import org.argeo.api.acr.spi.ProvidedContent;
 import org.argeo.api.acr.spi.ProvidedSession;
@@ -42,8 +50,12 @@ import org.xml.sax.SAXException;
 public class JcrContentUtils {
        private final static CmsLog log = CmsLog.getLog(JcrContentUtils.class);
 
-       public static void copyFiles(Node folder, Content collection) {
+       public static void copyFiles(Node folder, Content collection, String... additionalCollectionTypes) {
                try {
+                       log.debug("Copy collection " + collection);
+
+                       NamespaceContext jcrNamespaceContext = new JcrSessionNamespaceContext(folder.getSession());
+
                        nodes: for (NodeIterator it = folder.getNodes(); it.hasNext();) {
                                Node node = it.nextNode();
                                String name = node.getName();
@@ -53,29 +65,47 @@ public class JcrContentUtils {
                                                file.write(InputStream.class).complete(in);
                                        }
                                } else if (node.isNodeType(NodeType.NT_FOLDER)) {
-                                       Content subCol = collection.add(name, CrName.collection.qName());
-                                       copyFiles(node, subCol);
+                                       Content subCol = collection.add(name, DName.collection.qName());
+                                       copyFiles(node, subCol, additionalCollectionTypes);
                                } else {
-                                       QName qName = NamespaceUtils.parsePrefixedName(name);
-                                       if (NamespaceUtils.hasNamespace(qName)) {
-                                               if (node.getIndex() > 1) {
-                                                       log.warn("Same name siblings not supported, skipping " + node);
+                                       List<QName> contentClasses = typesAsContentClasses(node, jcrNamespaceContext);
+                                       for (String collectionType : additionalCollectionTypes) {
+                                               if (node.isNodeType(collectionType)) {
+                                                       contentClasses.add(DName.collection.qName());
+                                                       Content subCol = collection.add(name,
+                                                                       contentClasses.toArray(new QName[contentClasses.size()]));
+                                                       setAttributes(node, subCol, jcrNamespaceContext);
+//                                                     setContentClasses(node, subCol, jcrNamespaceContext);
+                                                       copyFiles(node, subCol, additionalCollectionTypes);
                                                        continue nodes;
                                                }
-                                               Content content = collection.add(qName, qName);
-                                               Source source = toSource(node);
-                                               ((ProvidedContent) content).getSession().edit((s) -> {
-                                                       ((ProvidedSession) s).notifyModification((ProvidedContent) content);
-                                                       content.write(Source.class).complete(source);
-//                                                     ContentUtils.traverse(content,
-//                                                                     (c, depth) -> ContentUtils.print(c, System.out, depth, false));
-                                               }).toCompletableFuture().join();
-
-                                       } else {
-                                               // ignore
-                                               log.debug(() -> "Ignored " + node);
+                                       }
+
+                                       QName qName = NamespaceUtils.parsePrefixedName(name);
+//                                     if (NamespaceUtils.hasNamespace(qName)) {
+                                       if (node.getIndex() > 1) {
+                                               log.warn("Same name siblings not supported, skipping " + node);
                                                continue nodes;
                                        }
+                                       Content content = collection.add(qName, contentClasses.toArray(new QName[contentClasses.size()]));
+                                       Source source = toSource(node);
+                                       ((ProvidedContent) content).getSession().edit((s) -> {
+                                               ((ProvidedSession) s).notifyModification((ProvidedContent) content);
+                                               content.write(Source.class).complete(source);
+//                                             try {
+//                                                     //setContentClasses(node, content, jcrNamespaceContext);
+//                                             } catch (RepositoryException e) {
+//                                                     // TODO Auto-generated catch block
+//                                                     e.printStackTrace();
+//                                             }
+                                       }).toCompletableFuture().join();
+                                       setAttributes(node, content, jcrNamespaceContext);
+
+//                                     } else {
+//                                             // ignore
+//                                             log.debug(() -> "Ignored " + node);
+//                                             continue nodes;
+//                                     }
                                }
                        }
                } catch (RepositoryException e) {
@@ -85,7 +115,22 @@ public class JcrContentUtils {
                }
        }
 
-       private static Source toSource(Node node) {
+       private static Source toSource(Node node) throws RepositoryException {
+
+//             try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+//                     node.getSession().exportDocumentView(node.getPath(), out, true, false);
+//                     System.out.println(new String(out.toByteArray(), StandardCharsets.UTF_8));
+////                   DocumentBuilder documentBuilder = DocumentBuilderFactory.newNSInstance().newDocumentBuilder();
+////                   Document document;
+////                   try (ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray())) {
+////                           document = documentBuilder.parse(in);
+////                   }
+////                   cleanJcrDom(document);
+////                   return new DOMSource(document);
+//             } catch (IOException e) {
+//                     throw new RuntimeException(e);
+//             }
+
                try (PipedInputStream in = new PipedInputStream();) {
 
                        CompletableFuture<Document> toDo = CompletableFuture.supplyAsync(() -> {
@@ -112,7 +157,50 @@ public class JcrContentUtils {
 
        }
 
+       public static void setAttributes(Node source, Content target, NamespaceContext jcrNamespaceContext)
+                       throws RepositoryException {
+               properties: for (PropertyIterator pit = source.getProperties(); pit.hasNext();) {
+                       Property p = pit.nextProperty();
+                       // TODO migrate JCR title, last modified, etc. ?
+                       if (p.getName().startsWith("jcr:"))
+                               continue properties;
+                       if (p.isMultiple()) {
+                               List<String> attr = new ArrayList<>();
+                               for (Value value : p.getValues()) {
+                                       attr.add(value.getString());
+                               }
+                               target.put(NamespaceUtils.parsePrefixedName(jcrNamespaceContext, p.getName()), attr);
+                       } else {
+                               target.put(NamespaceUtils.parsePrefixedName(jcrNamespaceContext, p.getName()), p.getString());
+                       }
+               }
+       }
+
+       public static List<QName> typesAsContentClasses(Node source, NamespaceContext jcrNamespaceContext)
+                       throws RepositoryException {
+               // TODO super types?
+               List<QName> contentClasses = new ArrayList<>();
+               contentClasses
+                               .add(NamespaceUtils.parsePrefixedName(jcrNamespaceContext, source.getPrimaryNodeType().getName()));
+               for (NodeType nodeType : source.getMixinNodeTypes()) {
+                       contentClasses.add(NamespaceUtils.parsePrefixedName(jcrNamespaceContext, nodeType.getName()));
+               }
+               // filter out JCR types
+               for (Iterator<QName> it = contentClasses.iterator(); it.hasNext();) {
+                       QName type = it.next();
+                       if (type.getNamespaceURI().equals(JCR_NT_NAMESPACE_URI)
+                                       || type.getNamespaceURI().equals(JCR_MIX_NAMESPACE_URI)) {
+                               it.remove();
+                       }
+               }
+               // target.addContentClasses(contentClasses.toArray(new
+               // QName[contentClasses.size()]));
+               return contentClasses;
+       }
+
        static final String JCR_NAMESPACE_URI = "http://www.jcp.org/jcr/1.0";
+       static final String JCR_NT_NAMESPACE_URI = "http://www.jcp.org/jcr/nt/1.0";
+       static final String JCR_MIX_NAMESPACE_URI = "http://www.jcp.org/jcr/mix/1.0";
 
        public static void cleanJcrDom(Document document) {
                Element documentElement = document.getDocumentElement();
@@ -130,11 +218,11 @@ public class JcrContentUtils {
                                String namespaceUri = attr.getValue();
                                if (!namespaceUris.contains(namespaceUri)) {
                                        toRemove.add(attr);
-                                       //log.debug("Removing "+i+" " + namespaceUri);
+                                       // log.debug("Removing "+i+" " + namespaceUri);
                                }
                        }
                }
-               for(Attr attr:toRemove)
+               for (Attr attr : toRemove)
                        documentElement.removeAttributeNode(attr);
 
        }
@@ -155,6 +243,7 @@ public class JcrContentUtils {
                        if (namespaceUri == null)
                                continue attributes;
                        if (JCR_NAMESPACE_URI.equals(namespaceUri)) {
+                               // FIXME probably wrong to change attributes length
                                element.removeAttributeNode(attr);
                                continue attributes;
                        }