Merge remote-tracking branch 'origin/unstable' into testing
[gpl/argeo-suite.git] / org.argeo.app.ui / src / org / argeo / app / ui / docbook / DbkImageManager.java
diff --git a/org.argeo.app.ui/src/org/argeo/app/ui/docbook/DbkImageManager.java b/org.argeo.app.ui/src/org/argeo/app/ui/docbook/DbkImageManager.java
new file mode 100644 (file)
index 0000000..32bbdd9
--- /dev/null
@@ -0,0 +1,175 @@
+package org.argeo.app.ui.docbook;
+
+import static javax.jcr.Node.JCR_CONTENT;
+import static javax.jcr.Property.JCR_DATA;
+import static javax.jcr.nodetype.NodeType.NT_FILE;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+
+import javax.jcr.Binary;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeType;
+
+import org.argeo.api.cms.Cms2DSize;
+import org.argeo.api.cms.CmsImageManager;
+import org.argeo.app.api.EntityNames;
+import org.argeo.app.api.EntityType;
+import org.argeo.app.docbook.DbkAttr;
+import org.argeo.app.docbook.DbkType;
+import org.argeo.app.docbook.DbkUtils;
+import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.ui.util.DefaultImageManager;
+import org.argeo.jcr.JcrException;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.swt.graphics.ImageData;
+
+/** Add DocBook images support to {@link CmsImageManager}. */
+public class DbkImageManager extends DefaultImageManager {
+       private Node baseFolder = null;
+
+       public DbkImageManager(Node baseFolder) {
+               this.baseFolder = baseFolder;
+       }
+
+       Node getImageDataNode(Node mediaObjectNode) {
+               try {
+                       if (mediaObjectNode.hasNode(DbkType.imageobject.get())) {
+                               Node imageDataNode = mediaObjectNode.getNode(DbkType.imageobject.get())
+                                               .getNode(DbkType.imagedata.get());
+                               return imageDataNode;
+                       } else {
+                               throw new IllegalStateException("No image data found for " + mediaObjectNode);
+                       }
+               } catch (RepositoryException e) {
+                       throw new JcrException(e);
+               }
+       }
+
+       @Override
+       public Binary getImageBinary(Node node) {
+               Node fileNode = null;
+               if (DbkUtils.isDbk(node, DbkType.mediaobject)) {
+                       Node imageDataNode = getImageDataNode(node);
+                       fileNode = getFileNode(imageDataNode);
+               }
+               try {
+                       if (node.isNodeType(NT_FILE)) {
+                               fileNode = node;
+                       }
+                       if (fileNode != null) {
+                               return node.getNode(JCR_CONTENT).getProperty(JCR_DATA).getBinary();
+                       } else {
+                               return null;
+                       }
+               } catch (RepositoryException e) {
+                       throw new JcrException(e);
+               }
+       }
+
+       public Cms2DSize getImageSize(Node mediaObjectNode) {
+               Node imageDataNode = getImageDataNode(mediaObjectNode);
+               Node fileNode = getFileNode(imageDataNode);
+               if (fileNode == null)
+                       return new Cms2DSize(0, 0);
+               try {
+                       Cms2DSize intrinsicSize;
+                       if (fileNode.hasProperty(EntityNames.SVG_WIDTH) && fileNode.hasProperty(EntityNames.SVG_HEIGHT)) {
+                               int width = (int) fileNode.getProperty(EntityNames.SVG_WIDTH).getLong();
+                               int height = (int) fileNode.getProperty(EntityNames.SVG_HEIGHT).getLong();
+                               intrinsicSize = new Cms2DSize(width, height);
+                       } else {
+                               try (InputStream in = JcrUtils.getFileAsStream(fileNode)) {
+                                       ImageData id = new ImageData(in);
+                                       intrinsicSize = updateSize(fileNode, id);
+                               } catch (IOException e) {
+                                       throw new RuntimeException("Cannot load file " + fileNode, e);
+                               }
+                       }
+                       // TODO interpret image data infos
+                       return intrinsicSize;
+               } catch (RepositoryException e) {
+                       throw new JcrException(e);
+               }
+       }
+
+       protected Cms2DSize updateSize(Node fileNode, ImageData id) throws RepositoryException {
+               fileNode.addMixin(EntityType.box.get());
+               fileNode.setProperty(EntityNames.SVG_WIDTH, id.width);
+               fileNode.setProperty(EntityNames.SVG_HEIGHT, id.height);
+               return new Cms2DSize(id.width, id.height);
+       }
+
+       @Override
+       protected void processNewImageFile(Node mediaObjectNode, Node fileNode, ImageData id)
+                       throws RepositoryException, IOException {
+               Node imageDataNode = getImageDataNode(mediaObjectNode);
+               updateSize(fileNode, id);
+               String filePath = fileNode.getPath();
+               String relPath = filePath.substring(baseFolder.getPath().length() + 1);
+               imageDataNode.setProperty(DbkAttr.fileref.name(), relPath);
+       }
+
+       @Override
+       public String getImageUrl(Node mediaObjectNode) {
+               Node imageDataNode = getImageDataNode(mediaObjectNode);
+               // TODO factorise
+               String fileref = null;
+               try {
+                       if (imageDataNode.hasProperty(DbkAttr.fileref.name()))
+                               fileref = imageDataNode.getProperty(DbkAttr.fileref.name()).getString();
+               } catch (RepositoryException e) {
+                       throw new JcrException(e);
+               }
+               if (fileref == null)
+                       return null;
+               URI fileUri;
+               try {
+                       // FIXME it messes up with the '/'
+                       fileUri = new URI(URLEncoder.encode(fileref, StandardCharsets.UTF_8.toString()));
+               } catch (URISyntaxException | UnsupportedEncodingException e) {
+                       throw new IllegalArgumentException("File ref in " + imageDataNode + " is badly formatted", e);
+               }
+               if (fileUri.getScheme() != null)
+                       return fileUri.toString();
+               // local
+               Node fileNode = getFileNode(imageDataNode);
+               String url = CmsUiUtils.getDataPathForUrl(fileNode);
+               return url;
+       }
+
+       protected Node getFileNode(Node imageDataNode) {
+               // FIXME make URL use case more robust
+               try {
+                       String fileref = null;
+                       if (imageDataNode.hasProperty(DbkAttr.fileref.name()))
+                               fileref = imageDataNode.getProperty(DbkAttr.fileref.name()).getString();
+                       if (fileref == null)
+                               return null;
+                       Node fileNode;
+                       if (fileref.startsWith("/"))
+                               fileNode = baseFolder.getSession().getNode(fileref);
+                       else
+                               fileNode = baseFolder.getNode(fileref);
+                       return fileNode;
+               } catch (RepositoryException e) {
+                       throw new JcrException(e);
+               }
+       }
+
+       protected Node getMediaFolder() {
+               try {
+                       // TODO check edition status
+                       Node mediaFolder = JcrUtils.getOrAdd(baseFolder, EntityNames.MEDIA, NodeType.NT_FOLDER);
+                       return mediaFolder;
+               } catch (RepositoryException e) {
+                       throw new JcrException("Cannot get media folder", e);
+               }
+       }
+}