001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.dynamicdatamapping.render;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
019    import com.liferay.portal.kernel.language.LanguageUtil;
020    import com.liferay.portal.kernel.servlet.JSPSupportServlet;
021    import com.liferay.portal.kernel.template.Template;
022    import com.liferay.portal.kernel.template.TemplateConstants;
023    import com.liferay.portal.kernel.template.TemplateManagerUtil;
024    import com.liferay.portal.kernel.template.TemplateResource;
025    import com.liferay.portal.kernel.template.URLTemplateResource;
026    import com.liferay.portal.kernel.util.ArrayUtil;
027    import com.liferay.portal.kernel.util.CharPool;
028    import com.liferay.portal.kernel.util.GetterUtil;
029    import com.liferay.portal.kernel.util.ParamUtil;
030    import com.liferay.portal.kernel.util.StringBundler;
031    import com.liferay.portal.kernel.util.StringPool;
032    import com.liferay.portal.kernel.util.StringUtil;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portlet.dynamicdatamapping.model.DDMForm;
035    import com.liferay.portlet.dynamicdatamapping.model.DDMFormField;
036    import com.liferay.portlet.dynamicdatamapping.model.DDMFormFieldOptions;
037    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants;
038    import com.liferay.portlet.dynamicdatamapping.model.LocalizedValue;
039    import com.liferay.portlet.dynamicdatamapping.storage.Field;
040    import com.liferay.portlet.dynamicdatamapping.storage.Fields;
041    import com.liferay.portlet.dynamicdatamapping.util.DDMFieldsCounter;
042    import com.liferay.portlet.dynamicdatamapping.util.DDMImpl;
043    import com.liferay.util.freemarker.FreeMarkerTaglibFactoryUtil;
044    
045    import freemarker.ext.servlet.HttpRequestHashModel;
046    import freemarker.ext.servlet.ServletContextHashModel;
047    
048    import freemarker.template.ObjectWrapper;
049    import freemarker.template.TemplateHashModel;
050    
051    import java.io.Writer;
052    
053    import java.net.URL;
054    
055    import java.util.ArrayList;
056    import java.util.HashMap;
057    import java.util.List;
058    import java.util.Locale;
059    import java.util.Map;
060    import java.util.Set;
061    
062    import javax.servlet.GenericServlet;
063    import javax.servlet.http.HttpServletRequest;
064    import javax.servlet.http.HttpServletResponse;
065    
066    /**
067     * @author Pablo Carvalho
068     */
069    public class DDMFormFieldFreeMarkerRenderer implements DDMFormFieldRenderer {
070    
071            public DDMFormFieldFreeMarkerRenderer() {
072                    String defaultTemplateId = _TPL_PATH + "alloy/text.ftl";
073    
074                    URL defaultTemplateURL = getResource(defaultTemplateId);
075    
076                    _defaultTemplateResource = new URLTemplateResource(
077                            defaultTemplateId, defaultTemplateURL);
078    
079                    String defaultReadOnlyTemplateId = _TPL_PATH + "readonly/default.ftl";
080    
081                    URL defaultReadOnlyTemplateURL = getResource(defaultReadOnlyTemplateId);
082    
083                    _defaultReadOnlyTemplateResource = new URLTemplateResource(
084                            defaultReadOnlyTemplateId, defaultReadOnlyTemplateURL);
085            }
086    
087            @Override
088            public String[] getSupportedDDMFormFieldTypes() {
089                    return _SUPPORTED_DDM_FORM_FIELD_TYPES;
090            }
091    
092            @Override
093            public String render(
094                            DDMFormField ddmFormField,
095                            DDMFormFieldRenderingContext ddmFormFieldRenderingContext)
096                    throws PortalException {
097    
098                    try {
099                            HttpServletRequest request =
100                                    ddmFormFieldRenderingContext.getHttpServletRequest();
101                            HttpServletResponse response =
102                                    ddmFormFieldRenderingContext.getHttpServletResponse();
103                            Fields fields = ddmFormFieldRenderingContext.getFields();
104                            String portletNamespace =
105                                    ddmFormFieldRenderingContext.getPortletNamespace();
106                            String namespace = ddmFormFieldRenderingContext.getNamespace();
107                            String mode = ddmFormFieldRenderingContext.getMode();
108                            boolean readOnly = ddmFormFieldRenderingContext.isReadOnly();
109                            boolean showEmptyFieldLabel =
110                                    ddmFormFieldRenderingContext.isShowEmptyFieldLabel();
111                            Locale locale = ddmFormFieldRenderingContext.getLocale();
112    
113                            return getFieldHTML(
114                                    request, response, ddmFormField, fields, null, portletNamespace,
115                                    namespace, mode, readOnly, showEmptyFieldLabel, locale);
116                    }
117                    catch (Exception e) {
118                            throw new PortalException(e);
119                    }
120            }
121    
122            protected void addLayoutProperties(
123                    DDMFormField ddmFormField, Map<String, Object> fieldContext,
124                    Locale locale) {
125    
126                    LocalizedValue label = ddmFormField.getLabel();
127    
128                    fieldContext.put("label", label.getString(locale));
129    
130                    LocalizedValue predefinedValue = ddmFormField.getPredefinedValue();
131    
132                    fieldContext.put("predefinedValue", predefinedValue.getString(locale));
133    
134                    LocalizedValue style = ddmFormField.getStyle();
135    
136                    fieldContext.put("style", style.getString(locale));
137    
138                    LocalizedValue tip = ddmFormField.getTip();
139    
140                    fieldContext.put("tip", tip.getString(locale));
141            }
142    
143            protected void addStructureProperties(
144                    DDMFormField ddmFormField, Map<String, Object> fieldContext) {
145    
146                    fieldContext.put("dataType", ddmFormField.getDataType());
147                    fieldContext.put("fieldNamespace", ddmFormField.getNamespace());
148                    fieldContext.put("indexType", ddmFormField.getIndexType());
149                    fieldContext.put(
150                            "localizable", Boolean.toString(ddmFormField.isLocalizable()));
151                    fieldContext.put(
152                            "multiple", Boolean.toString(ddmFormField.isMultiple()));
153                    fieldContext.put("name", ddmFormField.getName());
154                    fieldContext.put(
155                            "readOnly", Boolean.toString(ddmFormField.isReadOnly()));
156                    fieldContext.put(
157                            "repeatable", Boolean.toString(ddmFormField.isRepeatable()));
158                    fieldContext.put(
159                            "required", Boolean.toString(ddmFormField.isRequired()));
160                    fieldContext.put(
161                            "showLabel", Boolean.toString(ddmFormField.isShowLabel()));
162                    fieldContext.put("type", ddmFormField.getType());
163            }
164    
165            protected int countFieldRepetition(
166                    String[] fieldsDisplayValues, String parentFieldName, int offset) {
167    
168                    int total = 0;
169    
170                    String fieldName = fieldsDisplayValues[offset];
171    
172                    for (; offset < fieldsDisplayValues.length; offset++) {
173                            String fieldNameValue = fieldsDisplayValues[offset];
174    
175                            if (fieldNameValue.equals(fieldName)) {
176                                    total++;
177                            }
178    
179                            if (fieldNameValue.equals(parentFieldName)) {
180                                    break;
181                            }
182                    }
183    
184                    return total;
185            }
186    
187            protected String getDDMFormFieldOptionHTML(
188                            HttpServletRequest request, HttpServletResponse response,
189                            DDMFormField ddmFormField, String mode, boolean readOnly,
190                            Locale locale, Map<String, Object> freeMarkerContext)
191                    throws Exception {
192    
193                    StringBundler sb = new StringBundler();
194    
195                    DDMFormFieldOptions ddmFormFieldOptions =
196                            ddmFormField.getDDMFormFieldOptions();
197    
198                    for (String value : ddmFormFieldOptions.getOptionsValues()) {
199                            Map<String, Object> fieldStructure = new HashMap<String, Object>();
200    
201                            fieldStructure.put("children", StringPool.BLANK);
202                            fieldStructure.put("fieldNamespace", StringUtil.randomId());
203    
204                            LocalizedValue label = ddmFormFieldOptions.getOptionLabels(value);
205    
206                            fieldStructure.put("label", label.getString(locale));
207    
208                            fieldStructure.put("name", StringUtil.randomId());
209                            fieldStructure.put("value", value);
210    
211                            freeMarkerContext.put("fieldStructure", fieldStructure);
212    
213                            sb.append(
214                                    processFTL(
215                                            request, response, ddmFormField.getNamespace(), "option",
216                                            mode, readOnly, freeMarkerContext));
217                    }
218    
219                    return sb.toString();
220            }
221    
222            protected Map<String, Object> getFieldContext(
223                    HttpServletRequest request, HttpServletResponse response,
224                    String portletNamespace, String namespace, DDMFormField ddmFormField,
225                    Locale locale) {
226    
227                    Map<String, Map<String, Object>> fieldsContext = getFieldsContext(
228                            request, response, portletNamespace, namespace);
229    
230                    String name = ddmFormField.getName();
231    
232                    Map<String, Object> fieldContext = fieldsContext.get(name);
233    
234                    if (fieldContext != null) {
235                            return fieldContext;
236                    }
237    
238                    DDMForm ddmForm = ddmFormField.getDDMForm();
239    
240                    Set<Locale> availableLocales = ddmForm.getAvailableLocales();
241    
242                    Locale defaultLocale = ddmForm.getDefaultLocale();
243    
244                    Locale structureLocale = locale;
245    
246                    if (!availableLocales.contains(locale)) {
247                            structureLocale = defaultLocale;
248                    }
249    
250                    fieldContext = new HashMap<String, Object>();
251    
252                    addLayoutProperties(ddmFormField, fieldContext, structureLocale);
253    
254                    addStructureProperties(ddmFormField, fieldContext);
255    
256                    boolean localizable = ddmFormField.isLocalizable();
257    
258                    if (!localizable && !locale.equals(defaultLocale)) {
259                            fieldContext.put("disabled", Boolean.TRUE.toString());
260                    }
261    
262                    boolean checkRequired = GetterUtil.getBoolean(
263                            request.getAttribute("checkRequired"), true);
264    
265                    if (!checkRequired) {
266                            fieldContext.put("required", Boolean.FALSE.toString());
267                    }
268    
269                    fieldsContext.put(name, fieldContext);
270    
271                    return fieldContext;
272            }
273    
274            protected String getFieldHTML(
275                            HttpServletRequest request, HttpServletResponse response,
276                            DDMFormField ddmFormField, Fields fields,
277                            DDMFormField parentDDMFormField, String portletNamespace,
278                            String namespace, String mode, boolean readOnly,
279                            boolean showEmptyFieldLabel, Locale locale)
280                    throws Exception {
281    
282                    Map<String, Object> freeMarkerContext = getFreeMarkerContext(
283                            request, response, portletNamespace, namespace, ddmFormField,
284                            parentDDMFormField, showEmptyFieldLabel, locale);
285    
286                    if (fields != null) {
287                            freeMarkerContext.put("fields", fields);
288                    }
289    
290                    Map<String, Object> fieldStructure =
291                            (Map<String, Object>)freeMarkerContext.get("fieldStructure");
292    
293                    int fieldRepetition = 1;
294                    int offset = 0;
295    
296                    DDMFieldsCounter ddmFieldsCounter = getFieldsCounter(
297                            request, response, fields, portletNamespace, namespace);
298    
299                    String name = ddmFormField.getName();
300    
301                    String fieldDisplayValue = getFieldsDisplayValue(
302                            request, response, fields);
303    
304                    String[] fieldsDisplayValues = getFieldsDisplayValues(
305                            fieldDisplayValue);
306    
307                    boolean fieldDisplayable = ArrayUtil.contains(
308                            fieldsDisplayValues, name);
309    
310                    if (fieldDisplayable) {
311                            Map<String, Object> parentFieldStructure =
312                                    (Map<String, Object>)freeMarkerContext.get(
313                                            "parentFieldStructure");
314    
315                            String parentFieldName = (String)parentFieldStructure.get("name");
316    
317                            offset = getFieldOffset(
318                                    fieldsDisplayValues, name, ddmFieldsCounter.get(name));
319    
320                            if (offset == fieldsDisplayValues.length) {
321                                    return StringPool.BLANK;
322                            }
323    
324                            fieldRepetition = countFieldRepetition(
325                                    fieldsDisplayValues, parentFieldName, offset);
326                    }
327    
328                    StringBundler sb = new StringBundler(fieldRepetition);
329    
330                    while (fieldRepetition > 0) {
331                            offset = getFieldOffset(
332                                    fieldsDisplayValues, name, ddmFieldsCounter.get(name));
333    
334                            String fieldNamespace = StringUtil.randomId();
335    
336                            if (fieldDisplayable) {
337                                    fieldNamespace = getFieldNamespace(
338                                            fieldDisplayValue, ddmFieldsCounter, offset);
339                            }
340    
341                            fieldStructure.put("fieldNamespace", fieldNamespace);
342                            fieldStructure.put("valueIndex", ddmFieldsCounter.get(name));
343    
344                            if (fieldDisplayable) {
345                                    ddmFieldsCounter.incrementKey(name);
346                            }
347    
348                            StringBundler childrenHTML = new StringBundler(2);
349    
350                            childrenHTML.append(
351                                    getHTML(
352                                            request, response, ddmFormField.getNestedDDMFormFields(),
353                                            fields, ddmFormField, portletNamespace, namespace, mode,
354                                            readOnly, showEmptyFieldLabel, locale));
355    
356                            if (Validator.equals(ddmFormField.getType(), "select") ||
357                                    Validator.equals(ddmFormField.getType(), "radio")) {
358    
359                                    Map<String, Object> optionFreeMarkerContext =
360                                            new HashMap<String, Object>(freeMarkerContext);
361    
362                                    optionFreeMarkerContext.put(
363                                            "parentFieldStructure", fieldStructure);
364    
365                                    childrenHTML.append(
366                                            getDDMFormFieldOptionHTML(
367                                                    request, response, ddmFormField, mode, readOnly, locale,
368                                                    optionFreeMarkerContext));
369                            }
370    
371                            fieldStructure.put("children", childrenHTML.toString());
372    
373                            boolean disabled = GetterUtil.getBoolean(
374                                    fieldStructure.get("disabled"), false);
375    
376                            if (disabled) {
377                                    readOnly = true;
378                            }
379    
380                            sb.append(
381                                    processFTL(
382                                            request, response, ddmFormField.getNamespace(),
383                                            ddmFormField.getType(), mode, readOnly, freeMarkerContext));
384    
385                            fieldRepetition--;
386                    }
387    
388                    return sb.toString();
389            }
390    
391            protected String getFieldNamespace(
392                    String fieldDisplayValue, DDMFieldsCounter ddmFieldsCounter,
393                    int offset) {
394    
395                    String[] fieldsDisplayValues = StringUtil.split(fieldDisplayValue);
396    
397                    String fieldsDisplayValue = fieldsDisplayValues[offset];
398    
399                    return StringUtil.extractLast(
400                            fieldsDisplayValue, DDMImpl.INSTANCE_SEPARATOR);
401            }
402    
403            protected int getFieldOffset(
404                    String[] fieldsDisplayValues, String name, int index) {
405    
406                    int offset = 0;
407    
408                    for (; offset < fieldsDisplayValues.length; offset++) {
409                            if (name.equals(fieldsDisplayValues[offset])) {
410                                    index--;
411    
412                                    if (index < 0) {
413                                            break;
414                                    }
415                            }
416                    }
417    
418                    return offset;
419            }
420    
421            protected Map<String, Map<String, Object>> getFieldsContext(
422                    HttpServletRequest request, HttpServletResponse response,
423                    String portletNamespace, String namespace) {
424    
425                    String fieldsContextKey =
426                            portletNamespace + namespace + "fieldsContext";
427    
428                    Map<String, Map<String, Object>> fieldsContext =
429                            (Map<String, Map<String, Object>>)request.getAttribute(
430                                    fieldsContextKey);
431    
432                    if (fieldsContext == null) {
433                            fieldsContext = new HashMap<String, Map<String, Object>>();
434    
435                            request.setAttribute(fieldsContextKey, fieldsContext);
436                    }
437    
438                    return fieldsContext;
439            }
440    
441            protected DDMFieldsCounter getFieldsCounter(
442                    HttpServletRequest request, HttpServletResponse response, Fields fields,
443                    String portletNamespace, String namespace) {
444    
445                    String fieldsCounterKey = portletNamespace + namespace + "fieldsCount";
446    
447                    DDMFieldsCounter ddmFieldsCounter =
448                            (DDMFieldsCounter)request.getAttribute(fieldsCounterKey);
449    
450                    if (ddmFieldsCounter == null) {
451                            ddmFieldsCounter = new DDMFieldsCounter();
452    
453                            request.setAttribute(fieldsCounterKey, ddmFieldsCounter);
454                    }
455    
456                    return ddmFieldsCounter;
457            }
458    
459            protected String getFieldsDisplayValue(
460                    HttpServletRequest request, HttpServletResponse response,
461                    Fields fields) {
462    
463                    String defaultFieldsDisplayValue = null;
464    
465                    if (fields != null) {
466                            Field fieldsDisplayField = fields.get(DDMImpl.FIELDS_DISPLAY_NAME);
467    
468                            if (fieldsDisplayField != null) {
469                                    defaultFieldsDisplayValue =
470                                            (String)fieldsDisplayField.getValue();
471                            }
472                    }
473    
474                    return ParamUtil.getString(
475                            request, DDMImpl.FIELDS_DISPLAY_NAME, defaultFieldsDisplayValue);
476            }
477    
478            protected String[] getFieldsDisplayValues(String fieldDisplayValue) {
479                    List<String> fieldsDisplayValues = new ArrayList<String>();
480    
481                    for (String value : StringUtil.split(fieldDisplayValue)) {
482                            String fieldName = StringUtil.extractFirst(
483                                    value, DDMImpl.INSTANCE_SEPARATOR);
484    
485                            fieldsDisplayValues.add(fieldName);
486                    }
487    
488                    return fieldsDisplayValues.toArray(
489                            new String[fieldsDisplayValues.size()]);
490            }
491    
492            protected Map<String, Object> getFreeMarkerContext(
493                    HttpServletRequest request, HttpServletResponse response,
494                    String portletNamespace, String namespace, DDMFormField ddmFormField,
495                    DDMFormField parentDDMFormField, boolean showEmptyFieldLabel,
496                    Locale locale) {
497    
498                    Map<String, Object> freeMarkerContext = new HashMap<String, Object>();
499    
500                    Map<String, Object> fieldContext = getFieldContext(
501                            request, response, portletNamespace, namespace, ddmFormField,
502                            locale);
503    
504                    Map<String, Object> parentFieldContext = new HashMap<String, Object>();
505    
506                    if (parentDDMFormField != null) {
507                            parentFieldContext = getFieldContext(
508                                    request, response, portletNamespace, namespace,
509                                    parentDDMFormField, locale);
510                    }
511    
512                    freeMarkerContext.put("fieldStructure", fieldContext);
513                    freeMarkerContext.put("namespace", namespace);
514                    freeMarkerContext.put("parentFieldStructure", parentFieldContext);
515                    freeMarkerContext.put("portletNamespace", portletNamespace);
516                    freeMarkerContext.put(
517                            "requestedLanguageDir", LanguageUtil.get(locale, "lang.dir"));
518                    freeMarkerContext.put("requestedLocale", locale);
519                    freeMarkerContext.put("showEmptyFieldLabel", showEmptyFieldLabel);
520    
521                    return freeMarkerContext;
522            }
523    
524            protected String getHTML(
525                            HttpServletRequest request, HttpServletResponse response,
526                            List<DDMFormField> ddmFormFields, Fields fields,
527                            DDMFormField parentDDMFormField, String portletNamespace,
528                            String namespace, String mode, boolean readOnly,
529                            boolean showEmptyFieldLabel, Locale locale)
530                    throws Exception {
531    
532                    StringBundler sb = new StringBundler(ddmFormFields.size());
533    
534                    for (DDMFormField ddmFormField : ddmFormFields) {
535                            sb.append(
536                                    getFieldHTML(
537                                            request, response, ddmFormField, fields, parentDDMFormField,
538                                            portletNamespace, namespace, mode, readOnly,
539                                            showEmptyFieldLabel, locale));
540                    }
541    
542                    return sb.toString();
543            }
544    
545            protected URL getResource(String name) {
546                    Class<?> clazz = getClass();
547    
548                    ClassLoader classLoader = clazz.getClassLoader();
549    
550                    return classLoader.getResource(name);
551            }
552    
553            protected String processFTL(
554                            HttpServletRequest request, HttpServletResponse response,
555                            String fieldNamespace, String type, String mode, boolean readOnly,
556                            Map<String, Object> freeMarkerContext)
557                    throws Exception {
558    
559                    if (Validator.isNull(fieldNamespace)) {
560                            fieldNamespace = _DEFAULT_NAMESPACE;
561                    }
562    
563                    TemplateResource templateResource = _defaultTemplateResource;
564    
565                    Map<String, Object> fieldStructure =
566                            (Map<String, Object>)freeMarkerContext.get("fieldStructure");
567    
568                    boolean fieldReadOnly = GetterUtil.getBoolean(
569                            fieldStructure.get("readOnly"));
570    
571                    if ((fieldReadOnly && Validator.isNotNull(mode) &&
572                             StringUtil.equalsIgnoreCase(
573                                    mode, DDMTemplateConstants.TEMPLATE_MODE_EDIT)) ||
574                            readOnly) {
575    
576                            fieldNamespace = _DEFAULT_READ_ONLY_NAMESPACE;
577    
578                            templateResource = _defaultReadOnlyTemplateResource;
579                    }
580    
581                    String templateName = StringUtil.replaceFirst(
582                            type, fieldNamespace.concat(StringPool.DASH), StringPool.BLANK);
583    
584                    StringBundler resourcePath = new StringBundler(5);
585    
586                    resourcePath.append(_TPL_PATH);
587                    resourcePath.append(StringUtil.toLowerCase(fieldNamespace));
588                    resourcePath.append(CharPool.SLASH);
589                    resourcePath.append(templateName);
590                    resourcePath.append(_TPL_EXT);
591    
592                    String resource = resourcePath.toString();
593    
594                    URL url = getResource(resource);
595    
596                    if (url != null) {
597                            templateResource = new URLTemplateResource(resource, url);
598                    }
599    
600                    if (templateResource == null) {
601                            throw new Exception("Unable to load template resource " + resource);
602                    }
603    
604                    Template template = TemplateManagerUtil.getTemplate(
605                            TemplateConstants.LANG_TYPE_FTL, templateResource, false);
606    
607                    for (Map.Entry<String, Object> entry : freeMarkerContext.entrySet()) {
608                            template.put(entry.getKey(), entry.getValue());
609                    }
610    
611                    return processFTL(request, response, template);
612            }
613    
614            /**
615             * @see com.liferay.taglib.util.ThemeUtil#includeFTL
616             */
617            protected String processFTL(
618                            HttpServletRequest request, HttpServletResponse response,
619                            Template template)
620                    throws Exception {
621    
622                    // FreeMarker variables
623    
624                    template.prepare(request);
625    
626                    // Tag libraries
627    
628                    Writer writer = new UnsyncStringWriter();
629    
630                    // Portal JSP tag library factory
631    
632                    TemplateHashModel portalTaglib =
633                            FreeMarkerTaglibFactoryUtil.createTaglibFactory(
634                                    request.getServletContext());
635    
636                    template.put("PortalJspTagLibs", portalTaglib);
637    
638                    // FreeMarker JSP tag library support
639    
640                    GenericServlet genericServlet = new JSPSupportServlet(
641                            request.getServletContext());
642    
643                    ServletContextHashModel servletContextHashModel =
644                            new ServletContextHashModel(
645                                    genericServlet, ObjectWrapper.DEFAULT_WRAPPER);
646    
647                    template.put("Application", servletContextHashModel);
648    
649                    HttpRequestHashModel httpRequestHashModel = new HttpRequestHashModel(
650                            request, response, ObjectWrapper.DEFAULT_WRAPPER);
651    
652                    template.put("Request", httpRequestHashModel);
653    
654                    // Merge templates
655    
656                    template.processTemplate(writer);
657    
658                    return writer.toString();
659            }
660    
661            private static final String _DEFAULT_NAMESPACE = "alloy";
662    
663            private static final String _DEFAULT_READ_ONLY_NAMESPACE = "readonly";
664    
665            private static final String[] _SUPPORTED_DDM_FORM_FIELD_TYPES = {
666                    "checkbox", "ddm-date", "ddm-decimal", "ddm-documentlibrary",
667                    "ddm-geolocation", "ddm-image", "ddm-integer", "ddm-link-to-page",
668                    "ddm-number", "ddm-separator", "ddm-text-html", "fieldset", "option",
669                    "radio", "select", "text", "textarea"
670            };
671    
672            private static final String _TPL_EXT = ".ftl";
673    
674            private static final String _TPL_PATH =
675                    "com/liferay/portlet/dynamicdatamapping/dependencies/";
676    
677            private TemplateResource _defaultReadOnlyTemplateResource;
678            private TemplateResource _defaultTemplateResource;
679    
680    }