1 package org
.argeo
.app
.swt
.docbook
;
3 import static org
.argeo
.app
.docbook
.DbkAcrUtils
.isDbk
;
4 import static org
.argeo
.app
.docbook
.DbkType
.para
;
5 import static org
.argeo
.app
.docbook
.DbkType
.title
;
7 import java
.io
.IOException
;
8 import java
.io
.StringReader
;
9 import java
.io
.StringWriter
;
10 import java
.util
.List
;
12 import javax
.xml
.transform
.Result
;
13 import javax
.xml
.transform
.Source
;
14 import javax
.xml
.transform
.TransformerException
;
15 import javax
.xml
.transform
.TransformerFactory
;
16 import javax
.xml
.transform
.dom
.DOMResult
;
17 import javax
.xml
.transform
.stream
.StreamResult
;
19 import org
.apache
.commons
.io
.IOUtils
;
20 import org
.argeo
.api
.acr
.Content
;
21 import org
.w3c
.dom
.Element
;
22 import org
.w3c
.dom
.Node
;
23 import org
.w3c
.dom
.NodeList
;
25 /** Based on HTML with a few Wiki-like shortcuts. */
26 public class DbkTextInterpreter
implements TextInterpreter
{
28 private TransformerFactory transformerFactory
= TransformerFactory
.newDefaultInstance();
30 // private String linkCssClass = DbkType.link.name();
33 public void write(Content node
, String content
) {
34 if (isDbk(node
, para
) || isDbk(node
, title
)) {
35 String raw
= convertToStorage(node
, content
);
36 validateBeforeStoring(raw
);
38 String jcrUuid
= null;// node.getIdentifier();
39 // if (node.hasProperty(Property.JCR_UUID))
40 // jcrUuid = node.getProperty(Property.JCR_UUID).getString();
42 // // TODO use time based
43 // jcrUuid = UUID.randomUUID().toString();
44 // node.setProperty(Property.JCR_UUID, jcrUuid);
45 // node.getSession().save();
48 StringBuilder namespaces
= new StringBuilder();
49 namespaces
.append(" xmlns:dbk=\"http://docbook.org/ns/docbook\"");
50 namespaces
.append(" xmlns:jcr=\"http://www.jcp.org/jcr/1.0\"");
51 namespaces
.append(" xmlns:xlink=\"http://www.w3.org/1999/xlink\"");
52 raw
= "<" + node
.getName() + " jcr:uuid=\"" + jcrUuid
+ "\"" + namespaces
+ ">" + raw
+ "</"
53 + node
.getName() + ">";
54 // System.out.println(raw);
55 // try (InputStream in = new ByteArrayInputStream(raw.getBytes(StandardCharsets.UTF_8))) {
56 // node.getSession().importXML(node.getParent().getPath(), in,
57 // ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
58 // // node.getSession().save();
59 // } catch (IOException e) {
60 // throw new IllegalArgumentException("Cannot parse raw content of " + node, e);
64 // DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
66 // try (Reader in = new StringReader(raw)) {
67 // document = documentBuilder.parse(new InputSource(in));
69 // NodeList nl = document.getChildNodes();
70 // for (int i = 0; i < nl.getLength(); i++) {
71 // org.w3c.dom.Node n = nl.item(i);
72 // if (node instanceof Text) {
76 // } catch (ParserConfigurationException | SAXException | IOException e) {
77 // throw new IllegalArgumentException("Cannot parse raw content of " + node, e);
81 // if (!node.hasNode(Jcr.JCR_XMLTEXT))
82 // jcrText = node.addNode(Jcr.JCR_XMLTEXT, JcrxType.JCRX_XMLTEXT);
84 // jcrText = node.getNode(Jcr.JCR_XMLTEXT);
85 // jcrText.setProperty(Jcr.JCR_XMLCHARACTERS, raw);
87 throw new IllegalArgumentException("Don't know how to interpret " + node
);
92 public String
read(Content item
) {
93 String raw
= raw(item
);
94 return convertFromStorage(item
, raw
);
98 public String
raw(Content node
) {
99 if (isDbk(node
, para
) || isDbk(node
, title
)) {
100 try (StringWriter stringWriter
= new StringWriter()) {
101 Source source
= node
.adapt(Source
.class);
102 Result result
= new StreamResult(stringWriter
);
103 transformerFactory
.newTransformer().transform(source
, result
);
104 return stringWriter
.toString();
105 } catch (TransformerException
| IOException e
) {
106 throw new RuntimeException("Could not convert " + node
+ " to XML", e
);
109 // StringBuilder sb = new StringBuilder();
110 // readXml(node, sb);
111 // NodeIterator nit = node.getNodes();
112 // while (nit.hasNext()) {
113 // Node child = nit.nextNode();
114 // if (child.getName().equals(Jcr.JCR_XMLTEXT)) {
115 // Node jcrText = node.getNode(Jcr.JCR_XMLTEXT);
116 // String txt = jcrText.getProperty(Jcr.JCR_XMLCHARACTERS).getString();
117 // // TODO make it more robust
118 // // txt = txt.replace("\n", "").replace("\t", "");
119 // txt = txt.replace("\t", " ");
122 // try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
123 // child.getSession().exportDocumentView(child.getPath(), out, true, false);
124 // sb.append(new String(out.toByteArray(), StandardCharsets.UTF_8));
125 // } catch (IOException e) {
126 // throw new IllegalStateException("Cannot export " + child, e);
130 // return sb.toString();
132 throw new IllegalArgumentException("Don't know how to interpret " + node
);
136 // private void readXml(Content node, StringBuilder sb){
138 // NodeIterator nit = node.getNodes();
139 // while (nit.hasNext()) {
140 // Node child = nit.nextNode();
141 // if (child.getName().equals(Jcr.JCR_XMLTEXT)) {
142 // String txt = child.getProperty(Jcr.JCR_XMLCHARACTERS).getString();
143 // // TODO make it more robust
144 // // txt = txt.replace("\n", "").replace("\t", "");
145 // txt = txt.replace("\t", " ");
148 // sb.append('<').append(child.getName());
149 // PropertyIterator pit = child.getProperties();
150 // properties: while (pit.hasNext()) {
151 // Property p = pit.nextProperty();
152 // if (p.getName().startsWith("jcr:"))
153 // continue properties;
154 // sb.append(' ').append(p.getName()).append("=\"").append(p.getString()).append('\"');
157 // readXml(child, sb);
158 //// try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
159 //// child.getSession().exportDocumentView(child.getPath(), out, true, false);
160 //// sb.append(new String(out.toByteArray(), StandardCharsets.UTF_8));
161 //// } catch (IOException e) {
162 //// throw new IllegalStateException("Cannot export " + child, e);
164 // sb.append("</").append(child.getName()).append('>');
169 private void readAsSimpleHtml(Content node
, StringBuilder sb
) {
170 DOMResult result
= new DOMResult();
172 Source source
= node
.adapt(Source
.class);
173 transformerFactory
.newTransformer().transform(source
, result
);
174 } catch (TransformerException e
) {
175 throw new RuntimeException("Could not convert " + node
+ " to XML", e
);
178 NodeList nl
= result
.getNode().getChildNodes();
179 for (int i
= 0; i
< nl
.getLength(); i
++) {
181 // if (n instanceof Text) {
182 // Text text = (Text) n;
183 // sb.append(text.getTextContent());
185 if (n
instanceof Element
) {
186 Element elem
= (Element
) n
;
187 sb
.append(elem
.getTextContent());
191 // NodeIterator nit = node.getNodes();
192 // while (nit.hasNext()) {
193 // Node child = nit.nextNode();
194 // if (child.getName().equals(Jcr.JCR_XMLTEXT)) {
195 // String txt = child.getProperty(Jcr.JCR_XMLCHARACTERS).getString();
196 // // TODO make it more robust
197 // // txt = txt.replace("\n", "").replace("\t", "");
198 // txt = txt.replace("\t", " ");
199 // String html = textToSimpleHtml(txt);
201 // } else if (child.getName().equals(DbkType.link.get())) {
202 // if (child.hasProperty(DbkAttr.XLINK_HREF)) {
203 // String href = child.getProperty(DbkAttr.XLINK_HREF).getString();
204 // // TODO deal with other forbidden XML characters?
205 // href = href.replace("&", "&");
206 // sb.append("<a class='" + linkCssClass + "' href='").append(href).append("'>");
207 // readAsSimpleHtml(child, sb);
208 // sb.append("</a>");
216 private String
textToSimpleHtml(String raw
) {
217 // FIXME the saved data should be corrected instead.
218 if (raw
.indexOf('&') >= 0) {
219 raw
= raw
.replace("&", "&");
221 if (raw
.indexOf('<') >= 0) {
222 raw
= raw
.replace("<", "<");
224 if (raw
.indexOf('>') >= 0) {
225 raw
= raw
.replace(">", ">");
227 if (raw
.indexOf('\"') >= 0) {
228 raw
= raw
.replace("\"", """);
230 if (raw
.indexOf('\'') >= 0) {
231 raw
= raw
.replace("\'", "'");
233 // raw = "<span style='text-align:justify'>" + raw + "</span>";
234 if (raw
.length() == 0)
236 try (StringReader reader
= new StringReader(raw
)) {
237 List
<String
> lines
= IOUtils
.readLines(reader
);
238 if (lines
.size() == 1)
240 StringBuilder sb
= new StringBuilder(raw
.length() + lines
.size() * BR_LENGTH
);
241 for (int i
= 0; i
< lines
.size(); i
++) {
244 sb
.append(lines
.get(i
));
246 return sb
.toString();
250 final static int BR_LENGTH
= "<br/>".length();
252 public String
readSimpleHtml(Content item
) {
253 StringBuilder sb
= new StringBuilder();
254 // sb.append("<div style='text-align: justify;'>");
255 readAsSimpleHtml(item
, sb
);
256 // sb.append("</div>");
257 // System.out.println(sb);
258 return sb
.toString();
263 * To be overridden, in order to make sure that only valid strings are being
266 protected void validateBeforeStoring(String raw
) {
269 /** To be overridden, in order to support additional formatting. */
270 protected String
convertToStorage(Content item
, String content
) {
275 /** To be overridden, in order to support additional formatting. */
276 protected String
convertFromStorage(Content item
, String content
) {