X-Git-Url: https://git.argeo.org/?p=gpl%2Fargeo-suite.git;a=blobdiff_plain;f=publishing%2Forg.argeo.publishing.ui%2Fsrc%2Forg%2Fargeo%2Fdocbook%2FDbkUtils.java;h=151bf10db690a0ae538e95ab061fc10d42996892;hp=e153e86c39f226456c0d9f246bff00ddaf1742c5;hb=4d8967c70edd1051e97ebdc393cbe2cd59d2b8b6;hpb=1f5f12ce52315e19fb0016527c31127b70dceb5d diff --git a/publishing/org.argeo.publishing.ui/src/org/argeo/docbook/DbkUtils.java b/publishing/org.argeo.publishing.ui/src/org/argeo/docbook/DbkUtils.java index e153e86..151bf10 100644 --- a/publishing/org.argeo.publishing.ui/src/org/argeo/docbook/DbkUtils.java +++ b/publishing/org.argeo.publishing.ui/src/org/argeo/docbook/DbkUtils.java @@ -1,13 +1,22 @@ package org.argeo.docbook; +import static org.argeo.docbook.DbkType.para; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +import javax.jcr.ImportUUIDBehavior; import javax.jcr.Node; import javax.jcr.NodeIterator; +import javax.jcr.PathNotFoundException; import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; +import javax.jcr.ValueFormatException; -import org.argeo.docbook.ui.DocBookNames; -import org.argeo.docbook.ui.DocBookTypes; -import org.argeo.entity.EntityNames; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.argeo.entity.EntityType; import org.argeo.jcr.Jcr; import org.argeo.jcr.JcrException; @@ -16,24 +25,60 @@ import org.argeo.jcr.JcrxApi; /** Utilities around DocBook. */ public class DbkUtils { - public static String getTitle(Node node) { - return JcrxApi.getXmlValue(node, DocBookTypes.TITLE); + private final static Log log = LogFactory.getLog(DbkUtils.class); + + /** Get or add a DocBook element. */ + public static Node getOrAddDbk(Node parent, DbkType child) { + try { + if (!parent.hasNode(child.get())) { + return addDbk(parent, child); + } else { + return parent.getNode(child.get()); + } + } catch (RepositoryException e) { + throw new JcrException("Cannot get or add element " + child.get() + " to " + parent, e); + } } - public static void setTitle(Node node, String txt) { + /** Add a DocBook element to this node. */ + public static Node addDbk(Node parent, DbkType child) { try { - Node titleNode = JcrUtils.getOrAdd(node, DocBookTypes.TITLE, DocBookTypes.TITLE); - JcrxApi.setXmlValue(node, titleNode, txt); + Node node = parent.addNode(child.get(), child.get()); + return node; } catch (RepositoryException e) { - throw new JcrException("Cannot add empty paragraph to " + node, e); + throw new JcrException("Cannot add element " + child.get() + " to " + parent, e); } } + /** Whether this DocBook element is of this type. */ + public static boolean isDbk(Node node, DbkType type) { + return Jcr.getName(node).equals(type.get()); + } + + /** Whether this node is a DocBook type. */ + public static boolean isDbk(Node node) { + String name = Jcr.getName(node); + for (DbkType type : DbkType.values()) { + if (name.equals(type.get())) + return true; + } + return false; + } + + public static String getTitle(Node node) { + return JcrxApi.getXmlValue(node, DbkType.title.get()); + } + + public static void setTitle(Node node, String txt) { + Node titleNode = getOrAddDbk(node, DbkType.title); + JcrxApi.setXmlValue(node, titleNode, txt); + } + public static Node getMetadata(Node infoContainer) { try { - if (!infoContainer.hasNode(DocBookTypes.INFO)) + if (!infoContainer.hasNode(DbkType.info.get())) return null; - Node info = infoContainer.getNode(DocBookTypes.INFO); + Node info = infoContainer.getNode(DbkType.info.get()); if (!info.hasNode(EntityType.local.get())) return null; return info.getNode(EntityType.local.get()); @@ -47,7 +92,7 @@ public class DbkUtils { NodeIterator baseSections = parent.getNodes(); while (baseSections.hasNext()) { Node n = baseSections.nextNode(); - String r = Jcr.get(n, DocBookNames.DBK_ROLE); + String r = Jcr.get(n, DbkAttr.role.name()); if (r != null && r.equals(role)) return n; } @@ -58,33 +103,56 @@ public class DbkUtils { } public static Node addParagraph(Node node, String txt) { + Node p = addDbk(node, para); + JcrxApi.setXmlValue(node, p, txt); + return p; + } + + /** + * Removes a paragraph if it empty. The sesison is not saved. + * + * @return true if the paragraph was empty and it was removed + */ + public static boolean removeIfEmptyParagraph(Node node) { try { - Node para = node.addNode(DocBookTypes.PARA, DocBookTypes.PARA); - JcrxApi.setXmlValue(node, para, txt); - return para; + if (isDbk(node, DbkType.para)) { + NodeIterator nit = node.getNodes(); + if (!nit.hasNext()) { + node.remove(); + return true; + } + Node first = nit.nextNode(); + if (nit.hasNext()) + return false; + if (first.getName().equals(Jcr.JCR_XMLTEXT)) { + String str = Jcr.get(first, Jcr.JCR_XMLCHARACTERS); + if (str != null && str.trim().equals("")) { + node.remove(); + return true; + } + } else { + return false; + } + } + return false; } catch (RepositoryException e) { - throw new JcrException("Cannot add empty paragraph to " + node, e); + throw new JcrException("Cannot remove possibly empty paragraph", e); } } public static Node insertImageAfter(Node sibling) { try { - // FIXME make it more robust - if (DocBookTypes.IMAGEDATA.equals(sibling.getName())) { - sibling = sibling.getParent().getParent(); - } - Node parent = sibling.getParent(); - Node mediaNode = parent.addNode(DocBookTypes.MEDIAOBJECT, DocBookTypes.MEDIAOBJECT); + Node mediaNode = addDbk(parent, DbkType.mediaobject); // TODO optimise? parent.orderBefore(mediaNode.getName() + "[" + mediaNode.getIndex() + "]", sibling.getName() + "[" + sibling.getIndex() + "]"); parent.orderBefore(sibling.getName() + "[" + sibling.getIndex() + "]", mediaNode.getName() + "[" + mediaNode.getIndex() + "]"); - Node imageNode = mediaNode.addNode(DocBookTypes.IMAGEOBJECT, DocBookTypes.IMAGEOBJECT); - Node imageDataNode = imageNode.addNode(DocBookTypes.IMAGEDATA, DocBookTypes.IMAGEDATA); + Node imageNode = addDbk(mediaNode, DbkType.imageobject); + Node imageDataNode = addDbk(imageNode, DbkType.imagedata); // Node infoNode = imageNode.addNode(DocBookTypes.INFO, DocBookTypes.INFO); // Node fileNode = JcrUtils.copyBytesAsFile(mediaFolder, EntityType.box.get(), new byte[0]); // fileNode.addMixin(EntityType.box.get()); @@ -96,13 +164,91 @@ public class DbkUtils { // // TODO make it more robust and generic // String fileRef = mediaNode.getName(); // imageDataNode.setProperty(DocBookNames.DBK_FILEREF, fileRef); - return imageDataNode; + return mediaNode; } catch (RepositoryException e) { throw new JcrException("Cannot insert empty image after " + sibling, e); } } + public static Node insertVideoAfter(Node sibling) { + try { + + Node parent = sibling.getParent(); + Node mediaNode = addDbk(parent, DbkType.mediaobject); + // TODO optimise? + parent.orderBefore(mediaNode.getName() + "[" + mediaNode.getIndex() + "]", + sibling.getName() + "[" + sibling.getIndex() + "]"); + parent.orderBefore(sibling.getName() + "[" + sibling.getIndex() + "]", + mediaNode.getName() + "[" + mediaNode.getIndex() + "]"); + + Node videoNode = addDbk(mediaNode, DbkType.videoobject); + Node videoDataNode = addDbk(videoNode, DbkType.videodata); + return mediaNode; + } catch (RepositoryException e) { + throw new JcrException("Cannot insert empty image after " + sibling, e); + } + } + + public static String getMediaFileref(Node node) { + try { + Node mediadata; + if (node.hasNode(DbkType.imageobject.get())) { + mediadata = node.getNode(DbkType.imageobject.get()).getNode(DbkType.imagedata.get()); + } else if (node.hasNode(DbkType.videoobject.get())) { + mediadata = node.getNode(DbkType.videoobject.get()).getNode(DbkType.videodata.get()); + } else { + throw new IllegalArgumentException("Fileref not found in " + node); + } + + if (mediadata.hasProperty(DbkAttr.fileref.name())) { + return mediadata.getProperty(DbkAttr.fileref.name()).getString(); + } else { + return null; + } + } catch (RepositoryException e) { + throw new JcrException("Cannot retrieve file ref from " + node, e); + } + } + + public static void exportXml(Node node, OutputStream out) throws IOException { + try { + node.getSession().exportDocumentView(node.getPath(), out, false, false); + } catch (RepositoryException e) { + throw new JcrException("Cannot export " + node + " to XML", e); + } + } + + public static void exportToFs(Node baseNode, DbkType type, Path directory) { + String fileName = Jcr.getName(baseNode) + ".dbk.xml"; + Path filePath = directory.resolve(fileName); + Node docBookNode = Jcr.getNode(baseNode, type.get()); + if (docBookNode == null) + throw new IllegalArgumentException("No " + type.get() + " under " + baseNode); + try { + Files.createDirectories(directory); + try (OutputStream out = Files.newOutputStream(filePath)) { + exportXml(docBookNode, out); + } + JcrUtils.copyFilesToFs(baseNode, directory, true); + if (log.isDebugEnabled()) + log.debug("DocBook " + baseNode + " exported to " + filePath.toAbsolutePath()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static void importXml(Node baseNode, InputStream in) throws IOException { + try { + baseNode.getSession().importXML(baseNode.getPath(), in, + ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING); + } catch (RepositoryException e) { + throw new JcrException("Cannot import XML to " + baseNode, e); + } + + } + /** Singleton. */ private DbkUtils() { } + }