001
014
015 package com.liferay.portlet.dynamicdatamapping.util;
016
017 import com.liferay.portal.kernel.freemarker.FreeMarkerContext;
018 import com.liferay.portal.kernel.freemarker.FreeMarkerEngineUtil;
019 import com.liferay.portal.kernel.freemarker.FreeMarkerVariablesUtil;
020 import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
021 import com.liferay.portal.kernel.json.JSONArray;
022 import com.liferay.portal.kernel.json.JSONException;
023 import com.liferay.portal.kernel.json.JSONFactoryUtil;
024 import com.liferay.portal.kernel.json.JSONObject;
025 import com.liferay.portal.kernel.util.ArrayUtil;
026 import com.liferay.portal.kernel.util.CharPool;
027 import com.liferay.portal.kernel.util.LocaleUtil;
028 import com.liferay.portal.kernel.util.LocalizationUtil;
029 import com.liferay.portal.kernel.util.StringBundler;
030 import com.liferay.portal.kernel.util.StringPool;
031 import com.liferay.portal.kernel.util.StringUtil;
032 import com.liferay.portal.kernel.xml.Attribute;
033 import com.liferay.portal.kernel.xml.Document;
034 import com.liferay.portal.kernel.xml.DocumentException;
035 import com.liferay.portal.kernel.xml.Element;
036 import com.liferay.portal.kernel.xml.SAXReaderUtil;
037 import com.liferay.portal.util.PortalUtil;
038 import com.liferay.portlet.dynamicdatamapping.storage.Fields;
039
040 import freemarker.ext.jsp.TaglibFactory;
041 import freemarker.ext.servlet.HttpRequestHashModel;
042 import freemarker.ext.servlet.ServletContextHashModel;
043
044 import freemarker.template.ObjectWrapper;
045
046 import java.io.IOException;
047 import java.io.Writer;
048
049 import java.util.HashMap;
050 import java.util.List;
051 import java.util.Locale;
052 import java.util.Map;
053
054 import javax.servlet.GenericServlet;
055 import javax.servlet.Servlet;
056 import javax.servlet.ServletException;
057 import javax.servlet.ServletRequest;
058 import javax.servlet.ServletResponse;
059 import javax.servlet.http.HttpServletRequest;
060 import javax.servlet.http.HttpServletResponse;
061 import javax.servlet.jsp.PageContext;
062
063
068 public class DDMXSDImpl implements DDMXSD {
069
070 public String getHTML(
071 PageContext pageContext, Document document, Locale locale)
072 throws Exception {
073
074 return getHTML(pageContext, document.getRootElement(), locale);
075 }
076
077 public String getHTML(
078 PageContext pageContext, Document document, Fields fields,
079 Locale locale)
080 throws Exception {
081
082 return getHTML(pageContext, document.getRootElement(), fields, locale);
083 }
084
085 public String getHTML(
086 PageContext pageContext, Document document, Fields fields,
087 String namespace, boolean readOnly, Locale locale)
088 throws Exception {
089
090 return getHTML(
091 pageContext, document.getRootElement(), fields, namespace,
092 readOnly, locale);
093 }
094
095 public String getHTML(
096 PageContext pageContext, Element element, Locale locale)
097 throws Exception {
098
099 return getHTML(pageContext, element, null, locale);
100 }
101
102 public String getHTML(
103 PageContext pageContext, Element element, Fields fields,
104 Locale locale)
105 throws Exception {
106
107 return getHTML(
108 pageContext, element, fields, StringPool.BLANK, false, locale);
109 }
110
111 public String getHTML(
112 PageContext pageContext, Element element, Fields fields,
113 String namespace, boolean readOnly, Locale locale)
114 throws Exception {
115
116 StringBundler sb = new StringBundler();
117
118 HttpServletRequest request =
119 (HttpServletRequest)pageContext.getRequest();
120
121 String portletId = PortalUtil.getPortletId(request);
122
123 String portletNamespace = PortalUtil.getPortletNamespace(portletId);
124
125 List<Element> dynamicElementElements = element.elements(
126 "dynamic-element");
127
128 for (Element dynamicElementElement : dynamicElementElements) {
129 FreeMarkerContext freeMarkerContext = getFreeMarkerContext(
130 dynamicElementElement, locale);
131
132 freeMarkerContext.put("portletNamespace", portletNamespace);
133 freeMarkerContext.put("namespace", namespace);
134
135 if (fields != null) {
136 freeMarkerContext.put("fields", fields);
137 }
138
139 Map<String, Object> field =
140 (Map<String, Object>)freeMarkerContext.get("fieldStructure");
141
142 String childrenHTML = getHTML(
143 pageContext, dynamicElementElement, fields, namespace,
144 readOnly, locale);
145
146 field.put("children", childrenHTML);
147
148 String fieldNamespace = dynamicElementElement.attributeValue(
149 "fieldNamespace", _DEFAULT_NAMESPACE);
150
151 if (readOnly) {
152 fieldNamespace = _DEFAULT_READ_ONLY_NAMESPACE;
153 }
154
155 String type = dynamicElementElement.attributeValue("type");
156
157 String templateName = StringUtil.replaceFirst(
158 type, fieldNamespace.concat(StringPool.DASH), StringPool.BLANK);
159
160 StringBundler resourcePath = new StringBundler(5);
161
162 resourcePath.append(_TPL_PATH);
163 resourcePath.append(fieldNamespace.toLowerCase());
164 resourcePath.append(CharPool.SLASH);
165 resourcePath.append(templateName);
166 resourcePath.append(_TPL_EXT);
167
168 sb.append(
169 processFTL(
170 pageContext, freeMarkerContext, resourcePath.toString(),
171 readOnly));
172 }
173
174 return sb.toString();
175 }
176
177 public String getHTML(PageContext pageContext, String xml, Locale locale)
178 throws Exception {
179
180 return getHTML(pageContext, xml, null, locale);
181 }
182
183 public String getHTML(
184 PageContext pageContext, String xml, Fields fields, Locale locale)
185 throws Exception {
186
187 return getHTML(pageContext, SAXReaderUtil.read(xml), fields, locale);
188 }
189
190 public String getHTML(
191 PageContext pageContext, String xml, Fields fields,
192 String namespace, Locale locale)
193 throws Exception {
194
195 return getHTML(
196 pageContext, SAXReaderUtil.read(xml), fields, namespace, false,
197 locale);
198 }
199
200 public String getHTML(
201 PageContext pageContext, String xml, Fields fields,
202 String namespace, boolean readOnly, Locale locale)
203 throws Exception {
204
205 return getHTML(
206 pageContext, SAXReaderUtil.read(xml), fields, namespace, readOnly,
207 locale);
208 }
209
210 public JSONArray getJSONArray(Document document) throws JSONException {
211 return getJSONArray(document.getRootElement());
212 }
213
214 public JSONArray getJSONArray(Element element) throws JSONException {
215 JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
216
217 Document document = element.getDocument();
218
219 String defaultLocale = LocalizationUtil.getDefaultLocale(
220 document.asXML());
221
222 List<Element> dynamicElementElements = element.elements(
223 "dynamic-element");
224
225 for (Element dynamicElementElement : dynamicElementElements) {
226 JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
227 JSONObject localizationMapJSONObject =
228 JSONFactoryUtil.createJSONObject();
229
230 List<Element> metadataElements = dynamicElementElement.elements(
231 "meta-data");
232
233 for (Element metadataElement : metadataElements) {
234 if (metadataElement == null) {
235 continue;
236 }
237
238 String locale = metadataElement.attributeValue("locale");
239
240 JSONObject localeMap = JSONFactoryUtil.createJSONObject();
241
242 localizationMapJSONObject.put(locale, localeMap);
243
244 for (Element metadataEntryElement :
245 metadataElement.elements()) {
246
247 String attributeName = metadataEntryElement.attributeValue(
248 "name");
249 String attributeValue = metadataEntryElement.getText();
250
251 localeMap.put(attributeName, attributeValue);
252
253 if (defaultLocale.equals(locale)) {
254 jsonObject.put(attributeName, attributeValue);
255 }
256 }
257 }
258
259 jsonObject.put("localizationMap", localizationMapJSONObject);
260
261 for (Attribute attribute : dynamicElementElement.attributes()) {
262 jsonObject.put(attribute.getName(), attribute.getValue());
263 }
264
265 jsonObject.put(
266 "id", dynamicElementElement.attributeValue("name"));
267
268 String type = jsonObject.getString("type");
269
270 String key = "fields";
271
272 if (type.equals(_TYPE_RADIO) || type.equals(_TYPE_SELECT)) {
273 key = "options";
274 }
275
276 jsonObject.put(key, getJSONArray(dynamicElementElement));
277
278 jsonArray.put(jsonObject);
279 }
280
281 return jsonArray;
282 }
283
284 public JSONArray getJSONArray(String xml)
285 throws DocumentException, JSONException {
286
287 return getJSONArray(SAXReaderUtil.read(xml));
288 }
289
290 protected Map<String, Object> getFieldContext(
291 Element dynamicElementElement, Locale locale) {
292
293 Document document = dynamicElementElement.getDocument();
294
295 String[] availableLocales = LocalizationUtil.getAvailableLocales(
296 document.asXML());
297
298 String defaultLanguageId = LocalizationUtil.getDefaultLocale(
299 document.asXML());
300
301 String languageId = LocaleUtil.toLanguageId(locale);
302
303 if (!ArrayUtil.contains(availableLocales, languageId)) {
304 languageId = defaultLanguageId;
305 }
306
307 Element metadataElement =
308 (Element)dynamicElementElement.selectSingleNode(
309 "meta-data[@locale='" + languageId + "']");
310
311 Map<String, Object> field = new HashMap<String, Object>();
312
313 if (metadataElement != null) {
314 for (Element metadataEntry : metadataElement.elements()) {
315 field.put(
316 metadataEntry.attributeValue("name"),
317 metadataEntry.getText());
318 }
319 }
320
321 for (Attribute attribute : dynamicElementElement.attributes()) {
322 field.put(attribute.getName(), attribute.getValue());
323 }
324
325 return field;
326 }
327
328 protected FreeMarkerContext getFreeMarkerContext(
329 Element dynamicElementElement, Locale locale) {
330
331 FreeMarkerContext freeMarkerContext =
332 FreeMarkerEngineUtil.getWrappedStandardToolsContext();
333
334 Map<String, Object> fieldContext = getFieldContext(
335 dynamicElementElement, locale);
336
337 Map<String, Object> parentFieldContext = new HashMap<String, Object>();
338
339 Element parentElement = dynamicElementElement.getParent();
340
341 if (parentElement != null) {
342 parentFieldContext = getFieldContext(parentElement, locale);
343 }
344
345 freeMarkerContext.put("fieldStructure", fieldContext);
346 freeMarkerContext.put("parentFieldStructure", parentFieldContext);
347
348 return freeMarkerContext;
349 }
350
351
354 protected String processFTL(
355 PageContext pageContext, FreeMarkerContext freeMarkerContext,
356 String resourcePath, boolean readOnly)
357 throws Exception {
358
359 if (!FreeMarkerEngineUtil.resourceExists(resourcePath)) {
360 if (readOnly) {
361 resourcePath = _TPL_DEFAULT_READ_ONLY_PATH;
362 }
363 else {
364 resourcePath = _TPL_DEFAULT_PATH;
365 }
366 }
367
368 HttpServletRequest request =
369 (HttpServletRequest)pageContext.getRequest();
370
371
372
373 FreeMarkerVariablesUtil.insertVariables(
374 freeMarkerContext, request);
375
376
377
378 HttpServletResponse response =
379 (HttpServletResponse)pageContext.getResponse();
380
381 Writer writer = new UnsyncStringWriter();
382
383
384
385 TaglibFactory portalTaglib = new TaglibFactory(
386 pageContext.getServletContext());
387
388 freeMarkerContext.put("PortalJspTagLibs", portalTaglib);
389
390
391
392 final Servlet servlet = (Servlet)pageContext.getPage();
393
394 GenericServlet genericServlet = null;
395
396 if (servlet instanceof GenericServlet) {
397 genericServlet = (GenericServlet)servlet;
398 }
399 else {
400 genericServlet = new GenericServlet() {
401
402 @Override
403 public void service(
404 ServletRequest servletRequest,
405 ServletResponse servletResponse)
406 throws ServletException, IOException {
407
408 servlet.service(servletRequest, servletResponse);
409 }
410
411 };
412
413 genericServlet.init(pageContext.getServletConfig());
414 }
415
416 ServletContextHashModel servletContextHashModel =
417 new ServletContextHashModel(
418 genericServlet, ObjectWrapper.DEFAULT_WRAPPER);
419
420 freeMarkerContext.put("Application", servletContextHashModel);
421
422 HttpRequestHashModel httpRequestHashModel = new HttpRequestHashModel(
423 request, response, ObjectWrapper.DEFAULT_WRAPPER);
424
425 freeMarkerContext.put("Request", httpRequestHashModel);
426
427
428
429 FreeMarkerEngineUtil.mergeTemplate(
430 resourcePath, freeMarkerContext, writer);
431
432 return writer.toString();
433 }
434
435 private static final String _DEFAULT_NAMESPACE = "alloy";
436
437 private static final String _DEFAULT_READ_ONLY_NAMESPACE = "readonly";
438
439 private static final String _TPL_DEFAULT_PATH =
440 "com/liferay/portlet/dynamicdatamapping/dependencies/alloy/text.ftl";
441
442 private static final String _TPL_DEFAULT_READ_ONLY_PATH =
443 "com/liferay/portlet/dynamicdatamapping/dependencies/readonly/" +
444 "default.ftl";
445
446 private static final String _TPL_EXT = ".ftl";
447
448 private static final String _TPL_PATH =
449 "com/liferay/portlet/dynamicdatamapping/dependencies/";
450
451 private static final String _TYPE_RADIO = "radio";
452
453 private static final String _TYPE_SELECT = "select";
454
455 }