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