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.model.impl;
016    
017    import com.liferay.portal.LocaleException;
018    import com.liferay.portal.kernel.bean.BeanPropertiesUtil;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.util.ListUtil;
023    import com.liferay.portal.kernel.util.LocaleUtil;
024    import com.liferay.portal.kernel.util.PredicateFilter;
025    import com.liferay.portal.kernel.util.SetUtil;
026    import com.liferay.portal.kernel.util.StringBundler;
027    import com.liferay.portal.kernel.util.StringPool;
028    import com.liferay.portal.kernel.util.Validator;
029    import com.liferay.portal.model.CacheField;
030    import com.liferay.portal.model.Group;
031    import com.liferay.portal.service.GroupLocalServiceUtil;
032    import com.liferay.portal.theme.ThemeDisplay;
033    import com.liferay.portal.util.PortalUtil;
034    import com.liferay.portal.util.PropsValues;
035    import com.liferay.portlet.dynamicdatamapping.StructureFieldException;
036    import com.liferay.portlet.dynamicdatamapping.io.DDMFormJSONDeserializerUtil;
037    import com.liferay.portlet.dynamicdatamapping.io.DDMFormJSONSerializerUtil;
038    import com.liferay.portlet.dynamicdatamapping.model.DDMForm;
039    import com.liferay.portlet.dynamicdatamapping.model.DDMFormField;
040    import com.liferay.portlet.dynamicdatamapping.model.DDMFormLayout;
041    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
042    import com.liferay.portlet.dynamicdatamapping.model.DDMStructureLayout;
043    import com.liferay.portlet.dynamicdatamapping.model.DDMStructureVersion;
044    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
045    import com.liferay.portlet.dynamicdatamapping.model.LocalizedValue;
046    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLayoutLocalServiceUtil;
047    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
048    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureVersionLocalServiceUtil;
049    import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
050    import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
051    
052    import java.util.ArrayList;
053    import java.util.List;
054    import java.util.Locale;
055    import java.util.Map;
056    import java.util.Set;
057    
058    /**
059     * @author Brian Wing Shun Chan
060     */
061    public class DDMStructureImpl extends DDMStructureBaseImpl {
062    
063            @Override
064            public DDMForm createFullHierarchyDDMForm() throws PortalException {
065                    DDMForm fullHierarchyDDMForm = DDMFormJSONDeserializerUtil.deserialize(
066                            getDefinition());
067    
068                    DDMStructure parentDDMStructure = getParentDDMStructure();
069    
070                    if (parentDDMStructure != null) {
071                            DDMForm ancestorsDDMForm =
072                                    parentDDMStructure.createFullHierarchyDDMForm();
073    
074                            List<DDMFormField> ddmFormFields =
075                                    fullHierarchyDDMForm.getDDMFormFields();
076    
077                            ddmFormFields.addAll(ancestorsDDMForm.getDDMFormFields());
078                    }
079    
080                    return fullHierarchyDDMForm;
081            }
082    
083            @Override
084            public String[] getAvailableLanguageIds() {
085                    DDMForm ddmForm = getDDMForm();
086    
087                    Set<Locale> availableLocales = ddmForm.getAvailableLocales();
088    
089                    return LocaleUtil.toLanguageIds(
090                            availableLocales.toArray(new Locale[availableLocales.size()]));
091            }
092    
093            @Override
094            public List<String> getChildrenFieldNames(String fieldName)
095                    throws PortalException {
096    
097                    DDMFormField ddmFormField = getDDMFormField(fieldName);
098    
099                    return getDDMFormFieldNames(ddmFormField.getNestedDDMFormFields());
100            }
101    
102            @Override
103            public DDMForm getDDMForm() {
104                    if (_ddmForm == null) {
105                            try {
106                                    _ddmForm = DDMFormJSONDeserializerUtil.deserialize(
107                                            getDefinition());
108                            }
109                            catch (Exception e) {
110                                    _log.error(e, e);
111                            }
112                    }
113    
114                    return new DDMForm(_ddmForm);
115            }
116    
117            @Override
118            public DDMFormField getDDMFormField(String fieldName)
119                    throws PortalException {
120    
121                    Map<String, DDMFormField> ddmFormFieldsMap =
122                            getFullHierarchyDDMFormFieldsMap(true);
123    
124                    DDMFormField ddmFormField = ddmFormFieldsMap.get(fieldName);
125    
126                    if (ddmFormField == null) {
127                            throw new StructureFieldException(
128                                    "Unable to find field " + fieldName);
129                    }
130    
131                    return ddmFormField;
132            }
133    
134            @Override
135            public List<DDMFormField> getDDMFormFields(boolean includeTransientFields) {
136                    Map<String, DDMFormField> ddmFormFieldsMap =
137                            getFullHierarchyDDMFormFieldsMap(true);
138    
139                    List<DDMFormField> ddmFormFields = new ArrayList<>(
140                            ddmFormFieldsMap.values());
141    
142                    if (includeTransientFields) {
143                            return ddmFormFields;
144                    }
145    
146                    return filterTransientDDMFormFields(ddmFormFields);
147            }
148    
149            @Override
150            public DDMFormLayout getDDMFormLayout() throws PortalException {
151                    DDMStructureVersion structureVersion = getStructureVersion();
152    
153                    DDMStructureLayout ddmStructureLayout =
154                            DDMStructureLayoutLocalServiceUtil.
155                                    getStructureLayoutByStructureVersionId(
156                                            structureVersion.getStructureVersionId());
157    
158                    return ddmStructureLayout.getDDMFormLayout();
159            }
160    
161            @Override
162            public String getDefaultLanguageId() {
163                    DDMForm ddmForm = getDDMForm();
164    
165                    return LocaleUtil.toLanguageId(ddmForm.getDefaultLocale());
166            }
167    
168            @Override
169            public String getFieldDataType(String fieldName) throws PortalException {
170                    DDMFormField ddmFormField = getDDMFormField(fieldName);
171    
172                    return ddmFormField.getDataType();
173            }
174    
175            @Override
176            public String getFieldLabel(String fieldName, Locale locale)
177                    throws PortalException {
178    
179                    DDMFormField ddmFormField = getDDMFormField(fieldName);
180    
181                    LocalizedValue label = ddmFormField.getLabel();
182    
183                    return label.getString(locale);
184            }
185    
186            @Override
187            public String getFieldLabel(String fieldName, String locale)
188                    throws PortalException {
189    
190                    return getFieldLabel(fieldName, LocaleUtil.fromLanguageId(locale));
191            }
192    
193            @Override
194            public Set<String> getFieldNames() {
195                    List<DDMFormField> ddmFormFields = getDDMFormFields(false);
196    
197                    List<String> ddmFormFieldNames = getDDMFormFieldNames(ddmFormFields);
198    
199                    return SetUtil.fromList(ddmFormFieldNames);
200            }
201    
202            @Override
203            public String getFieldProperty(String fieldName, String property)
204                    throws PortalException {
205    
206                    DDMFormField ddmFormField = getDDMFormField(fieldName);
207    
208                    return BeanPropertiesUtil.getString(ddmFormField, property);
209            }
210    
211            @Override
212            public boolean getFieldRepeatable(String fieldName) throws PortalException {
213                    DDMFormField ddmFormField = getDDMFormField(fieldName);
214    
215                    return ddmFormField.isRepeatable();
216            }
217    
218            @Override
219            public boolean getFieldRequired(String fieldName) throws PortalException {
220                    DDMFormField ddmFormField = getDDMFormField(fieldName);
221    
222                    return ddmFormField.isRequired();
223            }
224    
225            @Override
226            public String getFieldTip(String fieldName, Locale locale)
227                    throws PortalException {
228    
229                    DDMFormField ddmFormField = getDDMFormField(fieldName);
230    
231                    LocalizedValue tip = ddmFormField.getTip();
232    
233                    return tip.getString(locale);
234            }
235    
236            @Override
237            public String getFieldTip(String fieldName, String locale)
238                    throws PortalException {
239    
240                    return getFieldTip(fieldName, LocaleUtil.fromLanguageId(locale));
241            }
242    
243            @Override
244            public String getFieldType(String fieldName) throws PortalException {
245                    DDMFormField ddmFormField = getDDMFormField(fieldName);
246    
247                    return ddmFormField.getType();
248            }
249    
250            @Override
251            public DDMForm getFullHierarchyDDMForm() {
252                    if (_fullHierarchyDDMForm == null) {
253                            try {
254                                    _fullHierarchyDDMForm = createFullHierarchyDDMForm();
255                            }
256                            catch (Exception e) {
257                                    _log.error(e, e);
258                            }
259                    }
260    
261                    return new DDMForm(_fullHierarchyDDMForm);
262            }
263    
264            @Override
265            public Map<String, DDMFormField> getFullHierarchyDDMFormFieldsMap(
266                    boolean includeNestedDDMFormFields) {
267    
268                    DDMForm ddmForm = getFullHierarchyDDMForm();
269    
270                    return ddmForm.getDDMFormFieldsMap(includeNestedDDMFormFields);
271            }
272    
273            @Override
274            public List<String> getRootFieldNames() {
275                    DDMForm ddmForm = getFullHierarchyDDMForm();
276    
277                    return getDDMFormFieldNames(ddmForm.getDDMFormFields());
278            }
279    
280            @Override
281            public DDMStructureVersion getStructureVersion() throws PortalException {
282                    return DDMStructureVersionLocalServiceUtil.getStructureVersion(
283                            getStructureId(), getVersion());
284            }
285    
286            @Override
287            public List<DDMTemplate> getTemplates() {
288                    return DDMTemplateLocalServiceUtil.getTemplates(getStructureId());
289            }
290    
291            @Override
292            public String getUnambiguousName(
293                            List<DDMStructure> structures, long groupId, final Locale locale)
294                    throws PortalException {
295    
296                    if (getGroupId() == groupId ) {
297                            return getName(locale);
298                    }
299    
300                    boolean hasAmbiguousName = ListUtil.exists(
301                            structures,
302                            new PredicateFilter<DDMStructure>() {
303    
304                                    @Override
305                                    public boolean filter(DDMStructure structure) {
306                                            String name = structure.getName(locale);
307    
308                                            if (name.equals(getName(locale)) &&
309                                                    (structure.getStructureId() != getStructureId())) {
310    
311                                                    return true;
312                                            }
313    
314                                            return false;
315                                    }
316    
317                            });
318    
319                    if (hasAmbiguousName) {
320                            Group group = GroupLocalServiceUtil.getGroup(getGroupId());
321    
322                            return group.getUnambiguousName(getName(locale), locale);
323                    }
324    
325                    return getName(locale);
326            }
327    
328            /**
329             * Returns the WebDAV URL to access the structure.
330             *
331             * @param  themeDisplay the theme display needed to build the URL. It can
332             *         set HTTPS access, the server name, the server port, the path
333             *         context, and the scope group.
334             * @param  webDAVToken the WebDAV token for the URL
335             * @return the WebDAV URL
336             */
337            @Override
338            public String getWebDavURL(ThemeDisplay themeDisplay, String webDAVToken) {
339                    StringBundler sb = new StringBundler(11);
340    
341                    boolean secure = false;
342    
343                    if (themeDisplay.isSecure() ||
344                            PropsValues.WEBDAV_SERVLET_HTTPS_REQUIRED) {
345    
346                            secure = true;
347                    }
348    
349                    String portalURL = PortalUtil.getPortalURL(
350                            themeDisplay.getServerName(), themeDisplay.getServerPort(), secure);
351    
352                    sb.append(portalURL);
353    
354                    sb.append(themeDisplay.getPathContext());
355                    sb.append(StringPool.SLASH);
356                    sb.append("webdav");
357    
358                    Group group = themeDisplay.getScopeGroup();
359    
360                    sb.append(group.getFriendlyURL());
361    
362                    sb.append(StringPool.SLASH);
363                    sb.append(webDAVToken);
364                    sb.append(StringPool.SLASH);
365                    sb.append("Structures");
366                    sb.append(StringPool.SLASH);
367                    sb.append(getStructureId());
368    
369                    return sb.toString();
370            }
371    
372            @Override
373            public boolean hasField(String fieldName) {
374                    Map<String, DDMFormField> ddmFormFieldsMap =
375                            getFullHierarchyDDMFormFieldsMap(true);
376    
377                    return ddmFormFieldsMap.containsKey(fieldName);
378            }
379    
380            @Override
381            public boolean isFieldRepeatable(String fieldName) throws PortalException {
382                    DDMFormField ddmFormField = getDDMFormField(fieldName);
383    
384                    return ddmFormField.isRepeatable();
385            }
386    
387            @Override
388            public boolean isFieldTransient(String fieldName) throws PortalException {
389                    DDMFormField ddmFormField = getDDMFormField(fieldName);
390    
391                    if (Validator.isNull(ddmFormField.getDataType())) {
392                            return true;
393                    }
394    
395                    return false;
396            }
397    
398            @Override
399            public void prepareLocalizedFieldsForImport(Locale defaultImportLocale)
400                    throws LocaleException {
401    
402                    super.prepareLocalizedFieldsForImport(defaultImportLocale);
403    
404                    Locale ddmStructureDefaultLocale = LocaleUtil.fromLanguageId(
405                            getDefaultLanguageId());
406    
407                    try {
408                            setDefinition(
409                                    DDMXMLUtil.updateXMLDefaultLocale(
410                                            getDefinition(), ddmStructureDefaultLocale,
411                                            defaultImportLocale));
412                    }
413                    catch (Exception e) {
414                            throw new LocaleException(LocaleException.TYPE_EXPORT_IMPORT, e);
415                    }
416            }
417    
418            @Override
419            public void setDDMForm(DDMForm ddmForm) {
420                    _ddmForm = ddmForm;
421            }
422    
423            @Override
424            public void setDefinition(String definition) {
425                    super.setDefinition(definition);
426    
427                    _ddmForm = null;
428                    _fullHierarchyDDMForm = null;
429            }
430    
431            @Override
432            public void setFullHierarchyDDMForm(DDMForm fullHierarchyDDMForm) {
433                    _fullHierarchyDDMForm = fullHierarchyDDMForm;
434            }
435    
436            @Override
437            public void updateDDMForm(DDMForm ddmForm) {
438                    setDefinition(DDMFormJSONSerializerUtil.serialize(ddmForm));
439            }
440    
441            protected List<DDMFormField> filterTransientDDMFormFields(
442                    List<DDMFormField> ddmFormFields) {
443    
444                    PredicateFilter<DDMFormField> predicateFilter =
445                            new PredicateFilter<DDMFormField>() {
446    
447                                    @Override
448                                    public boolean filter(DDMFormField ddmFormField) {
449                                            if (Validator.isNull(ddmFormField.getDataType())) {
450                                                    return false;
451                                            }
452    
453                                            return true;
454                                    }
455                            };
456    
457                    return ListUtil.filter(ddmFormFields, predicateFilter);
458            }
459    
460            protected List<String> getDDMFormFieldNames(
461                    List<DDMFormField> ddmFormFields) {
462    
463                    List<String> fieldNames = new ArrayList<>();
464    
465                    for (DDMFormField ddmFormField : ddmFormFields) {
466                            fieldNames.add(ddmFormField.getName());
467                    }
468    
469                    return fieldNames;
470            }
471    
472            protected DDMStructure getParentDDMStructure() throws PortalException {
473                    if (getParentStructureId() == 0) {
474                            return null;
475                    }
476    
477                    DDMStructure parentStructure =
478                            DDMStructureLocalServiceUtil.getStructure(getParentStructureId());
479    
480                    return parentStructure;
481            }
482    
483            private static final Log _log = LogFactoryUtil.getLog(
484                    DDMStructureImpl.class);
485    
486            @CacheField(methodName = "DDMForm")
487            private DDMForm _ddmForm;
488    
489            @CacheField(methodName = "FullHierarchyDDMForm")
490            private DDMForm _fullHierarchyDDMForm;
491    
492    }