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