]> git.argeo.org Git - gpl/argeo-suite.git/blob - org.argeo.app.core/src/org/argeo/app/docbook/DbkUtils.java
Instrument image utils
[gpl/argeo-suite.git] / org.argeo.app.core / src / org / argeo / app / docbook / DbkUtils.java
1 package org.argeo.app.docbook;
2
3 import static org.argeo.app.docbook.DbkType.para;
4
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.OutputStream;
8 import java.nio.file.Files;
9 import java.nio.file.Path;
10
11 import javax.jcr.ImportUUIDBehavior;
12 import javax.jcr.Node;
13 import javax.jcr.NodeIterator;
14 import javax.jcr.PathNotFoundException;
15 import javax.jcr.RepositoryException;
16 import javax.jcr.ValueFormatException;
17
18 import org.argeo.api.cms.CmsLog;
19 import org.argeo.app.api.EntityType;
20 import org.argeo.jcr.Jcr;
21 import org.argeo.jcr.JcrException;
22 import org.argeo.jcr.JcrUtils;
23 import org.argeo.jcr.JcrxApi;
24
25 /** Utilities around DocBook. */
26 public class DbkUtils {
27 private final static CmsLog log = CmsLog.getLog(DbkUtils.class);
28
29 /** Get or add a DocBook element. */
30 public static Node getOrAddDbk(Node parent, DbkType child) {
31 try {
32 if (!parent.hasNode(child.get())) {
33 return addDbk(parent, child);
34 } else {
35 return parent.getNode(child.get());
36 }
37 } catch (RepositoryException e) {
38 throw new JcrException("Cannot get or add element " + child.get() + " to " + parent, e);
39 }
40 }
41
42 /** Add a DocBook element to this node. */
43 public static Node addDbk(Node parent, DbkType child) {
44 try {
45 Node node = parent.addNode(child.get(), child.get());
46 return node;
47 } catch (RepositoryException e) {
48 throw new JcrException("Cannot add element " + child.get() + " to " + parent, e);
49 }
50 }
51
52 /** Whether this DocBook element is of this type. */
53 public static boolean isDbk(Node node, DbkType type) {
54 return Jcr.getName(node).equals(type.get());
55 }
56
57 /** Whether this node is a DocBook type. */
58 public static boolean isDbk(Node node) {
59 String name = Jcr.getName(node);
60 for (DbkType type : DbkType.values()) {
61 if (name.equals(type.get()))
62 return true;
63 }
64 return false;
65 }
66
67 public static String getTitle(Node node) {
68 return JcrxApi.getXmlValue(node, DbkType.title.get());
69 }
70
71 public static void setTitle(Node node, String txt) {
72 Node titleNode = getOrAddDbk(node, DbkType.title);
73 JcrxApi.setXmlValue(node, titleNode, txt);
74 }
75
76 public static Node getMetadata(Node infoContainer) {
77 try {
78 if (!infoContainer.hasNode(DbkType.info.get()))
79 return null;
80 Node info = infoContainer.getNode(DbkType.info.get());
81 if (!info.hasNode(EntityType.local.get()))
82 return null;
83 return info.getNode(EntityType.local.get());
84 } catch (RepositoryException e) {
85 throw new JcrException("Cannot retrieve metadata from " + infoContainer, e);
86 }
87 }
88
89 public static Node getChildByRole(Node parent, String role) {
90 try {
91 NodeIterator baseSections = parent.getNodes();
92 while (baseSections.hasNext()) {
93 Node n = baseSections.nextNode();
94 String r = Jcr.get(n, DbkAttr.role.name());
95 if (r != null && r.equals(role))
96 return n;
97 }
98 return null;
99 } catch (RepositoryException e) {
100 throw new JcrException("Cannot get child from " + parent + " with role " + role, e);
101 }
102 }
103
104 public static Node addParagraph(Node node, String txt) {
105 Node p = addDbk(node, para);
106 JcrxApi.setXmlValue(node, p, txt);
107 return p;
108 }
109
110 /**
111 * Removes a paragraph if it empty. The sesison is not saved.
112 *
113 * @return true if the paragraph was empty and it was removed
114 */
115 public static boolean removeIfEmptyParagraph(Node node) {
116 try {
117 if (isDbk(node, DbkType.para)) {
118 NodeIterator nit = node.getNodes();
119 if (!nit.hasNext()) {
120 node.remove();
121 return true;
122 }
123 Node first = nit.nextNode();
124 if (nit.hasNext())
125 return false;
126 if (first.getName().equals(Jcr.JCR_XMLTEXT)) {
127 String str = Jcr.get(first, Jcr.JCR_XMLCHARACTERS);
128 if (str != null && str.trim().equals("")) {
129 node.remove();
130 return true;
131 }
132 } else {
133 return false;
134 }
135 }
136 return false;
137 } catch (RepositoryException e) {
138 throw new JcrException("Cannot remove possibly empty paragraph", e);
139 }
140 }
141
142 public static Node insertImageAfter(Node sibling) {
143 try {
144
145 Node parent = sibling.getParent();
146 Node mediaNode = addDbk(parent, DbkType.mediaobject);
147 // TODO optimise?
148 parent.orderBefore(mediaNode.getName() + "[" + mediaNode.getIndex() + "]",
149 sibling.getName() + "[" + sibling.getIndex() + "]");
150 parent.orderBefore(sibling.getName() + "[" + sibling.getIndex() + "]",
151 mediaNode.getName() + "[" + mediaNode.getIndex() + "]");
152
153 Node imageNode = addDbk(mediaNode, DbkType.imageobject);
154 Node imageDataNode = addDbk(imageNode, DbkType.imagedata);
155 // Node infoNode = imageNode.addNode(DocBookTypes.INFO, DocBookTypes.INFO);
156 // Node fileNode = JcrUtils.copyBytesAsFile(mediaFolder, EntityType.box.get(), new byte[0]);
157 // fileNode.addMixin(EntityType.box.get());
158 // fileNode.setProperty(EntityNames.SVG_WIDTH, 0);
159 // fileNode.setProperty(EntityNames.SVG_LENGTH, 0);
160 // fileNode.addMixin(NodeType.MIX_MIMETYPE);
161 //
162 // // we assume this is a folder next to the main DocBook document
163 // // TODO make it more robust and generic
164 // String fileRef = mediaNode.getName();
165 // imageDataNode.setProperty(DocBookNames.DBK_FILEREF, fileRef);
166 return mediaNode;
167 } catch (RepositoryException e) {
168 throw new JcrException("Cannot insert empty image after " + sibling, e);
169 }
170 }
171
172 public static Node insertVideoAfter(Node sibling) {
173 try {
174
175 Node parent = sibling.getParent();
176 Node mediaNode = addDbk(parent, DbkType.mediaobject);
177 // TODO optimise?
178 parent.orderBefore(mediaNode.getName() + "[" + mediaNode.getIndex() + "]",
179 sibling.getName() + "[" + sibling.getIndex() + "]");
180 parent.orderBefore(sibling.getName() + "[" + sibling.getIndex() + "]",
181 mediaNode.getName() + "[" + mediaNode.getIndex() + "]");
182
183 Node videoNode = addDbk(mediaNode, DbkType.videoobject);
184 Node videoDataNode = addDbk(videoNode, DbkType.videodata);
185 return mediaNode;
186 } catch (RepositoryException e) {
187 throw new JcrException("Cannot insert empty image after " + sibling, e);
188 }
189 }
190
191 public static String getMediaFileref(Node node) {
192 try {
193 Node mediadata;
194 if (node.hasNode(DbkType.imageobject.get())) {
195 mediadata = node.getNode(DbkType.imageobject.get()).getNode(DbkType.imagedata.get());
196 } else if (node.hasNode(DbkType.videoobject.get())) {
197 mediadata = node.getNode(DbkType.videoobject.get()).getNode(DbkType.videodata.get());
198 } else {
199 throw new IllegalArgumentException("Fileref not found in " + node);
200 }
201
202 if (mediadata.hasProperty(DbkAttr.fileref.name())) {
203 return mediadata.getProperty(DbkAttr.fileref.name()).getString();
204 } else {
205 return null;
206 }
207 } catch (RepositoryException e) {
208 throw new JcrException("Cannot retrieve file ref from " + node, e);
209 }
210 }
211
212 public static void exportXml(Node node, OutputStream out) throws IOException {
213 try {
214 node.getSession().exportDocumentView(node.getPath(), out, false, false);
215 } catch (RepositoryException e) {
216 throw new JcrException("Cannot export " + node + " to XML", e);
217 }
218 }
219
220 public static void exportToFs(Node baseNode, DbkType type, Path directory) {
221 String fileName = Jcr.getName(baseNode) + ".dbk.xml";
222 Path filePath = directory.resolve(fileName);
223 Node docBookNode = Jcr.getNode(baseNode, type.get());
224 if (docBookNode == null)
225 throw new IllegalArgumentException("No " + type.get() + " under " + baseNode);
226 try {
227 Files.createDirectories(directory);
228 try (OutputStream out = Files.newOutputStream(filePath)) {
229 exportXml(docBookNode, out);
230 }
231 JcrUtils.copyFilesToFs(baseNode, directory, true);
232 if (log.isDebugEnabled())
233 log.debug("DocBook " + baseNode + " exported to " + filePath.toAbsolutePath());
234 } catch (IOException e) {
235 throw new RuntimeException(e);
236 }
237 }
238
239 public static void importXml(Node baseNode, InputStream in) throws IOException {
240 try {
241 baseNode.getSession().importXML(baseNode.getPath(), in,
242 ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
243 } catch (RepositoryException e) {
244 throw new JcrException("Cannot import XML to " + baseNode, e);
245 }
246
247 }
248
249 /** Singleton. */
250 private DbkUtils() {
251 }
252
253 }