001
014
015 package com.liferay.portlet.dynamicdatamapping.util;
016
017 import com.liferay.portal.kernel.exception.PortalException;
018 import com.liferay.portal.kernel.exception.SystemException;
019 import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
020 import com.liferay.portal.kernel.json.JSONArray;
021 import com.liferay.portal.kernel.json.JSONFactoryUtil;
022 import com.liferay.portal.kernel.json.JSONObject;
023 import com.liferay.portal.kernel.language.LanguageUtil;
024 import com.liferay.portal.kernel.security.pacl.DoPrivileged;
025 import com.liferay.portal.kernel.template.Template;
026 import com.liferay.portal.kernel.template.TemplateConstants;
027 import com.liferay.portal.kernel.template.TemplateManagerUtil;
028 import com.liferay.portal.kernel.template.TemplateResource;
029 import com.liferay.portal.kernel.template.URLTemplateResource;
030 import com.liferay.portal.kernel.util.ArrayUtil;
031 import com.liferay.portal.kernel.util.CharPool;
032 import com.liferay.portal.kernel.util.GetterUtil;
033 import com.liferay.portal.kernel.util.HtmlUtil;
034 import com.liferay.portal.kernel.util.LocaleUtil;
035 import com.liferay.portal.kernel.util.LocalizationUtil;
036 import com.liferay.portal.kernel.util.ParamUtil;
037 import com.liferay.portal.kernel.util.StringBundler;
038 import com.liferay.portal.kernel.util.StringPool;
039 import com.liferay.portal.kernel.util.StringUtil;
040 import com.liferay.portal.kernel.util.Validator;
041 import com.liferay.portal.kernel.xml.Attribute;
042 import com.liferay.portal.kernel.xml.Document;
043 import com.liferay.portal.kernel.xml.DocumentException;
044 import com.liferay.portal.kernel.xml.Element;
045 import com.liferay.portal.kernel.xml.Node;
046 import com.liferay.portal.kernel.xml.SAXReaderUtil;
047 import com.liferay.portal.kernel.xml.XPath;
048 import com.liferay.portal.util.PortalUtil;
049 import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
050 import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
051 import com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants;
052 import com.liferay.portlet.dynamicdatamapping.service.DDMStorageLinkLocalServiceUtil;
053 import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
054 import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
055 import com.liferay.portlet.dynamicdatamapping.storage.Field;
056 import com.liferay.portlet.dynamicdatamapping.storage.Fields;
057 import com.liferay.util.freemarker.FreeMarkerTaglibFactoryUtil;
058
059 import freemarker.ext.servlet.HttpRequestHashModel;
060 import freemarker.ext.servlet.ServletContextHashModel;
061
062 import freemarker.template.ObjectWrapper;
063 import freemarker.template.TemplateHashModel;
064
065 import java.io.IOException;
066 import java.io.Writer;
067
068 import java.net.URL;
069
070 import java.util.ArrayList;
071 import java.util.HashMap;
072 import java.util.List;
073 import java.util.Locale;
074 import java.util.Map;
075
076 import javax.servlet.GenericServlet;
077 import javax.servlet.Servlet;
078 import javax.servlet.ServletException;
079 import javax.servlet.ServletRequest;
080 import javax.servlet.ServletResponse;
081 import javax.servlet.http.HttpServletRequest;
082 import javax.servlet.http.HttpServletResponse;
083 import javax.servlet.jsp.PageContext;
084
085
091 @DoPrivileged
092 public class DDMXSDImpl implements DDMXSD {
093
094 public DDMXSDImpl() {
095 String defaultTemplateId = _TPL_PATH + "alloy/text.ftl";
096
097 URL defaultTemplateURL = getResource(defaultTemplateId);
098
099 _defaultTemplateResource = new URLTemplateResource(
100 defaultTemplateId, defaultTemplateURL);
101
102 String defaultReadOnlyTemplateId = _TPL_PATH + "readonly/default.ftl";
103
104 URL defaultReadOnlyTemplateURL = getResource(defaultReadOnlyTemplateId);
105
106 _defaultReadOnlyTemplateResource = new URLTemplateResource(
107 defaultReadOnlyTemplateId, defaultReadOnlyTemplateURL);
108 }
109
110 @Override
111 public String getFieldHTML(
112 PageContext pageContext, Element element, Fields fields,
113 String portletNamespace, String namespace, String mode,
114 boolean readOnly, Locale locale)
115 throws Exception {
116
117 Map<String, Object> freeMarkerContext = getFreeMarkerContext(
118 pageContext, portletNamespace, namespace, element, locale);
119
120 if (fields != null) {
121 freeMarkerContext.put("fields", fields);
122 }
123
124 Map<String, Object> fieldStructure =
125 (Map<String, Object>)freeMarkerContext.get("fieldStructure");
126
127 int fieldRepetition = 1;
128 int offset = 0;
129
130 DDMFieldsCounter ddmFieldsCounter = getFieldsCounter(
131 pageContext, fields, portletNamespace, namespace);
132
133 String name = element.attributeValue("name");
134
135 String fieldDisplayValue = getFieldsDisplayValue(
136 pageContext, fields, namespace);
137
138 String[] fieldsDisplayValues = getFieldsDisplayValues(
139 fieldDisplayValue);
140
141 boolean fieldDisplayable = ArrayUtil.contains(
142 fieldsDisplayValues, name);
143
144 if (fieldDisplayable) {
145 Map<String, Object> parentFieldStructure =
146 (Map<String, Object>)freeMarkerContext.get(
147 "parentFieldStructure");
148
149 String parentFieldName = (String)parentFieldStructure.get("name");
150
151 offset = getFieldOffset(
152 fieldsDisplayValues, name, ddmFieldsCounter.get(name));
153
154 if (offset == fieldsDisplayValues.length) {
155 return StringPool.BLANK;
156 }
157
158 fieldRepetition = countFieldRepetition(
159 fieldsDisplayValues, parentFieldName, offset);
160 }
161
162 StringBundler sb = new StringBundler(fieldRepetition);
163
164 while (fieldRepetition > 0) {
165 offset = getFieldOffset(
166 fieldsDisplayValues, name, ddmFieldsCounter.get(name));
167
168 String fieldNamespace = StringUtil.randomId();
169
170 if (fieldDisplayable) {
171 fieldNamespace = getFieldNamespace(
172 fieldDisplayValue, ddmFieldsCounter, offset);
173 }
174
175 fieldStructure.put("fieldNamespace", fieldNamespace);
176
177 fieldStructure.put("valueIndex", ddmFieldsCounter.get(name));
178
179 if (fieldDisplayable) {
180 ddmFieldsCounter.incrementKey(name);
181 }
182
183 String childrenHTML = getHTML(
184 pageContext, element, fields, portletNamespace, namespace, mode,
185 readOnly, locale);
186
187 fieldStructure.put("children", childrenHTML);
188
189 boolean disabled = GetterUtil.getBoolean(
190 fieldStructure.get("disabled"), false);
191
192 if (disabled) {
193 readOnly = true;
194 }
195
196 sb.append(
197 processFTL(
198 pageContext, element, mode, readOnly, freeMarkerContext));
199
200 fieldRepetition--;
201 }
202
203 return sb.toString();
204 }
205
206 @Override
207 public String getFieldHTMLByName(
208 PageContext pageContext, long classNameId, long classPK,
209 String fieldName, Fields fields, String portletNamespace,
210 String namespace, String mode, boolean readOnly, Locale locale)
211 throws Exception {
212
213 String xsd = getXSD(classNameId, classPK);
214
215 Document document = SAXReaderUtil.read(xsd);
216
217 String xPathExpression =
218 "
219 HtmlUtil.escapeXPathAttribute(fieldName)).concat("]");
220
221 XPath xPathSelector = SAXReaderUtil.createXPath(xPathExpression);
222
223 Node node = xPathSelector.selectSingleNode(document.getRootElement());
224
225 Element element = (Element)node.asXPathResult(node.getParent());
226
227 return getFieldHTML(
228 pageContext, element, fields, portletNamespace, namespace, mode,
229 readOnly, locale);
230 }
231
232 @Override
233 public String getHTML(
234 PageContext pageContext, DDMStructure ddmStructure, Fields fields,
235 String portletNamespace, String namespace, boolean readOnly,
236 Locale locale)
237 throws Exception {
238
239 return getHTML(
240 pageContext, ddmStructure.getXsd(), fields, portletNamespace,
241 namespace, readOnly, locale);
242 }
243
244 @Override
245 public String getHTML(
246 PageContext pageContext, DDMTemplate ddmTemplate, Fields fields,
247 String portletNamespace, String namespace, boolean readOnly,
248 Locale locale)
249 throws Exception {
250
251 return getHTML(
252 pageContext, ddmTemplate.getScript(), fields, portletNamespace,
253 namespace, ddmTemplate.getMode(), readOnly, locale);
254 }
255
256 public String getHTML(
257 PageContext pageContext, Element element, Fields fields,
258 String portletNamespace, Locale locale)
259 throws Exception {
260
261 return getHTML(
262 pageContext, element, fields, portletNamespace, StringPool.BLANK,
263 null, false, locale);
264 }
265
266 public String getHTML(
267 PageContext pageContext, Element element, Fields fields,
268 String portletNamespace, String namespace, String mode,
269 boolean readOnly, Locale locale)
270 throws Exception {
271
272 List<Element> dynamicElementElements = element.elements(
273 "dynamic-element");
274
275 StringBundler sb = new StringBundler(dynamicElementElements.size());
276
277 for (Element dynamicElementElement : dynamicElementElements) {
278 sb.append(
279 getFieldHTML(
280 pageContext, dynamicElementElement, fields,
281 portletNamespace, namespace, mode, readOnly, locale));
282 }
283
284 return sb.toString();
285 }
286
287 public String getHTML(
288 PageContext pageContext, Element element, String portletNamespace,
289 Locale locale)
290 throws Exception {
291
292 return getHTML(pageContext, element, null, portletNamespace, locale);
293 }
294
295 @Override
296 public String getHTML(
297 PageContext pageContext, String xml, Fields fields,
298 String portletNamespace, Locale locale)
299 throws Exception {
300
301 return getHTML(
302 pageContext, xml, fields, portletNamespace, StringPool.BLANK,
303 locale);
304 }
305
306 @Override
307 public String getHTML(
308 PageContext pageContext, String xml, Fields fields,
309 String portletNamespace, String namespace, boolean readOnly,
310 Locale locale)
311 throws Exception {
312
313 return getHTML(
314 pageContext, xml, fields, portletNamespace, namespace, null,
315 readOnly, locale);
316 }
317
318 @Override
319 public String getHTML(
320 PageContext pageContext, String xml, Fields fields,
321 String portletNamespace, String namespace, Locale locale)
322 throws Exception {
323
324 return getHTML(
325 pageContext, xml, fields, portletNamespace, namespace, false,
326 locale);
327 }
328
329 @Override
330 public String getHTML(
331 PageContext pageContext, String xml, Fields fields,
332 String portletNamespace, String namespace, String mode,
333 boolean readOnly, Locale locale)
334 throws Exception {
335
336 Document document = SAXReaderUtil.read(xml);
337
338 return getHTML(
339 pageContext, document.getRootElement(), fields, portletNamespace,
340 namespace, mode, readOnly, locale);
341 }
342
343 @Override
344 public String getHTML(
345 PageContext pageContext, String xml, String portletNamespace,
346 Locale locale)
347 throws Exception {
348
349 return getHTML(pageContext, xml, null, locale);
350 }
351
352 @Override
353 public JSONArray getJSONArray(DDMStructure structure, String xsd)
354 throws PortalException, SystemException {
355
356 JSONArray jsonArray = null;
357
358 if (Validator.isNull(xsd)) {
359 jsonArray = getJSONArray(structure.getDocument());
360 }
361 else {
362 jsonArray = getJSONArray(xsd);
363 }
364
365 addStructureFieldAttributes(structure, jsonArray);
366
367 return jsonArray;
368 }
369
370 @Override
371 public JSONArray getJSONArray(Document document) throws PortalException {
372 return getJSONArray(document.getRootElement());
373 }
374
375 @Override
376 public JSONArray getJSONArray(Element element) throws PortalException {
377 JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
378
379 Document document = element.getDocument();
380
381 String defaultLanguageId = LocalizationUtil.getDefaultLanguageId(
382 document.asXML());
383
384 List<Element> dynamicElementElements = element.elements(
385 "dynamic-element");
386
387 for (Element dynamicElementElement : dynamicElementElements) {
388 JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
389 JSONObject localizationMapJSONObject =
390 JSONFactoryUtil.createJSONObject();
391
392 for (Attribute attribute : dynamicElementElement.attributes()) {
393 jsonObject.put(attribute.getName(), attribute.getValue());
394 }
395
396 jsonObject.put("autoGeneratedName", false);
397 jsonObject.put("id", dynamicElementElement.attributeValue("name"));
398
399 String type = jsonObject.getString("type");
400
401 List<Element> metadataElements = dynamicElementElement.elements(
402 "meta-data");
403
404 for (Element metadataElement : metadataElements) {
405 if (metadataElement == null) {
406 continue;
407 }
408
409 String locale = metadataElement.attributeValue("locale");
410
411 JSONObject localeMap = JSONFactoryUtil.createJSONObject();
412
413 for (Element metadataEntryElement :
414 metadataElement.elements()) {
415
416 String attributeName = metadataEntryElement.attributeValue(
417 "name");
418 String attributeValue = metadataEntryElement.getTextTrim();
419
420 putMetadataValue(
421 localeMap, attributeName, attributeValue, type);
422
423 if (defaultLanguageId.equals(locale)) {
424 putMetadataValue(
425 jsonObject, attributeName, attributeValue, type);
426 }
427 }
428
429 localizationMapJSONObject.put(locale, localeMap);
430 }
431
432 jsonObject.put("localizationMap", localizationMapJSONObject);
433
434 JSONArray hiddenAttributesJSONArray =
435 JSONFactoryUtil.createJSONArray();
436
437 if (type.equals(DDMImpl.TYPE_CHECKBOX)) {
438 hiddenAttributesJSONArray.put("required");
439 }
440
441 hiddenAttributesJSONArray.put("readOnly");
442
443 jsonObject.put("hiddenAttributes", hiddenAttributesJSONArray);
444
445 String key = "fields";
446
447 if (type.equals(DDMImpl.TYPE_RADIO) ||
448 type.equals(DDMImpl.TYPE_SELECT)) {
449
450 key = "options";
451 }
452
453 jsonObject.put(key, getJSONArray(dynamicElementElement));
454
455 jsonArray.put(jsonObject);
456 }
457
458 return jsonArray;
459 }
460
461 @Override
462 public JSONArray getJSONArray(String xml)
463 throws PortalException, SystemException {
464
465 try {
466 return getJSONArray(SAXReaderUtil.read(xml));
467 }
468 catch (DocumentException de) {
469 throw new SystemException();
470 }
471 }
472
473 @Override
474 public String getSimpleFieldHTML(
475 PageContext pageContext, Element element, Field field,
476 String portletNamespace, String namespace, String mode,
477 boolean readOnly, Locale locale)
478 throws Exception {
479
480 Map<String, Object> freeMarkerContext = getFreeMarkerContext(
481 pageContext, portletNamespace, namespace, element, locale);
482
483 freeMarkerContext.put("ignoreRepeatable", Boolean.TRUE);
484
485 Map<String, Object> fieldStructure =
486 (Map<String, Object>)freeMarkerContext.get("fieldStructure");
487
488 DDMFieldsCounter ddmFieldsCounter = getFieldsCounter(
489 pageContext, null, portletNamespace, namespace);
490
491 String name = element.attributeValue("name");
492
493 if ((field != null) && Validator.isNotNull(field.getValue())) {
494 Fields fields = new Fields();
495
496 fields.put(field);
497
498 freeMarkerContext.put("fields", fields);
499 }
500
501 fieldStructure.put("fieldNamespace", StringUtil.randomId());
502 fieldStructure.put("valueIndex", ddmFieldsCounter.get(name));
503
504 List<Element> dynamicElementElements = element.elements(
505 "dynamic-element");
506
507 StringBundler sb = new StringBundler(dynamicElementElements.size());
508
509 for (Element dynamicElementElement : dynamicElementElements) {
510 String type = dynamicElementElement.attributeValue("type");
511
512 if (!type.equals("option")) {
513 sb.append(StringPool.BLANK);
514 }
515 else {
516 sb.append(
517 getSimpleFieldHTML(
518 pageContext, dynamicElementElement, field,
519 portletNamespace, namespace, mode, readOnly, locale));
520 }
521 }
522
523 fieldStructure.put("children", sb.toString());
524
525 return processFTL(
526 pageContext, element, mode, readOnly, freeMarkerContext);
527 }
528
529 @Override
530 public String getSimpleFieldHTMLByName(
531 PageContext pageContext, long classNameId, long classPK,
532 Field field, String portletNamespace, String namespace, String mode,
533 boolean readOnly, Locale locale)
534 throws Exception {
535
536 String xsd = getXSD(classNameId, classPK);
537
538 Document document = SAXReaderUtil.read(xsd);
539
540 String xPathExpression =
541 "
542 HtmlUtil.escapeXPathAttribute(field.getName())).concat("]");
543
544 XPath xPathSelector = SAXReaderUtil.createXPath(xPathExpression);
545
546 Node node = xPathSelector.selectSingleNode(document.getRootElement());
547
548 Element element = (Element)node.asXPathResult(node.getParent());
549
550 return getSimpleFieldHTML(
551 pageContext, element, field, portletNamespace, namespace, mode,
552 readOnly, locale);
553 }
554
555 @Override
556 public String getXSD(long classNameId, long classPK)
557 throws PortalException, SystemException {
558
559 if ((classNameId <= 0) || (classPK <= 0)) {
560 return null;
561 }
562
563 long ddmStructureClassNameId = PortalUtil.getClassNameId(
564 DDMStructure.class);
565
566 long ddmTemplateClassNameId = PortalUtil.getClassNameId(
567 DDMTemplate.class);
568
569 if (classNameId == ddmStructureClassNameId) {
570 DDMStructure structure = DDMStructureLocalServiceUtil.getStructure(
571 classPK);
572
573 return structure.getCompleteXsd();
574 }
575 else if (classNameId == ddmTemplateClassNameId) {
576 DDMTemplate template = DDMTemplateLocalServiceUtil.getTemplate(
577 classPK);
578
579 return template.getScript();
580 }
581
582 return null;
583 }
584
585 protected JSONArray addStructureFieldAttributes(
586 DDMStructure structure, JSONArray jsonArray) {
587
588 for (int i = 0; i < jsonArray.length(); i++) {
589 JSONObject jsonObject = jsonArray.getJSONObject(i);
590
591 String fieldName = jsonObject.getString("name");
592
593 jsonObject.put(
594 "readOnlyAttributes",
595 getStructureFieldReadOnlyAttributes(structure, fieldName));
596 }
597
598 return jsonArray;
599 }
600
601 protected int countFieldRepetition(
602 String[] fieldsDisplayValues, String parentFieldName, int offset) {
603
604 int total = 0;
605
606 String fieldName = fieldsDisplayValues[offset];
607
608 for (; offset < fieldsDisplayValues.length; offset++) {
609 String fieldNameValue = fieldsDisplayValues[offset];
610
611 if (fieldNameValue.equals(fieldName)) {
612 total++;
613 }
614
615 if (fieldNameValue.equals(parentFieldName)) {
616 break;
617 }
618 }
619
620 return total;
621 }
622
623 protected Map<String, Object> getFieldContext(
624 PageContext pageContext, String portletNamespace, String namespace,
625 Element dynamicElementElement, Locale locale) {
626
627 Map<String, Map<String, Object>> fieldsContext = getFieldsContext(
628 pageContext, portletNamespace, namespace);
629
630 String name = dynamicElementElement.attributeValue("name");
631
632 Map<String, Object> fieldContext = fieldsContext.get(name);
633
634 if (fieldContext != null) {
635 return fieldContext;
636 }
637
638 Document document = dynamicElementElement.getDocument();
639
640 HttpServletRequest request =
641 (HttpServletRequest)pageContext.getRequest();
642
643 String defaultLanguageId = request.getParameter("defaultLanguageId");
644
645 if (Validator.isNull(defaultLanguageId)) {
646 defaultLanguageId = GetterUtil.getString(
647 pageContext.getAttribute("contentDefaultLanguageId"));
648 }
649
650 String editingLanguageId = LocaleUtil.toLanguageId(locale);
651
652 if (Validator.isNull(defaultLanguageId)) {
653 defaultLanguageId = editingLanguageId;
654 }
655
656 String structureLanguageId = editingLanguageId;
657
658 String[] availableLanguageIds =
659 LocalizationUtil.getAvailableLanguageIds(document);
660
661 if (!ArrayUtil.contains(availableLanguageIds, editingLanguageId)) {
662 structureLanguageId = LocalizationUtil.getDefaultLanguageId(
663 document);
664 }
665
666 Element metadataElement =
667 (Element)dynamicElementElement.selectSingleNode(
668 "meta-data[@locale='" + structureLanguageId + "']");
669
670 fieldContext = new HashMap<String, Object>();
671
672 if (metadataElement != null) {
673 for (Element metadataEntry : metadataElement.elements()) {
674 fieldContext.put(
675 metadataEntry.attributeValue("name"),
676 metadataEntry.getText());
677 }
678 }
679
680 for (Attribute attribute : dynamicElementElement.attributes()) {
681 fieldContext.put(attribute.getName(), attribute.getValue());
682 }
683
684 boolean localizable = GetterUtil.getBoolean(
685 dynamicElementElement.attributeValue("localizable"), true);
686
687 if (!localizable && !editingLanguageId.equals(defaultLanguageId)) {
688 fieldContext.put("disabled", Boolean.TRUE.toString());
689 }
690
691 fieldContext.put("fieldNamespace", StringUtil.randomId());
692
693 boolean checkRequired = GetterUtil.getBoolean(
694 pageContext.getAttribute("checkRequired"), true);
695
696 if (!checkRequired) {
697 fieldContext.put("required", Boolean.FALSE.toString());
698 }
699
700 fieldsContext.put(name, fieldContext);
701
702 return fieldContext;
703 }
704
705 protected int getFieldOffset(
706 String[] fieldsDisplayValues, String name, int index) {
707
708 int offset = 0;
709
710 for (; offset < fieldsDisplayValues.length; offset++) {
711 if (name.equals(fieldsDisplayValues[offset])) {
712 index--;
713
714 if (index < 0) {
715 break;
716 }
717 }
718 }
719
720 return offset;
721 }
722
723 protected String getFieldNamespace(
724 String fieldDisplayValue, DDMFieldsCounter ddmFieldsCounter,
725 int offset) {
726
727 String[] fieldsDisplayValues = StringUtil.split(fieldDisplayValue);
728
729 String fieldsDisplayValue = fieldsDisplayValues[offset];
730
731 return StringUtil.extractLast(
732 fieldsDisplayValue, DDMImpl.INSTANCE_SEPARATOR);
733 }
734
735 protected Map<String, Map<String, Object>> getFieldsContext(
736 PageContext pageContext, String portletNamespace, String namespace) {
737
738 String fieldsContextKey =
739 portletNamespace + namespace + "fieldsContext";
740
741 Map<String, Map<String, Object>> fieldsContext =
742 (Map<String, Map<String, Object>>)pageContext.getAttribute(
743 fieldsContextKey);
744
745 if (fieldsContext == null) {
746 fieldsContext = new HashMap<String, Map<String, Object>>();
747
748 pageContext.setAttribute(fieldsContextKey, fieldsContext);
749 }
750
751 return fieldsContext;
752 }
753
754 protected DDMFieldsCounter getFieldsCounter(
755 PageContext pageContext, Fields fields, String portletNamespace,
756 String namespace) {
757
758 String fieldsCounterKey = portletNamespace + namespace + "fieldsCount";
759
760 DDMFieldsCounter ddmFieldsCounter =
761 (DDMFieldsCounter)pageContext.getAttribute(fieldsCounterKey);
762
763 if (ddmFieldsCounter == null) {
764 ddmFieldsCounter = new DDMFieldsCounter();
765
766 pageContext.setAttribute(fieldsCounterKey, ddmFieldsCounter);
767 }
768
769 return ddmFieldsCounter;
770 }
771
772 protected String getFieldsDisplayValue(
773 PageContext pageContext, Fields fields, String namespace) {
774
775 String defaultFieldsDisplayValue = null;
776
777 if (fields != null) {
778 Field fieldsDisplayField = fields.get(DDMImpl.FIELDS_DISPLAY_NAME);
779
780 if (fieldsDisplayField != null) {
781 defaultFieldsDisplayValue =
782 (String)fieldsDisplayField.getValue();
783 }
784 }
785
786 return ParamUtil.getString(
787 (HttpServletRequest)pageContext.getRequest(),
788 namespace + DDMImpl.FIELDS_DISPLAY_NAME, defaultFieldsDisplayValue);
789 }
790
791 protected String[] getFieldsDisplayValues(String fieldDisplayValue) {
792 List<String> fieldsDisplayValues = new ArrayList<String>();
793
794 for (String value : StringUtil.split(fieldDisplayValue)) {
795 String fieldName = StringUtil.extractFirst(
796 value, DDMImpl.INSTANCE_SEPARATOR);
797
798 fieldsDisplayValues.add(fieldName);
799 }
800
801 return fieldsDisplayValues.toArray(
802 new String[fieldsDisplayValues.size()]);
803 }
804
805 protected Map<String, Object> getFreeMarkerContext(
806 PageContext pageContext, String portletNamespace, String namespace,
807 Element dynamicElementElement, Locale locale) {
808
809 Map<String, Object> freeMarkerContext = new HashMap<String, Object>();
810
811 Map<String, Object> fieldContext = getFieldContext(
812 pageContext, portletNamespace, namespace, dynamicElementElement,
813 locale);
814
815 Map<String, Object> parentFieldContext = new HashMap<String, Object>();
816
817 Element parentElement = dynamicElementElement.getParent();
818
819 if (parentElement != null) {
820 parentFieldContext = getFieldContext(
821 pageContext, portletNamespace, namespace, parentElement,
822 locale);
823 }
824
825 freeMarkerContext.put("fieldStructure", fieldContext);
826 freeMarkerContext.put("namespace", namespace);
827 freeMarkerContext.put("parentFieldStructure", parentFieldContext);
828 freeMarkerContext.put("portletNamespace", portletNamespace);
829 freeMarkerContext.put(
830 "requestedLanguageDir", LanguageUtil.get(locale, "lang.dir"));
831 freeMarkerContext.put("requestedLocale", locale);
832
833 return freeMarkerContext;
834 }
835
836 protected URL getResource(String name) {
837 Class<?> clazz = getClass();
838
839 ClassLoader classLoader = clazz.getClassLoader();
840
841 return classLoader.getResource(name);
842 }
843
844 protected JSONArray getStructureFieldReadOnlyAttributes(
845 DDMStructure structure, String fieldName) {
846
847 JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
848
849 try {
850 if (DDMStorageLinkLocalServiceUtil.getStructureStorageLinksCount(
851 structure.getStructureId()) > 0) {
852
853 jsonArray.put("name");
854 }
855 }
856 catch (Exception e) {
857 }
858
859 return jsonArray;
860 }
861
862 protected String processFTL(
863 PageContext pageContext, Element element, String mode,
864 boolean readOnly, Map<String, Object> freeMarkerContext)
865 throws Exception {
866
867 String fieldNamespace = element.attributeValue(
868 "fieldNamespace", _DEFAULT_NAMESPACE);
869
870 TemplateResource templateResource = _defaultTemplateResource;
871
872 Map<String, Object> fieldStructure =
873 (Map<String, Object>)freeMarkerContext.get("fieldStructure");
874
875 boolean fieldReadOnly = GetterUtil.getBoolean(
876 fieldStructure.get("readOnly"));
877
878 if ((fieldReadOnly && Validator.isNotNull(mode) &&
879 StringUtil.equalsIgnoreCase(
880 mode, DDMTemplateConstants.TEMPLATE_MODE_EDIT)) ||
881 readOnly) {
882
883 fieldNamespace = _DEFAULT_READ_ONLY_NAMESPACE;
884
885 templateResource = _defaultReadOnlyTemplateResource;
886 }
887
888 String type = element.attributeValue("type");
889
890 String templateName = StringUtil.replaceFirst(
891 type, fieldNamespace.concat(StringPool.DASH), StringPool.BLANK);
892
893 StringBundler resourcePath = new StringBundler(5);
894
895 resourcePath.append(_TPL_PATH);
896 resourcePath.append(StringUtil.toLowerCase(fieldNamespace));
897 resourcePath.append(CharPool.SLASH);
898 resourcePath.append(templateName);
899 resourcePath.append(_TPL_EXT);
900
901 String resource = resourcePath.toString();
902
903 URL url = getResource(resource);
904
905 if (url != null) {
906 templateResource = new URLTemplateResource(resource, url);
907 }
908
909 if (templateResource == null) {
910 throw new Exception("Unable to load template resource " + resource);
911 }
912
913 Template template = TemplateManagerUtil.getTemplate(
914 TemplateConstants.LANG_TYPE_FTL, templateResource, false);
915
916 for (Map.Entry<String, Object> entry : freeMarkerContext.entrySet()) {
917 template.put(entry.getKey(), entry.getValue());
918 }
919
920 return processFTL(pageContext, template);
921 }
922
923
926 protected String processFTL(PageContext pageContext, Template template)
927 throws Exception {
928
929 HttpServletRequest request =
930 (HttpServletRequest)pageContext.getRequest();
931
932
933
934 template.prepare(request);
935
936
937
938 HttpServletResponse response =
939 (HttpServletResponse)pageContext.getResponse();
940
941 Writer writer = new UnsyncStringWriter();
942
943
944
945 TemplateHashModel portalTaglib =
946 FreeMarkerTaglibFactoryUtil.createTaglibFactory(
947 pageContext.getServletContext());
948
949 template.put("PortalJspTagLibs", portalTaglib);
950
951
952
953 final Servlet servlet = (Servlet)pageContext.getPage();
954
955 GenericServlet genericServlet = null;
956
957 if (servlet instanceof GenericServlet) {
958 genericServlet = (GenericServlet)servlet;
959 }
960 else {
961 genericServlet = new GenericServlet() {
962
963 @Override
964 public void service(
965 ServletRequest servletRequest,
966 ServletResponse servletResponse)
967 throws IOException, ServletException {
968
969 servlet.service(servletRequest, servletResponse);
970 }
971
972 };
973
974 genericServlet.init(pageContext.getServletConfig());
975 }
976
977 ServletContextHashModel servletContextHashModel =
978 new ServletContextHashModel(
979 genericServlet, ObjectWrapper.DEFAULT_WRAPPER);
980
981 template.put("Application", servletContextHashModel);
982
983 HttpRequestHashModel httpRequestHashModel = new HttpRequestHashModel(
984 request, response, ObjectWrapper.DEFAULT_WRAPPER);
985
986 template.put("Request", httpRequestHashModel);
987
988
989
990 template.processTemplate(writer);
991
992 return writer.toString();
993 }
994
995 protected void putMetadataValue(
996 JSONObject jsonObject, String attributeName, String attributeValue,
997 String type) {
998
999 if (type.equals(DDMImpl.TYPE_RADIO) ||
1000 type.equals(DDMImpl.TYPE_SELECT)) {
1001
1002 if (attributeName.equals("predefinedValue")) {
1003 try {
1004 jsonObject.put(
1005 attributeName,
1006 JSONFactoryUtil.createJSONArray(attributeValue));
1007 }
1008 catch (Exception e) {
1009 }
1010
1011 return;
1012 }
1013 }
1014
1015 jsonObject.put(attributeName, attributeValue);
1016 }
1017
1018 private static final String _DEFAULT_NAMESPACE = "alloy";
1019
1020 private static final String _DEFAULT_READ_ONLY_NAMESPACE = "readonly";
1021
1022 private static final String _TPL_EXT = ".ftl";
1023
1024 private static final String _TPL_PATH =
1025 "com/liferay/portlet/dynamicdatamapping/dependencies/";
1026
1027 private TemplateResource _defaultReadOnlyTemplateResource;
1028 private TemplateResource _defaultTemplateResource;
1029
1030 }