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 import com.liferay.util.freemarker.FreeMarkerTaglibFactoryUtil;
040
041 import freemarker.ext.servlet.HttpRequestHashModel;
042 import freemarker.ext.servlet.ServletContextHashModel;
043
044 import freemarker.template.ObjectWrapper;
045 import freemarker.template.TemplateHashModel;
046
047 import java.io.IOException;
048 import java.io.Writer;
049
050 import java.util.HashMap;
051 import java.util.List;
052 import java.util.Locale;
053 import java.util.Map;
054
055 import javax.servlet.GenericServlet;
056 import javax.servlet.Servlet;
057 import javax.servlet.ServletException;
058 import javax.servlet.ServletRequest;
059 import javax.servlet.ServletResponse;
060 import javax.servlet.http.HttpServletRequest;
061 import javax.servlet.http.HttpServletResponse;
062 import javax.servlet.jsp.PageContext;
063
064
069 public class DDMXSDImpl implements DDMXSD {
070
071 public String getHTML(
072 PageContext pageContext, Document document, Locale locale)
073 throws Exception {
074
075 return getHTML(pageContext, document.getRootElement(), locale);
076 }
077
078 public String getHTML(
079 PageContext pageContext, Document document, Fields fields,
080 Locale locale)
081 throws Exception {
082
083 return getHTML(pageContext, document.getRootElement(), fields, locale);
084 }
085
086 public String getHTML(
087 PageContext pageContext, Document document, Fields fields,
088 String namespace, boolean readOnly, Locale locale)
089 throws Exception {
090
091 return getHTML(
092 pageContext, document.getRootElement(), fields, namespace,
093 readOnly, locale);
094 }
095
096 public String getHTML(
097 PageContext pageContext, Element element, Locale locale)
098 throws Exception {
099
100 return getHTML(pageContext, element, null, locale);
101 }
102
103 public String getHTML(
104 PageContext pageContext, Element element, Fields fields,
105 Locale locale)
106 throws Exception {
107
108 return getHTML(
109 pageContext, element, fields, StringPool.BLANK, false, locale);
110 }
111
112 public String getHTML(
113 PageContext pageContext, Element element, Fields fields,
114 String namespace, boolean readOnly, Locale locale)
115 throws Exception {
116
117 StringBundler sb = new StringBundler();
118
119 HttpServletRequest request =
120 (HttpServletRequest)pageContext.getRequest();
121
122 String portletId = PortalUtil.getPortletId(request);
123
124 String portletNamespace = PortalUtil.getPortletNamespace(portletId);
125
126 List<Element> dynamicElementElements = element.elements(
127 "dynamic-element");
128
129 for (Element dynamicElementElement : dynamicElementElements) {
130 FreeMarkerContext freeMarkerContext = getFreeMarkerContext(
131 dynamicElementElement, locale);
132
133 freeMarkerContext.put("portletNamespace", portletNamespace);
134 freeMarkerContext.put("namespace", namespace);
135
136 if (fields != null) {
137 freeMarkerContext.put("fields", fields);
138 }
139
140 Map<String, Object> field =
141 (Map<String, Object>)freeMarkerContext.get("fieldStructure");
142
143 String childrenHTML = getHTML(
144 pageContext, dynamicElementElement, fields, namespace,
145 readOnly, locale);
146
147 field.put("children", childrenHTML);
148
149 String fieldNamespace = dynamicElementElement.attributeValue(
150 "fieldNamespace", _DEFAULT_NAMESPACE);
151
152 if (readOnly) {
153 fieldNamespace = _DEFAULT_READ_ONLY_NAMESPACE;
154 }
155
156 String type = dynamicElementElement.attributeValue("type");
157
158 String templateName = StringUtil.replaceFirst(
159 type, fieldNamespace.concat(StringPool.DASH), StringPool.BLANK);
160
161 StringBundler resourcePath = new StringBundler(5);
162
163 resourcePath.append(_TPL_PATH);
164 resourcePath.append(fieldNamespace.toLowerCase());
165 resourcePath.append(CharPool.SLASH);
166 resourcePath.append(templateName);
167 resourcePath.append(_TPL_EXT);
168
169 sb.append(
170 processFTL(
171 pageContext, freeMarkerContext, resourcePath.toString(),
172 readOnly));
173 }
174
175 return sb.toString();
176 }
177
178 public String getHTML(PageContext pageContext, String xml, Locale locale)
179 throws Exception {
180
181 return getHTML(pageContext, xml, null, locale);
182 }
183
184 public String getHTML(
185 PageContext pageContext, String xml, Fields fields, Locale locale)
186 throws Exception {
187
188 return getHTML(pageContext, SAXReaderUtil.read(xml), fields, locale);
189 }
190
191 public String getHTML(
192 PageContext pageContext, String xml, Fields fields,
193 String namespace, Locale locale)
194 throws Exception {
195
196 return getHTML(
197 pageContext, SAXReaderUtil.read(xml), fields, namespace, false,
198 locale);
199 }
200
201 public String getHTML(
202 PageContext pageContext, String xml, Fields fields,
203 String namespace, boolean readOnly, Locale locale)
204 throws Exception {
205
206 return getHTML(
207 pageContext, SAXReaderUtil.read(xml), fields, namespace, readOnly,
208 locale);
209 }
210
211 public JSONArray getJSONArray(Document document) throws JSONException {
212 return getJSONArray(document.getRootElement());
213 }
214
215 public JSONArray getJSONArray(Element element) throws JSONException {
216 JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
217
218 Document document = element.getDocument();
219
220 String defaultLocale = LocalizationUtil.getDefaultLocale(
221 document.asXML());
222
223 List<Element> dynamicElementElements = element.elements(
224 "dynamic-element");
225
226 for (Element dynamicElementElement : dynamicElementElements) {
227 JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
228 JSONObject localizationMapJSONObject =
229 JSONFactoryUtil.createJSONObject();
230
231 List<Element> metadataElements = dynamicElementElement.elements(
232 "meta-data");
233
234 for (Element metadataElement : metadataElements) {
235 if (metadataElement == null) {
236 continue;
237 }
238
239 String locale = metadataElement.attributeValue("locale");
240
241 JSONObject localeMap = JSONFactoryUtil.createJSONObject();
242
243 localizationMapJSONObject.put(locale, localeMap);
244
245 for (Element metadataEntryElement :
246 metadataElement.elements()) {
247
248 String attributeName = metadataEntryElement.attributeValue(
249 "name");
250 String attributeValue = metadataEntryElement.getText();
251
252 localeMap.put(attributeName, attributeValue);
253
254 if (defaultLocale.equals(locale)) {
255 jsonObject.put(attributeName, attributeValue);
256 }
257 }
258 }
259
260 jsonObject.put("localizationMap", localizationMapJSONObject);
261
262 for (Attribute attribute : dynamicElementElement.attributes()) {
263 jsonObject.put(attribute.getName(), attribute.getValue());
264 }
265
266 jsonObject.put("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(freeMarkerContext, request);
374
375
376
377 HttpServletResponse response =
378 (HttpServletResponse)pageContext.getResponse();
379
380 Writer writer = new UnsyncStringWriter();
381
382
383
384 TemplateHashModel portalTaglib =
385 FreeMarkerTaglibFactoryUtil.createTaglibFactory(
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 }