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.io;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.util.GetterUtil;
019    import com.liferay.portal.kernel.util.HtmlUtil;
020    import com.liferay.portal.kernel.util.LocaleUtil;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.StringUtil;
023    import com.liferay.portal.kernel.xml.Document;
024    import com.liferay.portal.kernel.xml.DocumentException;
025    import com.liferay.portal.kernel.xml.Element;
026    import com.liferay.portal.kernel.xml.SAXReaderUtil;
027    import com.liferay.portal.kernel.xml.XPath;
028    import com.liferay.portlet.dynamicdatamapping.model.DDMForm;
029    import com.liferay.portlet.dynamicdatamapping.model.DDMFormField;
030    import com.liferay.portlet.dynamicdatamapping.model.DDMFormFieldOptions;
031    import com.liferay.portlet.dynamicdatamapping.model.LocalizedValue;
032    
033    import java.util.ArrayList;
034    import java.util.HashSet;
035    import java.util.List;
036    import java.util.Locale;
037    import java.util.Set;
038    
039    /**
040     * @author Pablo Carvalho
041     */
042    public class DDMFormXSDDeserializerImpl implements DDMFormXSDDeserializer {
043    
044            @Override
045            public DDMForm deserialize(String serializedDDMForm)
046                    throws PortalException {
047    
048                    try {
049                            Document document = SAXReaderUtil.read(serializedDDMForm);
050    
051                            DDMForm ddmForm = new DDMForm();
052    
053                            setDDMFormAvailableLocales(document.getRootElement(), ddmForm);
054                            setDDMFormDefaultLocale(document.getRootElement(), ddmForm);
055                            setDDMFormFields(document.getRootElement(), ddmForm);
056                            setDDMFormLocalizedValuesDefaultLocale(ddmForm);
057    
058                            return ddmForm;
059                    }
060                    catch (DocumentException de) {
061                            throw new PortalException(de);
062                    }
063            }
064    
065            protected void addOptionValueLabels(
066                    Element dynamicElementElement, DDMFormFieldOptions ddmFormFieldOptions,
067                    String optionValue) {
068    
069                    List<Element> metadataElements = dynamicElementElement.elements(
070                            "meta-data");
071    
072                    for (Element metadataElement : metadataElements) {
073                            String languageId = metadataElement.attributeValue("locale");
074    
075                            Locale locale = LocaleUtil.fromLanguageId(languageId);
076    
077                            Element labelElement = fetchMetadataEntry(metadataElement, "label");
078    
079                            ddmFormFieldOptions.addOptionLabel(
080                                    optionValue, locale, labelElement.getText());
081                    }
082            }
083    
084            protected Element fetchMetadataEntry(
085                    Element parentElement, String entryName) {
086    
087                    XPath xPathSelector = SAXReaderUtil.createXPath(
088                            "entry[@name=" + HtmlUtil.escapeXPathAttribute(entryName) +
089                                    StringPool.CLOSE_BRACKET);
090    
091                    return (Element)xPathSelector.selectSingleNode(parentElement);
092            }
093    
094            protected Set<Locale> getAvailableLocales(Element rootElement) {
095                    Set<Locale> availableLocales = new HashSet<>();
096    
097                    String availableLanguageIds = rootElement.attributeValue(
098                            "available-locales");
099    
100                    for (String availableLanguageId :
101                                    StringUtil.split(availableLanguageIds)) {
102    
103                            Locale availableLocale = LocaleUtil.fromLanguageId(
104                                    availableLanguageId);
105    
106                            availableLocales.add(availableLocale);
107                    }
108    
109                    return availableLocales;
110            }
111    
112            protected DDMFormField getDDMFormField(Element dynamicElementElement) {
113                    String name = dynamicElementElement.attributeValue("name");
114                    String type = dynamicElementElement.attributeValue("type");
115    
116                    DDMFormField ddmFormField = new DDMFormField(name, type);
117    
118                    setDDMFormFieldDataType(dynamicElementElement, ddmFormField);
119                    setDDMFormFieldIndexType(dynamicElementElement, ddmFormField);
120                    setDDMFormFieldLocalizable(dynamicElementElement, ddmFormField);
121                    setDDMFormFieldMultiple(dynamicElementElement, ddmFormField);
122                    setDDMFormFieldNamespace(dynamicElementElement, ddmFormField);
123                    setDDMFormFieldReadOnly(dynamicElementElement, ddmFormField);
124                    setDDMFormFieldRepeatable(dynamicElementElement, ddmFormField);
125                    setDDMFormFieldRequired(dynamicElementElement, ddmFormField);
126                    setDDMFormFieldShowLabel(dynamicElementElement, ddmFormField);
127    
128                    List<Element> metadataElements = dynamicElementElement.elements(
129                            "meta-data");
130    
131                    for (Element metadataElement : metadataElements) {
132                            setDDMFormFieldMetadata(metadataElement, ddmFormField);
133                    }
134    
135                    if (type.equals("radio") || type.equals("select")) {
136                            setDDMFormFieldOptions(dynamicElementElement, ddmFormField);
137                    }
138                    else {
139                            setNestedDDMFormField(dynamicElementElement, ddmFormField);
140                    }
141    
142                    return ddmFormField;
143            }
144    
145            protected DDMFormFieldOptions getDDMFormFieldOptions(
146                    List<Element> dynamicElementElements) {
147    
148                    DDMFormFieldOptions ddmFormFieldOptions = new DDMFormFieldOptions();
149    
150                    for (Element dynamicElementElement : dynamicElementElements) {
151                            String value = dynamicElementElement.attributeValue("value");
152    
153                            ddmFormFieldOptions.addOption(value);
154    
155                            addOptionValueLabels(
156                                    dynamicElementElement, ddmFormFieldOptions, value);
157                    }
158    
159                    return ddmFormFieldOptions;
160            }
161    
162            protected List<DDMFormField> getDDMFormFields(Element rootElement) {
163                    List<DDMFormField> ddmFormFields = new ArrayList<>();
164    
165                    for (Element dynamicElement : rootElement.elements("dynamic-element")) {
166                            DDMFormField ddmFormField = getDDMFormField(dynamicElement);
167    
168                            ddmFormFields.add(ddmFormField);
169                    }
170    
171                    return ddmFormFields;
172            }
173    
174            protected Locale getDefaultLocale(Element rootElement) {
175                    String defaultLanguageId = rootElement.attributeValue("default-locale");
176    
177                    return LocaleUtil.fromLanguageId(defaultLanguageId);
178            }
179    
180            protected void setDDMFormAvailableLocales(
181                    Element rootElement, DDMForm ddmForm) {
182    
183                    Set<Locale> availableLocales = getAvailableLocales(rootElement);
184    
185                    ddmForm.setAvailableLocales(availableLocales);
186            }
187    
188            protected void setDDMFormDefaultLocale(
189                    Element rootElement, DDMForm ddmForm) {
190    
191                    Locale defaultLocale = getDefaultLocale(rootElement);
192    
193                    ddmForm.setDefaultLocale(defaultLocale);
194            }
195    
196            protected void setDDMFormFieldDataType(
197                    Element dynamicElementElement, DDMFormField ddmFormField) {
198    
199                    String dataType = dynamicElementElement.attributeValue("dataType");
200    
201                    ddmFormField.setDataType(dataType);
202            }
203    
204            protected void setDDMFormFieldIndexType(
205                    Element dynamicElementElement, DDMFormField ddmFormField) {
206    
207                    String indexType = dynamicElementElement.attributeValue("indexType");
208    
209                    ddmFormField.setIndexType(indexType);
210            }
211    
212            protected void setDDMFormFieldLocalizable(
213                    Element dynamicElementElement, DDMFormField ddmFormField) {
214    
215                    boolean localizable = GetterUtil.getBoolean(
216                            dynamicElementElement.attributeValue("localizable"), true);
217    
218                    ddmFormField.setLocalizable(localizable);
219            }
220    
221            protected void setDDMFormFieldLocalizedValueDefaultLocale(
222                    LocalizedValue localizedValue, Locale defaultLocale) {
223    
224                    if (localizedValue == null) {
225                            return;
226                    }
227    
228                    localizedValue.setDefaultLocale(defaultLocale);
229            }
230    
231            protected void setDDMFormFieldLocalizedValuesDefaultLocale(
232                    DDMFormField ddmFormField, Locale defaultLocale) {
233    
234                    setDDMFormFieldLocalizedValueDefaultLocale(
235                            ddmFormField.getLabel(), defaultLocale);
236    
237                    setDDMFormFieldLocalizedValueDefaultLocale(
238                            ddmFormField.getPredefinedValue(), defaultLocale);
239    
240                    setDDMFormFieldLocalizedValueDefaultLocale(
241                            ddmFormField.getStyle(), defaultLocale);
242    
243                    setDDMFormFieldLocalizedValueDefaultLocale(
244                            ddmFormField.getTip(), defaultLocale);
245    
246                    DDMFormFieldOptions ddmFormFieldOptions =
247                            ddmFormField.getDDMFormFieldOptions();
248    
249                    if (ddmFormFieldOptions != null) {
250                            ddmFormFieldOptions.setDefaultLocale(defaultLocale);
251                    }
252    
253                    for (DDMFormField nestedDDMFormField :
254                                    ddmFormField.getNestedDDMFormFields()) {
255    
256                            setDDMFormFieldLocalizedValuesDefaultLocale(
257                                    nestedDDMFormField, defaultLocale);
258                    }
259            }
260    
261            protected void setDDMFormFieldMetadata(
262                    Element metadataElement, DDMFormField ddmFormField) {
263    
264                    String languageId = metadataElement.attributeValue("locale");
265    
266                    Locale locale = LocaleUtil.fromLanguageId(languageId);
267    
268                    Element labelElement = fetchMetadataEntry(metadataElement, "label");
269    
270                    if (labelElement != null) {
271                            LocalizedValue label = ddmFormField.getLabel();
272    
273                            label.addString(locale, labelElement.getText());
274                    }
275    
276                    Element predefinedValueElement = fetchMetadataEntry(
277                            metadataElement, "predefinedValue");
278    
279                    if (predefinedValueElement != null) {
280                            LocalizedValue predefinedValue = ddmFormField.getPredefinedValue();
281    
282                            predefinedValue.addString(locale, predefinedValueElement.getText());
283                    }
284    
285                    Element styleElement = fetchMetadataEntry(metadataElement, "style");
286    
287                    if (styleElement != null) {
288                            LocalizedValue style = ddmFormField.getStyle();
289    
290                            style.addString(locale, styleElement.getText());
291                    }
292    
293                    Element tipElement = fetchMetadataEntry(metadataElement, "tip");
294    
295                    if (tipElement != null) {
296                            LocalizedValue tip = ddmFormField.getTip();
297    
298                            tip.addString(locale, tipElement.getText());
299                    }
300            }
301    
302            protected void setDDMFormFieldMultiple(
303                    Element dynamicElementElement, DDMFormField ddmFormField) {
304    
305                    boolean multiple = GetterUtil.getBoolean(
306                            dynamicElementElement.attributeValue("multiple"));
307    
308                    ddmFormField.setMultiple(multiple);
309            }
310    
311            protected void setDDMFormFieldNamespace(
312                    Element dynamicElementElement, DDMFormField ddmFormField) {
313    
314                    String fieldNamespace = dynamicElementElement.attributeValue(
315                            "fieldNamespace");
316    
317                    ddmFormField.setFieldNamespace(fieldNamespace);
318            }
319    
320            protected void setDDMFormFieldOptions(
321                    Element dynamicElementElement, DDMFormField ddmFormField) {
322    
323                    DDMFormFieldOptions ddmFormFieldOptions = getDDMFormFieldOptions(
324                            dynamicElementElement.elements("dynamic-element"));
325    
326                    ddmFormField.setDDMFormFieldOptions(ddmFormFieldOptions);
327            }
328    
329            protected void setDDMFormFieldReadOnly(
330                    Element dynamicElementElement, DDMFormField ddmFormField) {
331    
332                    boolean readOnly = GetterUtil.getBoolean(
333                            dynamicElementElement.attributeValue("readOnly"));
334    
335                    ddmFormField.setReadOnly(readOnly);
336            }
337    
338            protected void setDDMFormFieldRepeatable(
339                    Element dynamicElementElement, DDMFormField ddmFormField) {
340    
341                    boolean repeatable = GetterUtil.getBoolean(
342                            dynamicElementElement.attributeValue("repeatable"));
343    
344                    ddmFormField.setRepeatable(repeatable);
345            }
346    
347            protected void setDDMFormFieldRequired(
348                    Element dynamicElementElement, DDMFormField ddmFormField) {
349    
350                    boolean required = GetterUtil.getBoolean(
351                            dynamicElementElement.attributeValue("required"));
352    
353                    ddmFormField.setRequired(required);
354            }
355    
356            protected void setDDMFormFields(Element rootElement, DDMForm ddmForm) {
357                    List<DDMFormField> ddmFormFields = getDDMFormFields(rootElement);
358    
359                    ddmForm.setDDMFormFields(ddmFormFields);
360            }
361    
362            protected void setDDMFormFieldShowLabel(
363                    Element dynamicElementElement, DDMFormField ddmFormField) {
364    
365                    boolean showLabel = GetterUtil.getBoolean(
366                            dynamicElementElement.attributeValue("showLabel"), true);
367    
368                    ddmFormField.setShowLabel(showLabel);
369            }
370    
371            protected void setDDMFormLocalizedValuesDefaultLocale(DDMForm ddmForm) {
372                    for (DDMFormField ddmFormField : ddmForm.getDDMFormFields()) {
373                            setDDMFormFieldLocalizedValuesDefaultLocale(
374                                    ddmFormField, ddmForm.getDefaultLocale());
375                    }
376            }
377    
378            protected void setNestedDDMFormField(
379                    Element dynamicElementElement, DDMFormField ddmFormField) {
380    
381                    List<DDMFormField> nestedDDMFormFields = getDDMFormFields(
382                            dynamicElementElement);
383    
384                    ddmFormField.setNestedDDMFormFields(nestedDDMFormFields);
385            }
386    
387    }