1
22
23 package com.liferay.portlet.journal.util;
24
25 import com.liferay.portal.kernel.util.GetterUtil;
26 import com.liferay.portal.kernel.util.StringPool;
27 import com.liferay.portal.kernel.util.StringUtil;
28 import com.liferay.portal.velocity.VelocityResourceListener;
29 import com.liferay.portal.velocity.VelocityVariables;
30 import com.liferay.portlet.journal.TransformException;
31 import com.liferay.util.Html;
32 import com.liferay.util.PwdGenerator;
33 import com.liferay.util.xml.CDATAUtil;
34
35 import java.io.IOException;
36 import java.io.StringReader;
37 import java.io.StringWriter;
38
39 import java.util.ArrayList;
40 import java.util.HashMap;
41 import java.util.Iterator;
42 import java.util.List;
43 import java.util.Map;
44
45 import org.apache.velocity.VelocityContext;
46 import org.apache.velocity.app.Velocity;
47 import org.apache.velocity.exception.VelocityException;
48
49 import org.dom4j.Document;
50 import org.dom4j.DocumentException;
51 import org.dom4j.Element;
52 import org.dom4j.io.SAXReader;
53
54
62 public class JournalVmUtil {
63
64 public static String transform(
65 Map tokens, String languageId, String xml, String script)
66 throws TransformException {
67
68 StringWriter output = new StringWriter();
69
70 boolean load = false;
71
72 try {
73 VelocityContext context = new VelocityContext();
74
75 SAXReader reader = new SAXReader();
76
77 Document doc = reader.read(new StringReader(xml));
78
79 Element root = doc.getRootElement();
80
81 List nodes = _extractDynamicContents(root);
82
83 Iterator itr = nodes.iterator();
84
85 while (itr.hasNext()) {
86 TemplateNode node = (TemplateNode)itr.next();
87
88 context.put(node.getName(), node);
89 }
90
91 context.put(
92 "request", _insertRequestVariables(root.element("request")));
93
94 long companyId = GetterUtil.getLong(
95 (String)tokens.get("company_id"));
96 long groupId = GetterUtil.getLong((String)tokens.get("group_id"));
97 String journalTemplatesPath =
98 VelocityResourceListener.JOURNAL_SEPARATOR + StringPool.SLASH +
99 companyId + StringPool.SLASH + groupId;
100 String randomNamespace =
101 PwdGenerator.getPassword(PwdGenerator.KEY3, 4) +
102 StringPool.UNDERLINE;
103
104 context.put("companyId", String.valueOf(companyId));
105 context.put("groupId", String.valueOf(groupId));
106 context.put("journalTemplatesPath", journalTemplatesPath);
107 context.put("randomNamespace", randomNamespace);
108
109 VelocityVariables.insertHelperUtilities(context);
110
111 script = _injectEditInPlace(xml, script);
112
113 load = Velocity.evaluate(
114 context, output, JournalVmUtil.class.getName(), script);
115 }
116 catch (Exception e) {
117 if (e instanceof DocumentException) {
118 throw new TransformException("Unable to read XML document", e);
119 }
120 else if (e instanceof VelocityException) {
121 VelocityException pex = (VelocityException)e;
122
123 throw new TransformException(
124 "Unable to parse velocity template: " +
125 Html.escape(pex.getMessage()),
126 e);
127 }
128 else if (e instanceof IOException) {
129 throw new TransformException(
130 "Error reading velocity template", e);
131 }
132 else if (e instanceof TransformException) {
133 throw (TransformException)e;
134 }
135 else {
136 throw new TransformException("Unhandled exception", e);
137 }
138 }
139
140 if (!load) {
141 throw new TransformException(
142 "Unable to dynamically load velocity transform script");
143 }
144
145 return output.toString();
146 }
147
148 private static List _extractDynamicContents(Element parent)
149 throws TransformException {
150
151 List nodes = new ArrayList();
152
153 Iterator itr1 = parent.elementIterator("dynamic-element");
154
155 while (itr1.hasNext()) {
156 Element element = (Element)itr1.next();
157
158 Element content = element.element("dynamic-content");
159
160 if (content == null) {
161 throw new TransformException(
162 "Element missing \"dynamic-content\"");
163 }
164
165 String name = element.attributeValue("name", "");
166
167 if (name.length() == 0) {
168 throw new TransformException(
169 "Element missing \"name\" attribute");
170 }
171
172 String type = element.attributeValue("type", "");
173
174 TemplateNode node = new TemplateNode(
175 name, CDATAUtil.strip(content.getText()), type);
176
177 if (element.element("dynamic-element") != null) {
178 node.appendChildren(_extractDynamicContents(element));
179 }
180 else if (content.element("option") != null) {
181 Iterator itr2 = content.elementIterator("option");
182
183 while (itr2.hasNext()) {
184 Element option = (Element)itr2.next();
185
186 node.appendOption(CDATAUtil.strip(option.getText()));
187 }
188 }
189
190 nodes.add(node);
191 }
192
193 return nodes;
194 }
195
196 private static String _injectEditInPlace(String xml, String script)
197 throws DocumentException {
198
199 SAXReader reader = new SAXReader();
200
201 Document doc = reader.read(new StringReader(xml));
202
203 Iterator itr = doc.selectNodes("//dynamic-element").iterator();
204
205 while (itr.hasNext()) {
206 Element el = (Element)itr.next();
207
208 String name = GetterUtil.getString(el.attributeValue("name"));
209 String type = GetterUtil.getString(el.attributeValue("type"));
210
211 if ((!name.startsWith("reserved-")) &&
212 (type.equals("text") || type.equals("text_box") ||
213 type.equals("text_area"))) {
214
215 script = _wrapField(script, name, type, "data");
216 script = _wrapField(script, name, type, "getData()");
217 }
218 }
219
220 return script;
221 }
222
223 private static Map _insertRequestVariables(Element parent) {
224 Map map = new HashMap();
225
226 if (parent == null) {
227 return map;
228 }
229
230 Iterator itr1 = parent.elements().iterator();
231
232 while (itr1.hasNext()) {
233 Element el = (Element)itr1.next();
234
235 String name = el.getName();
236
237 if (name.equals("attribute")) {
238 map.put(el.elementText("name"), el.elementText("value"));
239 }
240 else if (name.equals("parameter")) {
241 name = el.element("name").getText();
242
243 List valueEls = el.elements("value");
244
245 if (valueEls.size() == 1) {
246 map.put(name, ((Element)valueEls.get(0)).getText());
247 }
248 else {
249 List values = new ArrayList();
250
251 Iterator itr2 = valueEls.iterator();
252
253 while (itr2.hasNext()) {
254 Element valueEl = (Element)itr2.next();
255
256 values.add(valueEl.getText());
257 }
258
259 map.put(name, values);
260 }
261 }
262 else if (el.elements().size() > 0) {
263 map.put(name, _insertRequestVariables(el));
264 }
265 else {
266 map.put(name, el.getText());
267 }
268 }
269
270 return map;
271 }
272
273 private static String _wrapField(
274 String script, String name, String type, String call) {
275
276 String field = "$" + name + "." + call;
277 String wrappedField =
278 "<span class=\"journal-content-eip-" + type + "\" " +
279 "id=\"journal-content-field-name-" + name + "\">" + field +
280 "</span>";
281
282 return StringUtil.replace(
283 script, "$editInPlace(" + field + ")", wrappedField);
284 }
285
286 }