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