001    /**
002     * Copyright (c) 2000-2013 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.util;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.json.JSONArray;
020    import com.liferay.portal.kernel.json.JSONFactoryUtil;
021    import com.liferay.portal.kernel.json.JSONObject;
022    import com.liferay.portal.kernel.language.LanguageUtil;
023    import com.liferay.portal.kernel.repository.model.FileEntry;
024    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
025    import com.liferay.portal.kernel.upload.UploadRequest;
026    import com.liferay.portal.kernel.util.ArrayUtil;
027    import com.liferay.portal.kernel.util.DateFormatFactoryUtil;
028    import com.liferay.portal.kernel.util.FileUtil;
029    import com.liferay.portal.kernel.util.GetterUtil;
030    import com.liferay.portal.kernel.util.HttpUtil;
031    import com.liferay.portal.kernel.util.ListUtil;
032    import com.liferay.portal.kernel.util.LocaleUtil;
033    import com.liferay.portal.kernel.util.OrderByComparator;
034    import com.liferay.portal.kernel.util.StringPool;
035    import com.liferay.portal.kernel.util.StringUtil;
036    import com.liferay.portal.kernel.util.UnicodeFormatter;
037    import com.liferay.portal.kernel.util.Validator;
038    import com.liferay.portal.model.Image;
039    import com.liferay.portal.model.Layout;
040    import com.liferay.portal.service.ImageLocalServiceUtil;
041    import com.liferay.portal.service.LayoutLocalServiceUtil;
042    import com.liferay.portal.service.ServiceContext;
043    import com.liferay.portal.theme.ThemeDisplay;
044    import com.liferay.portal.util.PortalUtil;
045    import com.liferay.portal.util.PropsValues;
046    import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
047    import com.liferay.portlet.documentlibrary.util.DLUtil;
048    import com.liferay.portlet.dynamicdatamapping.NoSuchTemplateException;
049    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
050    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
051    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
052    import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
053    import com.liferay.portlet.dynamicdatamapping.storage.Field;
054    import com.liferay.portlet.dynamicdatamapping.storage.FieldConstants;
055    import com.liferay.portlet.dynamicdatamapping.storage.Fields;
056    import com.liferay.portlet.dynamicdatamapping.util.comparator.StructureIdComparator;
057    import com.liferay.portlet.dynamicdatamapping.util.comparator.StructureModifiedDateComparator;
058    import com.liferay.portlet.dynamicdatamapping.util.comparator.TemplateIdComparator;
059    import com.liferay.portlet.dynamicdatamapping.util.comparator.TemplateModifiedDateComparator;
060    
061    import java.io.File;
062    import java.io.Serializable;
063    
064    import java.text.DateFormat;
065    
066    import java.util.ArrayList;
067    import java.util.Date;
068    import java.util.Iterator;
069    import java.util.List;
070    import java.util.Locale;
071    import java.util.Set;
072    
073    import javax.servlet.http.HttpServletRequest;
074    
075    /**
076     * @author Eduardo Lundgren
077     * @author Brian Wing Shun Chan
078     * @author Eduardo Garcia
079     * @author Marcellus Tavares
080     */
081    @DoPrivileged
082    public class DDMImpl implements DDM {
083    
084            public static final String FIELDS_DISPLAY_NAME = "_fieldsDisplay";
085    
086            public static final String INSTANCE_SEPARATOR = "_INSTANCE_";
087    
088            public static final String TYPE_CHECKBOX = "checkbox";
089    
090            public static final String TYPE_DDM_DATE = "ddm-date";
091    
092            public static final String TYPE_DDM_DOCUMENTLIBRARY = "ddm-documentlibrary";
093    
094            public static final String TYPE_DDM_IMAGE = "ddm-image";
095    
096            public static final String TYPE_DDM_LINK_TO_PAGE = "ddm-link-to-page";
097    
098            public static final String TYPE_DDM_TEXT_HTML = "ddm-text-html";
099    
100            public static final String TYPE_RADIO = "radio";
101    
102            public static final String TYPE_SELECT = "select";
103    
104            @Override
105            public DDMDisplay getDDMDisplay(ServiceContext serviceContext) {
106                    String refererPortletName = (String)serviceContext.getAttribute(
107                            "refererPortletName");
108    
109                    if (refererPortletName == null) {
110                            refererPortletName = serviceContext.getPortletId();
111                    }
112    
113                    return DDMDisplayRegistryUtil.getDDMDisplay(refererPortletName);
114            }
115    
116            @Override
117            public Serializable getDisplayFieldValue(
118                            ThemeDisplay themeDisplay, Serializable fieldValue, String type)
119                    throws Exception {
120    
121                    if (fieldValue instanceof Date) {
122                            Date valueDate = (Date)fieldValue;
123    
124                            DateFormat dateFormat = DateFormatFactoryUtil.getDate(
125                                    themeDisplay.getLocale());
126    
127                            fieldValue = dateFormat.format(valueDate);
128                    }
129                    else if (type.equals(DDMImpl.TYPE_CHECKBOX)) {
130                            Boolean valueBoolean = (Boolean)fieldValue;
131    
132                            if (valueBoolean) {
133                                    fieldValue = LanguageUtil.get(themeDisplay.getLocale(), "yes");
134                            }
135                            else {
136                                    fieldValue = LanguageUtil.get(themeDisplay.getLocale(), "no");
137                            }
138                    }
139                    else if (type.equals(DDMImpl.TYPE_DDM_DOCUMENTLIBRARY)) {
140                            if (Validator.isNull(fieldValue)) {
141                                    return StringPool.BLANK;
142                            }
143    
144                            String valueString = String.valueOf(fieldValue);
145    
146                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject(
147                                    valueString);
148    
149                            String uuid = jsonObject.getString("uuid");
150                            long groupId = jsonObject.getLong("groupId");
151    
152                            FileEntry fileEntry =
153                                    DLAppLocalServiceUtil.getFileEntryByUuidAndGroupId(
154                                            uuid, groupId);
155    
156                            fieldValue = DLUtil.getPreviewURL(
157                                    fileEntry, fileEntry.getFileVersion(), null, StringPool.BLANK,
158                                    false, true);
159                    }
160                    else if (type.equals(DDMImpl.TYPE_DDM_LINK_TO_PAGE)) {
161                            if (Validator.isNull(fieldValue)) {
162                                    return StringPool.BLANK;
163                            }
164    
165                            String valueString = String.valueOf(fieldValue);
166    
167                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject(
168                                    valueString);
169    
170                            long groupId = jsonObject.getLong("groupId");
171                            boolean privateLayout = jsonObject.getBoolean("privateLayout");
172                            long layoutId = jsonObject.getLong("layoutId");
173    
174                            Layout layout = LayoutLocalServiceUtil.getLayout(
175                                    groupId, privateLayout, layoutId);
176    
177                            fieldValue = PortalUtil.getLayoutFriendlyURL(layout, themeDisplay);
178                    }
179                    else if (type.equals(DDMImpl.TYPE_RADIO) ||
180                                     type.equals(DDMImpl.TYPE_SELECT)) {
181    
182                            String valueString = String.valueOf(fieldValue);
183    
184                            JSONArray jsonArray = JSONFactoryUtil.createJSONArray(valueString);
185    
186                            String[] stringArray = ArrayUtil.toStringArray(jsonArray);
187    
188                            fieldValue = stringArray[0];
189                    }
190    
191                    return fieldValue;
192            }
193    
194            @Override
195            public Fields getFields(
196                            long ddmStructureId, long ddmTemplateId,
197                            ServiceContext serviceContext)
198                    throws PortalException, SystemException {
199    
200                    return getFields(
201                            ddmStructureId, ddmTemplateId, StringPool.BLANK, serviceContext);
202            }
203    
204            @Override
205            public Fields getFields(
206                            long ddmStructureId, long ddmTemplateId, String fieldNamespace,
207                            ServiceContext serviceContext)
208                    throws PortalException, SystemException {
209    
210                    DDMStructure ddmStructure = getDDMStructure(
211                            ddmStructureId, ddmTemplateId);
212    
213                    Set<String> fieldNames = ddmStructure.getFieldNames();
214    
215                    boolean translating = true;
216    
217                    String defaultLanguageId = (String)serviceContext.getAttribute(
218                            "defaultLanguageId");
219                    String toLanguageId = (String)serviceContext.getAttribute(
220                            "toLanguageId");
221    
222                    if (Validator.isNull(toLanguageId) ||
223                            Validator.equals(defaultLanguageId, toLanguageId)) {
224    
225                            translating = false;
226                    }
227    
228                    Fields fields = new Fields();
229    
230                    for (String fieldName : fieldNames) {
231                            boolean localizable = GetterUtil.getBoolean(
232                                    ddmStructure.getFieldProperty(fieldName, "localizable"), true);
233    
234                            if (!localizable && translating) {
235                                    continue;
236                            }
237    
238                            List<Serializable> fieldValues = getFieldValues(
239                                    ddmStructure, fieldName, fieldNamespace, serviceContext);
240    
241                            if ((fieldValues == null) || fieldValues.isEmpty()) {
242                                    continue;
243                            }
244    
245                            Field field = createField(
246                                    ddmStructure, fieldName, fieldValues, serviceContext);
247    
248                            fields.put(field);
249                    }
250    
251                    return fields;
252            }
253    
254            @Override
255            public Fields getFields(long ddmStructureId, ServiceContext serviceContext)
256                    throws PortalException, SystemException {
257    
258                    return getFields(ddmStructureId, 0, serviceContext);
259            }
260    
261            @Override
262            public Fields getFields(
263                            long ddmStructureId, String fieldNamespace,
264                            ServiceContext serviceContext)
265                    throws PortalException, SystemException {
266    
267                    return getFields(ddmStructureId, 0, fieldNamespace, serviceContext);
268            }
269    
270            @Override
271            public String[] getFieldsDisplayValues(Field fieldsDisplayField)
272                    throws Exception {
273    
274                    DDMStructure ddmStructure = fieldsDisplayField.getDDMStructure();
275    
276                    List<String> fieldsDisplayValues = new ArrayList<String>();
277    
278                    String[] values = StringUtil.split(
279                            (String)fieldsDisplayField.getValue());
280    
281                    for (String value : values) {
282                            String fieldName = StringUtil.extractFirst(
283                                    value, DDMImpl.INSTANCE_SEPARATOR);
284    
285                            if (ddmStructure.hasField(fieldName)) {
286                                    fieldsDisplayValues.add(fieldName);
287                            }
288                    }
289    
290                    return fieldsDisplayValues.toArray(
291                            new String[fieldsDisplayValues.size()]);
292            }
293    
294            @Override
295            public Serializable getIndexedFieldValue(
296                            Serializable fieldValue, String type)
297                    throws Exception {
298    
299                    if (fieldValue instanceof Date) {
300                            Date valueDate = (Date)fieldValue;
301    
302                            DateFormat dateFormat = DateFormatFactoryUtil.getSimpleDateFormat(
303                                    "yyyyMMddHHmmss");
304    
305                            fieldValue = dateFormat.format(valueDate);
306                    }
307                    else if (type.equals(DDMImpl.TYPE_RADIO) ||
308                                     type.equals(DDMImpl.TYPE_SELECT)) {
309    
310                            String valueString = (String)fieldValue;
311    
312                            JSONArray jsonArray = JSONFactoryUtil.createJSONArray(valueString);
313    
314                            String[] stringArray = ArrayUtil.toStringArray(jsonArray);
315    
316                            fieldValue = stringArray[0];
317                    }
318    
319                    return fieldValue;
320            }
321    
322            @Override
323            public OrderByComparator getStructureOrderByComparator(
324                    String orderByCol, String orderByType) {
325    
326                    boolean orderByAsc = false;
327    
328                    if (orderByType.equals("asc")) {
329                            orderByAsc = true;
330                    }
331    
332                    OrderByComparator orderByComparator = null;
333    
334                    if (orderByCol.equals("id")) {
335                            orderByComparator = new StructureIdComparator(orderByAsc);
336                    }
337                    else if (orderByCol.equals("modified-date")) {
338                            orderByComparator = new StructureModifiedDateComparator(orderByAsc);
339                    }
340    
341                    return orderByComparator;
342            }
343    
344            @Override
345            public OrderByComparator getTemplateOrderByComparator(
346                    String orderByCol, String orderByType) {
347    
348                    boolean orderByAsc = false;
349    
350                    if (orderByType.equals("asc")) {
351                            orderByAsc = true;
352                    }
353    
354                    OrderByComparator orderByComparator = null;
355    
356                    if (orderByCol.equals("id")) {
357                            orderByComparator = new TemplateIdComparator(orderByAsc);
358                    }
359                    else if (orderByCol.equals("modified-date")) {
360                            orderByComparator = new TemplateModifiedDateComparator(orderByAsc);
361                    }
362    
363                    return orderByComparator;
364            }
365    
366            @Override
367            public Fields mergeFields(Fields newFields, Fields existingFields) {
368                    Iterator<Field> itr = newFields.iterator(true);
369    
370                    while (itr.hasNext()) {
371                            Field newField = itr.next();
372    
373                            Field existingField = existingFields.get(newField.getName());
374    
375                            if (existingField == null) {
376                                    existingFields.put(newField);
377                            }
378                            else {
379                                    for (Locale locale : newField.getAvailableLocales()) {
380                                            existingField.setValues(locale, newField.getValues(locale));
381                                    }
382    
383                                    existingField.setDefaultLocale(newField.getDefaultLocale());
384                            }
385                    }
386    
387                    return existingFields;
388            }
389    
390            protected Field createField(
391                            DDMStructure ddmStructure, String fieldName,
392                            List<Serializable> fieldValues, ServiceContext serviceContext)
393                    throws PortalException, SystemException {
394    
395                    Field field = new Field();
396    
397                    field.setDDMStructureId(ddmStructure.getStructureId());
398    
399                    String languageId = GetterUtil.getString(
400                            serviceContext.getAttribute("languageId"),
401                            serviceContext.getLanguageId());
402    
403                    Locale locale = LocaleUtil.fromLanguageId(languageId);
404    
405                    String defaultLanguageId = GetterUtil.getString(
406                            serviceContext.getAttribute("defaultLanguageId"));
407    
408                    Locale defaultLocale = LocaleUtil.fromLanguageId(defaultLanguageId);
409    
410                    if (ddmStructure.isFieldPrivate(fieldName)) {
411                            locale = LocaleUtil.getSiteDefault();
412    
413                            defaultLocale = LocaleUtil.getSiteDefault();
414                    }
415    
416                    field.setDefaultLocale(defaultLocale);
417    
418                    field.setName(fieldName);
419                    field.setValues(locale, fieldValues);
420    
421                    return field;
422            }
423    
424            protected DDMStructure getDDMStructure(
425                            long ddmStructureId, long ddmTemplateId)
426                    throws PortalException, SystemException {
427    
428                    DDMStructure ddmStructure = DDMStructureLocalServiceUtil.getStructure(
429                            ddmStructureId);
430    
431                    try {
432                            DDMTemplate ddmTemplate = DDMTemplateLocalServiceUtil.getTemplate(
433                                    ddmTemplateId);
434    
435                            // Clone ddmStructure to make sure changes are never persisted
436    
437                            ddmStructure = (DDMStructure)ddmStructure.clone();
438    
439                            ddmStructure.setXsd(ddmTemplate.getScript());
440                    }
441                    catch (NoSuchTemplateException nste) {
442                    }
443    
444                    return ddmStructure;
445            }
446    
447            protected List<String> getFieldNames(
448                    String fieldNamespace, String fieldName,
449                    ServiceContext serviceContext) {
450    
451                    String[] fieldsDisplayValues = StringUtil.split(
452                            (String)serviceContext.getAttribute(
453                                    fieldNamespace + FIELDS_DISPLAY_NAME));
454    
455                    List<String> privateFieldNames = ListUtil.fromArray(
456                            PropsValues.DYNAMIC_DATA_MAPPING_STRUCTURE_PRIVATE_FIELD_NAMES);
457    
458                    List<String> fieldNames = new ArrayList<String>();
459    
460                    if ((fieldsDisplayValues.length == 0) ||
461                            privateFieldNames.contains(fieldName)) {
462    
463                            fieldNames.add(fieldNamespace + fieldName);
464                    }
465                    else {
466                            for (String namespacedFieldName : fieldsDisplayValues) {
467                                    String fieldNameValue = StringUtil.extractFirst(
468                                            namespacedFieldName, INSTANCE_SEPARATOR);
469    
470                                    if (fieldNameValue.equals(fieldName)) {
471                                            fieldNames.add(fieldNamespace + namespacedFieldName);
472                                    }
473                            }
474                    }
475    
476                    return fieldNames;
477            }
478    
479            protected List<Serializable> getFieldValues(
480                            DDMStructure ddmStructure, String fieldName, String fieldNamespace,
481                            ServiceContext serviceContext)
482                    throws PortalException, SystemException {
483    
484                    String fieldDataType = ddmStructure.getFieldDataType(fieldName);
485                    String fieldType = ddmStructure.getFieldType(fieldName);
486    
487                    List<String> fieldNames = getFieldNames(
488                            fieldNamespace, fieldName, serviceContext);
489    
490                    List<Serializable> fieldValues = new ArrayList<Serializable>(
491                            fieldNames.size());
492    
493                    for (String fieldNameValue : fieldNames) {
494                            Serializable fieldValue = serviceContext.getAttribute(
495                                    fieldNameValue);
496    
497                            if (fieldDataType.equals(FieldConstants.DATE)) {
498                                    int fieldValueMonth = GetterUtil.getInteger(
499                                            serviceContext.getAttribute(fieldNameValue + "Month"));
500                                    int fieldValueDay = GetterUtil.getInteger(
501                                            serviceContext.getAttribute(fieldNameValue + "Day"));
502                                    int fieldValueYear = GetterUtil.getInteger(
503                                            serviceContext.getAttribute(fieldNameValue + "Year"));
504    
505                                    String fieldValueDateString = GetterUtil.getString(
506                                            serviceContext.getAttribute(fieldNameValue));
507    
508                                    if (Validator.isNull(fieldValueDateString)) {
509                                            fieldValue = StringPool.BLANK;
510                                    }
511                                    else {
512                                            Date fieldValueDate = PortalUtil.getDate(
513                                                    fieldValueMonth, fieldValueDay, fieldValueYear);
514    
515                                            if (fieldValueDate != null) {
516                                                    fieldValue = String.valueOf(fieldValueDate.getTime());
517                                            }
518                                    }
519                            }
520                            else if (fieldDataType.equals(FieldConstants.IMAGE) &&
521                                             Validator.isNull(fieldValue)) {
522    
523                                    HttpServletRequest request = serviceContext.getRequest();
524    
525                                    if (!(request instanceof UploadRequest)) {
526                                            return null;
527                                    }
528    
529                                    fieldValue = getImageFieldValue(
530                                            (UploadRequest)request, fieldNameValue);
531                            }
532    
533                            if (fieldValue == null) {
534                                    return null;
535                            }
536    
537                            if (DDMImpl.TYPE_RADIO.equals(fieldType) ||
538                                    DDMImpl.TYPE_SELECT.equals(fieldType)) {
539    
540                                    if (fieldValue instanceof String) {
541                                            fieldValue = new String[] {String.valueOf(fieldValue)};
542                                    }
543    
544                                    fieldValue = JSONFactoryUtil.serialize(fieldValue);
545                            }
546    
547                            Serializable fieldValueSerializable =
548                                    FieldConstants.getSerializable(
549                                            fieldDataType, GetterUtil.getString(fieldValue));
550    
551                            fieldValues.add(fieldValueSerializable);
552                    }
553    
554                    return fieldValues;
555            }
556    
557            protected byte[] getImageBytes(
558                            UploadRequest uploadRequest, String fieldNameValue)
559                    throws Exception {
560    
561                    File file = uploadRequest.getFile(fieldNameValue);
562    
563                    byte[] bytes = FileUtil.getBytes(file);
564    
565                    if (ArrayUtil.isNotEmpty(bytes)) {
566                            return bytes;
567                    }
568    
569                    String url = uploadRequest.getParameter(fieldNameValue + "URL");
570    
571                    long imageId = GetterUtil.getLong(
572                            HttpUtil.getParameter(url, "img_id", false));
573    
574                    Image image = ImageLocalServiceUtil.fetchImage(imageId);
575    
576                    if (image == null) {
577                            return null;
578                    }
579    
580                    return image.getTextObj();
581            }
582    
583            protected String getImageFieldValue(
584                    UploadRequest uploadRequest, String fieldNameValue) {
585    
586                    try {
587                            byte[] bytes = getImageBytes(uploadRequest, fieldNameValue);
588    
589                            if (ArrayUtil.isNotEmpty(bytes)) {
590                                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
591    
592                                    jsonObject.put(
593                                            "alt", uploadRequest.getParameter(fieldNameValue + "Alt"));
594                                    jsonObject.put("data", UnicodeFormatter.bytesToHex(bytes));
595    
596                                    return jsonObject.toString();
597                            }
598                    }
599                    catch (Exception e) {
600                    }
601    
602                    return StringPool.BLANK;
603            }
604    
605    }