Improve links.
[gpl/argeo-suite.git] / publishing / org.argeo.publishing.ui / src / org / argeo / docbook / ui / DbkImageManager.java
1 package org.argeo.docbook.ui;
2
3 import static javax.jcr.Node.JCR_CONTENT;
4 import static javax.jcr.Property.JCR_DATA;
5 import static javax.jcr.nodetype.NodeType.NT_FILE;
6
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.UnsupportedEncodingException;
10 import java.net.URI;
11 import java.net.URISyntaxException;
12 import java.net.URLEncoder;
13 import java.nio.charset.StandardCharsets;
14
15 import javax.jcr.Binary;
16 import javax.jcr.Node;
17 import javax.jcr.RepositoryException;
18 import javax.jcr.nodetype.NodeType;
19
20 import org.argeo.cms.ui.CmsImageManager;
21 import org.argeo.cms.ui.util.CmsUiUtils;
22 import org.argeo.cms.ui.util.DefaultImageManager;
23 import org.argeo.docbook.DbkUtils;
24 import org.argeo.docbook.DbkAttr;
25 import org.argeo.docbook.DbkType;
26 import org.argeo.entity.EntityNames;
27 import org.argeo.entity.EntityType;
28 import org.argeo.jcr.JcrException;
29 import org.argeo.jcr.JcrUtils;
30 import org.eclipse.swt.graphics.ImageData;
31 import org.eclipse.swt.graphics.Point;
32
33 /** Add DocBook images support to {@link CmsImageManager}. */
34 public class DbkImageManager extends DefaultImageManager {
35         private Node baseFolder = null;
36
37         public DbkImageManager(Node baseFolder) {
38                 this.baseFolder = baseFolder;
39         }
40
41         Node getImageDataNode(Node mediaObjectNode) throws RepositoryException {
42                 if (mediaObjectNode.hasNode(DbkType.imageobject.get())) {
43                         Node imageDataNode = mediaObjectNode.getNode(DbkType.imageobject.get()).getNode(DbkType.imagedata.get());
44                         return imageDataNode;
45                 } else {
46                         throw new IllegalStateException("No image data found for " + mediaObjectNode);
47                 }
48         }
49
50         @Override
51         public Binary getImageBinary(Node node) throws RepositoryException {
52                 Node fileNode = null;
53                 if (DbkUtils.isDbk(node, DbkType.mediaobject)) {
54                         Node imageDataNode = getImageDataNode(node);
55                         fileNode = getFileNode(imageDataNode);
56                 }
57                 if (node.isNodeType(NT_FILE)) {
58                         fileNode = node;
59                 }
60                 if (fileNode != null) {
61                         return node.getNode(JCR_CONTENT).getProperty(JCR_DATA).getBinary();
62                 } else {
63                         return null;
64                 }
65         }
66
67         public Point getImageSize(Node mediaObjectNode) throws RepositoryException {
68                 Node imageDataNode = getImageDataNode(mediaObjectNode);
69                 Node fileNode = getFileNode(imageDataNode);
70                 if (fileNode == null)
71                         return new Point(0, 0);
72                 Point intrinsicSize;
73                 if (fileNode.hasProperty(EntityNames.SVG_WIDTH) && fileNode.hasProperty(EntityNames.SVG_HEIGHT)) {
74                         int width = (int) fileNode.getProperty(EntityNames.SVG_WIDTH).getLong();
75                         int height = (int) fileNode.getProperty(EntityNames.SVG_HEIGHT).getLong();
76                         intrinsicSize = new Point(width, height);
77                 } else {
78                         try (InputStream in = JcrUtils.getFileAsStream(fileNode)) {
79                                 ImageData id = new ImageData(in);
80                                 intrinsicSize = updateSize(fileNode, id);
81                         } catch (IOException e) {
82                                 throw new RuntimeException("Cannot load file " + fileNode, e);
83                         }
84                 }
85                 // TODO interpret image data infos
86                 return intrinsicSize;
87         }
88
89         protected Point updateSize(Node fileNode, ImageData id) throws RepositoryException {
90                 fileNode.addMixin(EntityType.box.get());
91                 fileNode.setProperty(EntityNames.SVG_WIDTH, id.width);
92                 fileNode.setProperty(EntityNames.SVG_HEIGHT, id.height);
93                 return new Point(id.width, id.height);
94         }
95
96         @Override
97         protected void processNewImageFile(Node mediaObjectNode, Node fileNode, ImageData id)
98                         throws RepositoryException, IOException {
99                 Node imageDataNode = getImageDataNode(mediaObjectNode);
100                 updateSize(fileNode, id);
101                 String filePath = fileNode.getPath();
102                 String relPath = filePath.substring(baseFolder.getPath().length() + 1);
103                 imageDataNode.setProperty(DbkAttr.fileref.name(), relPath);
104         }
105
106         @Override
107         public String getImageUrl(Node mediaObjectNode) throws RepositoryException {
108                 Node imageDataNode = getImageDataNode(mediaObjectNode);
109                 // TODO factorise
110                 String fileref = null;
111                 if (imageDataNode.hasProperty(DbkAttr.fileref.name()))
112                         fileref = imageDataNode.getProperty(DbkAttr.fileref.name()).getString();
113                 if (fileref == null)
114                         return null;
115                 URI fileUri;
116                 try {
117                         // FIXME it messes up with the '/'
118                         fileUri = new URI(URLEncoder.encode(fileref, StandardCharsets.UTF_8.toString()));
119                 } catch (URISyntaxException | UnsupportedEncodingException e) {
120                         throw new IllegalArgumentException("File ref in " + imageDataNode + " is badly formatted", e);
121                 }
122                 if (fileUri.getScheme() != null)
123                         return fileUri.toString();
124                 // local
125                 Node fileNode = getFileNode(imageDataNode);
126                 String url = CmsUiUtils.getDataPathForUrl(fileNode);
127                 return url;
128         }
129
130         protected Node getFileNode(Node imageDataNode) throws RepositoryException {
131                 // FIXME make URL use case more robust
132                 String fileref = null;
133                 if (imageDataNode.hasProperty(DbkAttr.fileref.name()))
134                         fileref = imageDataNode.getProperty(DbkAttr.fileref.name()).getString();
135                 if (fileref == null)
136                         return null;
137                 Node fileNode;
138                 if (fileref.startsWith("/"))
139                         fileNode = baseFolder.getSession().getNode(fileref);
140                 else
141                         fileNode = baseFolder.getNode(fileref);
142                 return fileNode;
143         }
144
145         protected Node getMediaFolder() {
146                 try {
147                         // TODO check edition status
148                         Node mediaFolder = JcrUtils.getOrAdd(baseFolder, EntityNames.MEDIA, NodeType.NT_FOLDER);
149                         return mediaFolder;
150                 } catch (RepositoryException e) {
151                         throw new JcrException("Cannot get media folder", e);
152                 }
153         }
154 }