]> git.argeo.org Git - gpl/argeo-suite.git/blob - swt/org.argeo.app.swt/src/org/argeo/app/swt/docbook/DbkTextInterpreter.java
Move vcard to another package
[gpl/argeo-suite.git] / swt / org.argeo.app.swt / src / org / argeo / app / swt / docbook / DbkTextInterpreter.java
1 package org.argeo.app.swt.docbook;
2
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;
6
7 import java.io.IOException;
8 import java.io.StringReader;
9 import java.io.StringWriter;
10 import java.util.List;
11
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;
18
19 import org.apache.commons.io.IOUtils;
20 import org.argeo.api.acr.Content;
21 import org.argeo.app.docbook.DbkType;
22 import org.w3c.dom.Element;
23 import org.w3c.dom.Node;
24 import org.w3c.dom.NodeList;
25 import org.w3c.dom.Text;
26
27 /** Based on HTML with a few Wiki-like shortcuts. */
28 public class DbkTextInterpreter implements TextInterpreter {
29
30 private TransformerFactory transformerFactory = TransformerFactory.newDefaultInstance();
31
32 private String linkCssClass = DbkType.link.name();
33
34 @Override
35 public void write(Content node, String content) {
36 if (isDbk(node, para) || isDbk(node, title)) {
37 String raw = convertToStorage(node, content);
38 validateBeforeStoring(raw);
39
40 String jcrUuid = null;// node.getIdentifier();
41 // if (node.hasProperty(Property.JCR_UUID))
42 // jcrUuid = node.getProperty(Property.JCR_UUID).getString();
43 // else {
44 // // TODO use time based
45 // jcrUuid = UUID.randomUUID().toString();
46 // node.setProperty(Property.JCR_UUID, jcrUuid);
47 // node.getSession().save();
48 // }
49
50 StringBuilder namespaces = new StringBuilder();
51 namespaces.append(" xmlns:dbk=\"http://docbook.org/ns/docbook\"");
52 namespaces.append(" xmlns:jcr=\"http://www.jcp.org/jcr/1.0\"");
53 namespaces.append(" xmlns:xlink=\"http://www.w3.org/1999/xlink\"");
54 raw = "<" + node.getName() + " jcr:uuid=\"" + jcrUuid + "\"" + namespaces + ">" + raw + "</"
55 + node.getName() + ">";
56 // System.out.println(raw);
57 // try (InputStream in = new ByteArrayInputStream(raw.getBytes(StandardCharsets.UTF_8))) {
58 // node.getSession().importXML(node.getParent().getPath(), in,
59 // ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
60 // // node.getSession().save();
61 // } catch (IOException e) {
62 // throw new IllegalArgumentException("Cannot parse raw content of " + node, e);
63 // }
64
65 // try {
66 // DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
67 // Document document;
68 // try (Reader in = new StringReader(raw)) {
69 // document = documentBuilder.parse(new InputSource(in));
70 // }
71 // NodeList nl = document.getChildNodes();
72 // for (int i = 0; i < nl.getLength(); i++) {
73 // org.w3c.dom.Node n = nl.item(i);
74 // if (node instanceof Text) {
75 //
76 // }
77 // }
78 // } catch (ParserConfigurationException | SAXException | IOException e) {
79 // throw new IllegalArgumentException("Cannot parse raw content of " + node, e);
80 // }
81
82 // Node jcrText;
83 // if (!node.hasNode(Jcr.JCR_XMLTEXT))
84 // jcrText = node.addNode(Jcr.JCR_XMLTEXT, JcrxType.JCRX_XMLTEXT);
85 // else
86 // jcrText = node.getNode(Jcr.JCR_XMLTEXT);
87 // jcrText.setProperty(Jcr.JCR_XMLCHARACTERS, raw);
88 } else {
89 throw new IllegalArgumentException("Don't know how to interpret " + node);
90 }
91 }
92
93 @Override
94 public String read(Content item) {
95 String raw = raw(item);
96 return convertFromStorage(item, raw);
97 }
98
99 @Override
100 public String raw(Content node) {
101 if (isDbk(node, para) || isDbk(node, title)) {
102 try (StringWriter stringWriter = new StringWriter()) {
103 Source source = node.adapt(Source.class);
104 Result result = new StreamResult(stringWriter);
105 transformerFactory.newTransformer().transform(source, result);
106 return stringWriter.toString();
107 } catch (TransformerException | IOException e) {
108 throw new RuntimeException("Could not convert " + node + " to XML", e);
109 }
110
111 // StringBuilder sb = new StringBuilder();
112 // readXml(node, sb);
113 // NodeIterator nit = node.getNodes();
114 // while (nit.hasNext()) {
115 // Node child = nit.nextNode();
116 // if (child.getName().equals(Jcr.JCR_XMLTEXT)) {
117 // Node jcrText = node.getNode(Jcr.JCR_XMLTEXT);
118 // String txt = jcrText.getProperty(Jcr.JCR_XMLCHARACTERS).getString();
119 // // TODO make it more robust
120 // // txt = txt.replace("\n", "").replace("\t", "");
121 // txt = txt.replace("\t", " ");
122 // sb.append(txt);
123 // } else {
124 // try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
125 // child.getSession().exportDocumentView(child.getPath(), out, true, false);
126 // sb.append(new String(out.toByteArray(), StandardCharsets.UTF_8));
127 // } catch (IOException e) {
128 // throw new IllegalStateException("Cannot export " + child, e);
129 // }
130 // }
131 // }
132 // return sb.toString();
133 } else {
134 throw new IllegalArgumentException("Don't know how to interpret " + node);
135 }
136 }
137
138 // private void readXml(Content node, StringBuilder sb){
139 //
140 // NodeIterator nit = node.getNodes();
141 // while (nit.hasNext()) {
142 // Node child = nit.nextNode();
143 // if (child.getName().equals(Jcr.JCR_XMLTEXT)) {
144 // String txt = child.getProperty(Jcr.JCR_XMLCHARACTERS).getString();
145 // // TODO make it more robust
146 // // txt = txt.replace("\n", "").replace("\t", "");
147 // txt = txt.replace("\t", " ");
148 // sb.append(txt);
149 // } else {
150 // sb.append('<').append(child.getName());
151 // PropertyIterator pit = child.getProperties();
152 // properties: while (pit.hasNext()) {
153 // Property p = pit.nextProperty();
154 // if (p.getName().startsWith("jcr:"))
155 // continue properties;
156 // sb.append(' ').append(p.getName()).append("=\"").append(p.getString()).append('\"');
157 // }
158 // sb.append('>');
159 // readXml(child, sb);
160 //// try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
161 //// child.getSession().exportDocumentView(child.getPath(), out, true, false);
162 //// sb.append(new String(out.toByteArray(), StandardCharsets.UTF_8));
163 //// } catch (IOException e) {
164 //// throw new IllegalStateException("Cannot export " + child, e);
165 //// }
166 // sb.append("</").append(child.getName()).append('>');
167 // }
168 // }
169 // }
170
171 private void readAsSimpleHtml(Content node, StringBuilder sb) {
172 DOMResult result = new DOMResult();
173 try {
174 Source source = node.adapt(Source.class);
175 transformerFactory.newTransformer().transform(source, result);
176 } catch (TransformerException e) {
177 throw new RuntimeException("Could not convert " + node + " to XML", e);
178 }
179
180 NodeList nl = result.getNode().getChildNodes();
181 for (int i = 0; i < nl.getLength(); i++) {
182 Node n = nl.item(i);
183 // if (n instanceof Text) {
184 // Text text = (Text) n;
185 // sb.append(text.getTextContent());
186 // } else
187 if (n instanceof Element) {
188 Element elem = (Element) n;
189 sb.append(elem.getTextContent());
190 }
191 }
192
193 // NodeIterator nit = node.getNodes();
194 // while (nit.hasNext()) {
195 // Node child = nit.nextNode();
196 // if (child.getName().equals(Jcr.JCR_XMLTEXT)) {
197 // String txt = child.getProperty(Jcr.JCR_XMLCHARACTERS).getString();
198 // // TODO make it more robust
199 // // txt = txt.replace("\n", "").replace("\t", "");
200 // txt = txt.replace("\t", " ");
201 // String html = textToSimpleHtml(txt);
202 // sb.append(html);
203 // } else if (child.getName().equals(DbkType.link.get())) {
204 // if (child.hasProperty(DbkAttr.XLINK_HREF)) {
205 // String href = child.getProperty(DbkAttr.XLINK_HREF).getString();
206 // // TODO deal with other forbidden XML characters?
207 // href = href.replace("&", "&amp;");
208 // sb.append("<a class='" + linkCssClass + "' href='").append(href).append("'>");
209 // readAsSimpleHtml(child, sb);
210 // sb.append("</a>");
211 // }
212 // } else {
213 // // ignore
214 // }
215 // }
216 }
217
218 private String textToSimpleHtml(String raw) {
219 // FIXME the saved data should be corrected instead.
220 if (raw.indexOf('&') >= 0) {
221 raw = raw.replace("&", "&amp;");
222 }
223 if (raw.indexOf('<') >= 0) {
224 raw = raw.replace("<", "&lt;");
225 }
226 if (raw.indexOf('>') >= 0) {
227 raw = raw.replace(">", "&gt;");
228 }
229 if (raw.indexOf('\"') >= 0) {
230 raw = raw.replace("\"", "&quot;");
231 }
232 if (raw.indexOf('\'') >= 0) {
233 raw = raw.replace("\'", "&apos;");
234 }
235 // raw = "<span style='text-align:justify'>" + raw + "</span>";
236 if (raw.length() == 0)
237 return raw;
238 try (StringReader reader = new StringReader(raw)) {
239 List<String> lines = IOUtils.readLines(reader);
240 if (lines.size() == 1)
241 return lines.get(0);
242 StringBuilder sb = new StringBuilder(raw.length() + lines.size() * BR_LENGTH);
243 for (int i = 0; i < lines.size(); i++) {
244 if (i != 0)
245 sb.append("<br/>");
246 sb.append(lines.get(i));
247 }
248 return sb.toString();
249 } catch (IOException e) {
250 throw new RuntimeException(e);
251 }
252 }
253
254 final static int BR_LENGTH = "<br/>".length();
255
256 public String readSimpleHtml(Content item) {
257 StringBuilder sb = new StringBuilder();
258 // sb.append("<div style='text-align: justify;'>");
259 readAsSimpleHtml(item, sb);
260 // sb.append("</div>");
261 // System.out.println(sb);
262 return sb.toString();
263 }
264
265 // EXTENSIBILITY
266 /**
267 * To be overridden, in order to make sure that only valid strings are being
268 * stored.
269 */
270 protected void validateBeforeStoring(String raw) {
271 }
272
273 /** To be overridden, in order to support additional formatting. */
274 protected String convertToStorage(Content item, String content) {
275 return content;
276
277 }
278
279 /** To be overridden, in order to support additional formatting. */
280 protected String convertFromStorage(Content item, String content) {
281 return content;
282 }
283 }