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.dynamicdatalists.util;
016    
017    import com.liferay.portal.kernel.json.JSONArray;
018    import com.liferay.portal.kernel.json.JSONFactoryUtil;
019    import com.liferay.portal.kernel.json.JSONObject;
020    import com.liferay.portal.kernel.language.LanguageUtil;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.repository.model.FileEntry;
024    import com.liferay.portal.kernel.search.Hits;
025    import com.liferay.portal.kernel.search.Indexer;
026    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
027    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
028    import com.liferay.portal.kernel.template.TemplateConstants;
029    import com.liferay.portal.kernel.util.Constants;
030    import com.liferay.portal.kernel.util.GetterUtil;
031    import com.liferay.portal.kernel.util.LocaleThreadLocal;
032    import com.liferay.portal.kernel.util.LocaleUtil;
033    import com.liferay.portal.kernel.util.ParamUtil;
034    import com.liferay.portal.kernel.util.PropsKeys;
035    import com.liferay.portal.kernel.util.StringPool;
036    import com.liferay.portal.kernel.util.Validator;
037    import com.liferay.portal.service.LayoutServiceUtil;
038    import com.liferay.portal.service.ServiceContext;
039    import com.liferay.portal.templateparser.Transformer;
040    import com.liferay.portal.theme.ThemeDisplay;
041    import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
042    import com.liferay.portlet.dynamicdatalists.NoSuchRecordException;
043    import com.liferay.portlet.dynamicdatalists.model.DDLRecord;
044    import com.liferay.portlet.dynamicdatalists.model.DDLRecordConstants;
045    import com.liferay.portlet.dynamicdatalists.model.DDLRecordSet;
046    import com.liferay.portlet.dynamicdatalists.model.DDLRecordVersion;
047    import com.liferay.portlet.dynamicdatalists.service.DDLRecordLocalServiceUtil;
048    import com.liferay.portlet.dynamicdatalists.service.DDLRecordServiceUtil;
049    import com.liferay.portlet.dynamicdatalists.service.DDLRecordSetLocalServiceUtil;
050    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
051    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
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.storage.StorageEngineUtil;
057    import com.liferay.portlet.dynamicdatamapping.util.DDMImpl;
058    import com.liferay.portlet.dynamicdatamapping.util.DDMUtil;
059    
060    import java.util.ArrayList;
061    import java.util.Date;
062    import java.util.HashMap;
063    import java.util.List;
064    import java.util.Locale;
065    import java.util.Map;
066    
067    import javax.portlet.PortletPreferences;
068    import javax.portlet.RenderRequest;
069    import javax.portlet.RenderResponse;
070    
071    import javax.servlet.http.HttpServletRequest;
072    
073    /**
074     * @author Marcellus Tavares
075     * @author Eduardo Lundgren
076     */
077    @DoPrivileged
078    public class DDLImpl implements DDL {
079    
080            @Override
081            public JSONObject getRecordJSONObject(DDLRecord record) throws Exception {
082                    return getRecordJSONObject(record, false);
083            }
084    
085            @Override
086            public JSONObject getRecordJSONObject(
087                            DDLRecord record, boolean latestRecordVersion)
088                    throws Exception {
089    
090                    DDLRecordSet recordSet = record.getRecordSet();
091    
092                    DDMStructure ddmStructure = recordSet.getDDMStructure();
093    
094                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
095    
096                    for (String fieldName : ddmStructure.getFieldNames()) {
097                            jsonObject.put(fieldName, StringPool.BLANK);
098                    }
099    
100                    jsonObject.put("displayIndex", record.getDisplayIndex());
101                    jsonObject.put("recordId", record.getRecordId());
102    
103                    DDLRecordVersion recordVersion = record.getRecordVersion();
104    
105                    if (latestRecordVersion) {
106                            recordVersion = record.getLatestRecordVersion();
107                    }
108    
109                    Fields fields = StorageEngineUtil.getFields(
110                            recordVersion.getDDMStorageId());
111    
112                    for (Field field : fields) {
113                            String fieldName = field.getName();
114                            String fieldType = field.getType();
115                            Object fieldValue = field.getValue();
116    
117                            if (fieldValue instanceof Date) {
118                                    jsonObject.put(fieldName, ((Date)fieldValue).getTime());
119                            }
120                            else if (fieldType.equals(DDMImpl.TYPE_DDM_DOCUMENTLIBRARY) &&
121                                             Validator.isNotNull(fieldValue)) {
122    
123                                    JSONObject fieldValueJSONObject =
124                                            JSONFactoryUtil.createJSONObject(
125                                                    String.valueOf(fieldValue));
126    
127                                    String uuid = fieldValueJSONObject.getString("uuid");
128                                    long groupId = fieldValueJSONObject.getLong("groupId");
129    
130                                    fieldValueJSONObject.put(
131                                            "title", getFileEntryTitle(uuid, groupId));
132    
133                                    jsonObject.put(fieldName, fieldValueJSONObject.toString());
134                            }
135                            else if (fieldType.equals(DDMImpl.TYPE_DDM_LINK_TO_PAGE) &&
136                                             Validator.isNotNull(fieldValue)) {
137    
138                                    JSONObject fieldValueJSONObject =
139                                            JSONFactoryUtil.createJSONObject(
140                                                    String.valueOf(fieldValue));
141    
142                                    long groupId = fieldValueJSONObject.getLong("groupId");
143                                    boolean privateLayout = fieldValueJSONObject.getBoolean(
144                                            "privateLayout");
145                                    long layoutId = fieldValueJSONObject.getLong("layoutId");
146                                    Locale locale = LocaleThreadLocal.getThemeDisplayLocale();
147    
148                                    String layoutName = getLayoutName(
149                                            groupId, privateLayout, layoutId,
150                                            LanguageUtil.getLanguageId(locale));
151    
152                                    fieldValueJSONObject.put("name", layoutName);
153    
154                                    jsonObject.put(fieldName, fieldValueJSONObject.toString());
155                            }
156                            else if ((fieldType.equals(DDMImpl.TYPE_RADIO) ||
157                                              fieldType.equals(DDMImpl.TYPE_SELECT)) &&
158                                             Validator.isNotNull(fieldValue)) {
159    
160                                    fieldValue = JSONFactoryUtil.createJSONArray(
161                                            String.valueOf(fieldValue));
162    
163                                    jsonObject.put(fieldName, (JSONArray)fieldValue);
164                            }
165                            else {
166                                    jsonObject.put(fieldName, String.valueOf(fieldValue));
167                            }
168                    }
169    
170                    return jsonObject;
171            }
172    
173            @Override
174            public List<DDLRecord> getRecords(Hits hits) throws Exception {
175                    List<DDLRecord> records = new ArrayList<DDLRecord>();
176    
177                    List<com.liferay.portal.kernel.search.Document> documents =
178                            hits.toList();
179    
180                    for (com.liferay.portal.kernel.search.Document document : documents) {
181                            long recordId = GetterUtil.getLong(
182                                    document.get(
183                                            com.liferay.portal.kernel.search.Field.ENTRY_CLASS_PK));
184    
185                            try {
186                                    DDLRecord record = DDLRecordLocalServiceUtil.getRecord(
187                                            recordId);
188    
189                                    records.add(record);
190                            }
191                            catch (NoSuchRecordException nsre) {
192                                    if (_log.isWarnEnabled()) {
193                                            _log.warn(
194                                                    "DDL record index is stale and contains record " +
195                                                            recordId);
196                                    }
197    
198                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
199                                            DDLRecord.class);
200    
201                                    long companyId = GetterUtil.getLong(
202                                            document.get(
203                                                    com.liferay.portal.kernel.search.Field.COMPANY_ID));
204    
205                                    indexer.delete(companyId, document.getUID());
206                            }
207                    }
208    
209                    return records;
210            }
211    
212            @Override
213            public JSONArray getRecordSetJSONArray(DDLRecordSet recordSet)
214                    throws Exception {
215    
216                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
217    
218                    DDMStructure ddmStructure = recordSet.getDDMStructure();
219    
220                    Map<String, Map<String, String>> fieldsMap =
221                            ddmStructure.getFieldsMap();
222    
223                    for (Map<String, String> fields : fieldsMap.values()) {
224                            String name = fields.get(FieldConstants.NAME);
225    
226                            if (ddmStructure.isFieldPrivate(name)) {
227                                    continue;
228                            }
229    
230                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
231    
232                            String dataType = fields.get(FieldConstants.DATA_TYPE);
233    
234                            jsonObject.put("dataType", dataType);
235    
236                            boolean editable = GetterUtil.getBoolean(
237                                    fields.get(FieldConstants.EDITABLE), true);
238    
239                            jsonObject.put("editable", editable);
240    
241                            String label = fields.get(FieldConstants.LABEL);
242    
243                            jsonObject.put("label", label);
244    
245                            jsonObject.put("name", name);
246    
247                            boolean required = GetterUtil.getBoolean(
248                                    fields.get(FieldConstants.REQUIRED));
249    
250                            jsonObject.put("required", required);
251    
252                            boolean sortable = GetterUtil.getBoolean(
253                                    fields.get(FieldConstants.SORTABLE), true);
254    
255                            jsonObject.put("sortable", sortable);
256    
257                            String type = fields.get(FieldConstants.TYPE);
258    
259                            jsonObject.put("type", type);
260    
261                            jsonArray.put(jsonObject);
262                    }
263    
264                    return jsonArray;
265            }
266    
267            @Override
268            public JSONArray getRecordsJSONArray(DDLRecordSet recordSet)
269                    throws Exception {
270    
271                    return getRecordsJSONArray(recordSet.getRecords(), false);
272            }
273    
274            @Override
275            public JSONArray getRecordsJSONArray(List<DDLRecord> records)
276                    throws Exception {
277    
278                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
279    
280                    for (DDLRecord record : records) {
281                            JSONObject jsonObject = getRecordJSONObject(record);
282    
283                            jsonArray.put(jsonObject);
284                    }
285    
286                    return jsonArray;
287            }
288    
289            @Override
290            public JSONArray getRecordsJSONArray(
291                            List<DDLRecord> records, boolean latestRecordVersion)
292                    throws Exception {
293    
294                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
295    
296                    for (DDLRecord record : records) {
297                            JSONObject jsonObject = getRecordJSONObject(
298                                    record, latestRecordVersion);
299    
300                            jsonArray.put(jsonObject);
301                    }
302    
303                    return jsonArray;
304            }
305    
306            @Override
307            public String getTemplateContent(
308                            long ddmTemplateId, DDLRecordSet recordSet,
309                            ThemeDisplay themeDisplay, RenderRequest renderRequest,
310                            RenderResponse renderResponse)
311                    throws Exception {
312    
313                    Map<String, Object> contextObjects = new HashMap<String, Object>();
314    
315                    contextObjects.put(
316                            DDLConstants.RESERVED_DDM_STRUCTURE_ID,
317                            recordSet.getDDMStructureId());
318                    contextObjects.put(
319                            DDLConstants.RESERVED_DDM_TEMPLATE_ID, ddmTemplateId);
320                    contextObjects.put(
321                            DDLConstants.RESERVED_RECORD_SET_DESCRIPTION,
322                            recordSet.getDescription(themeDisplay.getLocale()));
323                    contextObjects.put(
324                            DDLConstants.RESERVED_RECORD_SET_ID, recordSet.getRecordSetId());
325                    contextObjects.put(
326                            DDLConstants.RESERVED_RECORD_SET_NAME,
327                            recordSet.getName(themeDisplay.getLocale()));
328                    contextObjects.put(TemplateConstants.TEMPLATE_ID, ddmTemplateId);
329    
330                    String viewMode = ParamUtil.getString(renderRequest, "viewMode");
331    
332                    if (Validator.isNull(viewMode)) {
333                            viewMode = Constants.VIEW;
334                    }
335    
336                    contextObjects.put("viewMode", viewMode);
337    
338                    DDMTemplate ddmTemplate = DDMTemplateLocalServiceUtil.getTemplate(
339                            ddmTemplateId);
340    
341                    contextObjects.put(
342                            TemplateConstants.CLASS_NAME_ID, ddmTemplate.getClassNameId());
343    
344                    return _transformer.transform(
345                            themeDisplay, contextObjects, ddmTemplate.getScript(),
346                            ddmTemplate.getLanguage());
347            }
348    
349            /**
350             * @deprecated As of 7.0.0, with no direct replacement
351             */
352            @Deprecated
353            @Override
354            public boolean isEditable(
355                            HttpServletRequest request, String portletId, long groupId)
356                    throws Exception {
357    
358                    return true;
359            }
360    
361            /**
362             * @deprecated As of 7.0.0, with no direct replacement
363             */
364            @Deprecated
365            @Override
366            public boolean isEditable(
367                            PortletPreferences preferences, String portletId, long groupId)
368                    throws Exception {
369    
370                    return true;
371            }
372    
373            @Override
374            public DDLRecord updateRecord(
375                            long recordId, long recordSetId, boolean mergeFields,
376                            boolean checkPermission, ServiceContext serviceContext)
377                    throws Exception {
378    
379                    DDLRecord record = DDLRecordLocalServiceUtil.fetchRecord(recordId);
380    
381                    boolean majorVersion = ParamUtil.getBoolean(
382                            serviceContext, "majorVersion");
383    
384                    DDLRecordSet recordSet = DDLRecordSetLocalServiceUtil.getDDLRecordSet(
385                            recordSetId);
386    
387                    DDMStructure ddmStructure = recordSet.getDDMStructure();
388    
389                    Fields fields = DDMUtil.getFields(
390                            ddmStructure.getStructureId(), serviceContext);
391    
392                    if (record != null) {
393                            if (checkPermission) {
394                                    record = DDLRecordServiceUtil.updateRecord(
395                                            recordId, majorVersion,
396                                            DDLRecordConstants.DISPLAY_INDEX_DEFAULT, fields,
397                                            mergeFields, serviceContext);
398                            }
399                            else {
400                                    record = DDLRecordLocalServiceUtil.updateRecord(
401                                            serviceContext.getUserId(), recordId, majorVersion,
402                                            DDLRecordConstants.DISPLAY_INDEX_DEFAULT, fields,
403                                            mergeFields, serviceContext);
404                            }
405                    }
406                    else {
407                            if (checkPermission) {
408                                    record = DDLRecordServiceUtil.addRecord(
409                                            serviceContext.getScopeGroupId(), recordSetId,
410                                            DDLRecordConstants.DISPLAY_INDEX_DEFAULT, fields,
411                                            serviceContext);
412                            }
413                            else {
414                                    record = DDLRecordLocalServiceUtil.addRecord(
415                                            serviceContext.getUserId(),
416                                            serviceContext.getScopeGroupId(), recordSetId,
417                                            DDLRecordConstants.DISPLAY_INDEX_DEFAULT, fields,
418                                            serviceContext);
419                            }
420                    }
421    
422                    return record;
423            }
424    
425            @Override
426            public DDLRecord updateRecord(
427                            long recordId, long recordSetId, boolean mergeFields,
428                            ServiceContext serviceContext)
429                    throws Exception {
430    
431                    return updateRecord(
432                            recordId, recordSetId, mergeFields, true, serviceContext);
433            }
434    
435            protected String getFileEntryTitle(String uuid, long groupId) {
436                    try {
437                            FileEntry fileEntry =
438                                    DLAppLocalServiceUtil.getFileEntryByUuidAndGroupId(
439                                            uuid, groupId);
440    
441                            return fileEntry.getTitle();
442                    }
443                    catch (Exception e) {
444                            return LanguageUtil.format(
445                                    LocaleUtil.getSiteDefault(), "is-temporarily-unavailable",
446                                    "content");
447                    }
448            }
449    
450            protected String getLayoutName(
451                    long groupId, boolean privateLayout, long layoutId, String languageId) {
452    
453                    try {
454                            return LayoutServiceUtil.getLayoutName(
455                                    groupId, privateLayout, layoutId, languageId);
456                    }
457                    catch (Exception e) {
458                            return LanguageUtil.format(
459                                    LocaleUtil.getSiteDefault(), "is-temporarily-unavailable",
460                                    "content");
461                    }
462            }
463    
464            private static Log _log = LogFactoryUtil.getLog(DDLImpl.class);
465    
466            private Transformer _transformer = new Transformer(
467                    PropsKeys.DYNAMIC_DATA_LISTS_ERROR_TEMPLATE, true);
468    
469    }