001    /**
002     * Copyright (c) 2000-2012 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.templateparser.Transformer;
028    import com.liferay.portal.kernel.util.GetterUtil;
029    import com.liferay.portal.kernel.util.LocaleUtil;
030    import com.liferay.portal.kernel.util.ParamUtil;
031    import com.liferay.portal.kernel.util.StringPool;
032    import com.liferay.portal.kernel.util.StringUtil;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portal.kernel.xml.Document;
035    import com.liferay.portal.kernel.xml.Element;
036    import com.liferay.portal.kernel.xml.SAXReaderUtil;
037    import com.liferay.portal.model.Group;
038    import com.liferay.portal.model.PortletConstants;
039    import com.liferay.portal.service.GroupLocalServiceUtil;
040    import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
041    import com.liferay.portal.service.ServiceContext;
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    import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
063    import com.liferay.portlet.journal.util.JournalUtil;
064    import com.liferay.util.portlet.PortletRequestUtil;
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.Map;
071    
072    import javax.portlet.PortletPreferences;
073    import javax.portlet.RenderRequest;
074    import javax.portlet.RenderResponse;
075    
076    import javax.servlet.http.HttpServletRequest;
077    import javax.servlet.http.HttpServletResponse;
078    
079    /**
080     * @author Marcelllus Tavares
081     * @author Eduardo Lundgren
082     */
083    public class DDLImpl implements DDL {
084    
085            public void addAllReservedEls(
086                    Element rootElement, Map<String, String> tokens,
087                    DDLRecordSet recordSet) {
088    
089                    JournalUtil.addReservedEl(
090                            rootElement, tokens, DDLConstants.RESERVED_RECORD_SET_ID,
091                            String.valueOf(recordSet.getRecordSetId()));
092    
093                    JournalUtil.addReservedEl(
094                            rootElement, tokens, DDLConstants.RESERVED_RECORD_SET_NAME,
095                            recordSet.getName());
096    
097                    JournalUtil.addReservedEl(
098                            rootElement, tokens, DDLConstants.RESERVED_RECORD_SET_DESCRIPTION,
099                            recordSet.getDescription());
100    
101                    JournalUtil.addReservedEl(
102                            rootElement, tokens, DDLConstants.RESERVED_DDM_STRUCTURE_ID,
103                            String.valueOf(recordSet.getDDMStructureId()));
104            }
105    
106            public JSONObject getRecordJSONObject(DDLRecord record) throws Exception {
107                    return getRecordJSONObject(record, false);
108            }
109    
110            public JSONObject getRecordJSONObject(
111                            DDLRecord record, boolean latestRecordVersion)
112                    throws Exception {
113    
114                    DDLRecordSet recordSet = record.getRecordSet();
115    
116                    DDMStructure ddmStructure = recordSet.getDDMStructure();
117    
118                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
119    
120                    for (String fieldName : ddmStructure.getFieldNames()) {
121                            jsonObject.put(fieldName, StringPool.BLANK);
122                    }
123    
124                    jsonObject.put("displayIndex", record.getDisplayIndex());
125                    jsonObject.put("recordId", record.getRecordId());
126    
127                    DDLRecordVersion recordVersion = record.getRecordVersion();
128    
129                    if (latestRecordVersion) {
130                            recordVersion = record.getLatestRecordVersion();
131                    }
132    
133                    Fields fields = StorageEngineUtil.getFields(
134                            recordVersion.getDDMStorageId());
135    
136                    Iterator<Field> itr = fields.iterator();
137    
138                    while (itr.hasNext()) {
139                            Field field = itr.next();
140    
141                            String fieldName = field.getName();
142                            String fieldType = field.getType();
143                            Object fieldValue = field.getValue();
144    
145                            if (fieldValue instanceof Date) {
146                                    jsonObject.put(fieldName, ((Date)fieldValue).getTime());
147                            }
148                            else if (fieldType.equals(DDMImpl.TYPE_DDM_DOCUMENTLIBRARY) &&
149                                             Validator.isNotNull(fieldValue)) {
150    
151                                    JSONObject fieldValueJSONObject =
152                                            JSONFactoryUtil.createJSONObject(
153                                                    String.valueOf(fieldValue));
154    
155                                    String uuid = fieldValueJSONObject.getString("uuid");
156                                    long groupId = fieldValueJSONObject.getLong("groupId");
157    
158                                    fieldValueJSONObject.put(
159                                            "title", getFileEntryTitle(uuid, groupId));
160    
161                                    jsonObject.put(fieldName, fieldValueJSONObject.toString());
162                            }
163                            else if ((fieldType.equals(DDMImpl.TYPE_RADIO) ||
164                                              fieldType.equals(DDMImpl.TYPE_SELECT)) &&
165                                             Validator.isNotNull(fieldValue)) {
166    
167                                    fieldValue = JSONFactoryUtil.createJSONArray(
168                                            String.valueOf(fieldValue));
169    
170                                    jsonObject.put(fieldName, (JSONArray)fieldValue);
171                            }
172                            else {
173                                    jsonObject.put(fieldName, String.valueOf(fieldValue));
174                            }
175                    }
176    
177                    return jsonObject;
178            }
179    
180            public List<DDLRecord> getRecords(Hits hits) throws Exception {
181                    List<DDLRecord> records = new ArrayList<DDLRecord>();
182    
183                    List<com.liferay.portal.kernel.search.Document> documents =
184                            hits.toList();
185    
186                    for (com.liferay.portal.kernel.search.Document document : documents) {
187                            long recordId = GetterUtil.getLong(
188                                    document.get(
189                                            com.liferay.portal.kernel.search.Field.ENTRY_CLASS_PK));
190    
191                            try {
192                                    DDLRecord record = DDLRecordLocalServiceUtil.getRecord(
193                                            recordId);
194    
195                                    records.add(record);
196                            }
197                            catch (NoSuchRecordException nsre) {
198                                    if (_log.isWarnEnabled()) {
199                                            _log.warn(
200                                                    "DDL record index is stale and contains record " +
201                                                            recordId);
202                                    }
203    
204                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
205                                            DDLRecord.class);
206    
207                                    long companyId = GetterUtil.getLong(
208                                            document.get(
209                                                    com.liferay.portal.kernel.search.Field.COMPANY_ID));
210    
211                                    indexer.delete(companyId, document.getUID());
212                            }
213                    }
214    
215                    return records;
216            }
217    
218            public JSONArray getRecordSetJSONArray(DDLRecordSet recordSet)
219                    throws Exception {
220    
221                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
222    
223                    DDMStructure ddmStructure = recordSet.getDDMStructure();
224    
225                    Map<String, Map<String, String>> fieldsMap =
226                            ddmStructure.getFieldsMap();
227    
228                    for (Map<String, String> fields : fieldsMap.values()) {
229                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
230    
231                            String dataType = fields.get(FieldConstants.DATA_TYPE);
232    
233                            jsonObject.put("dataType", dataType);
234    
235                            boolean editable = GetterUtil.getBoolean(
236                                    fields.get(FieldConstants.EDITABLE), true);
237    
238                            jsonObject.put("editable", editable);
239    
240                            String label = fields.get(FieldConstants.LABEL);
241    
242                            jsonObject.put("label", label);
243    
244                            String name = fields.get(FieldConstants.NAME);
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            public JSONArray getRecordsJSONArray(DDLRecordSet recordSet)
269                    throws Exception {
270    
271                    return getRecordsJSONArray(recordSet.getRecords(), false);
272            }
273    
274            public JSONArray getRecordsJSONArray(List<DDLRecord> records)
275                    throws Exception {
276    
277                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
278    
279                    for (DDLRecord record : records) {
280                            JSONObject jsonObject = getRecordJSONObject(record);
281    
282                            jsonArray.put(jsonObject);
283                    }
284    
285                    return jsonArray;
286            }
287    
288            public JSONArray getRecordsJSONArray(
289                            List<DDLRecord> records, boolean latestRecordVersion)
290                    throws Exception {
291    
292                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
293    
294                    for (DDLRecord record : records) {
295                            JSONObject jsonObject = getRecordJSONObject(
296                                    record, latestRecordVersion);
297    
298                            jsonArray.put(jsonObject);
299                    }
300    
301                    return jsonArray;
302            }
303    
304            public String getTemplateContent(
305                            long ddmTemplateId, DDLRecordSet recordSet,
306                            ThemeDisplay themeDisplay, RenderRequest renderRequest,
307                            RenderResponse renderResponse)
308                    throws Exception {
309    
310                    String viewMode = ParamUtil.getString(renderRequest, "viewMode");
311    
312                    String languageId = LanguageUtil.getLanguageId(renderRequest);
313    
314                    String xmlRequest = PortletRequestUtil.toXML(
315                            renderRequest, renderResponse);
316    
317                    if (Validator.isNull(xmlRequest)) {
318                            xmlRequest = "<request />";
319                    }
320    
321                    Map<String, String> tokens = JournalUtil.getTokens(
322                            recordSet.getGroupId(), themeDisplay, xmlRequest);
323    
324                    tokens.put("template_id", StringUtil.valueOf(ddmTemplateId));
325    
326                    String xml = StringPool.BLANK;
327    
328                    Document document = SAXReaderUtil.createDocument();
329    
330                    Element rootElement = document.addElement("root");
331    
332                    Document requestDocument = SAXReaderUtil.read(xmlRequest);
333    
334                    rootElement.add(requestDocument.getRootElement().createCopy());
335    
336                    addAllReservedEls(rootElement, tokens, recordSet);
337    
338                    xml = DDMXMLUtil.formatXML(document);
339    
340                    DDMTemplate template = DDMTemplateLocalServiceUtil.getTemplate(
341                            ddmTemplateId);
342    
343                    return _transformer.transform(
344                            themeDisplay, tokens, viewMode, languageId, xml,
345                            template.getScript(), template.getLanguage());
346            }
347    
348            public boolean isEditable(
349                            HttpServletRequest request, String portletId, long groupId)
350                    throws Exception {
351    
352                    boolean defaultValue = ParamUtil.getBoolean(request, "editable", true);
353    
354                    return isEditable(portletId, groupId, defaultValue);
355            }
356    
357            public boolean isEditable(
358                            PortletPreferences preferences, String portletId, long groupId)
359                    throws Exception {
360    
361                    boolean defaultValue = GetterUtil.getBoolean(
362                            preferences.getValue("editable", null), true);
363    
364                    return isEditable(portletId, groupId, defaultValue);
365            }
366    
367            public void sendRecordFileUpload(
368                            HttpServletRequest request, HttpServletResponse response,
369                            DDLRecord record, String fieldName, int valueIndex)
370                    throws Exception {
371    
372                    Field field = record.getField(fieldName);
373    
374                    DDMUtil.sendFieldFile(request, response, field, valueIndex);
375            }
376    
377            public void sendRecordFileUpload(
378                            HttpServletRequest request, HttpServletResponse response,
379                            long recordId, String fieldName, int valueIndex)
380                    throws Exception {
381    
382                    DDLRecord record = DDLRecordServiceUtil.getRecord(recordId);
383    
384                    sendRecordFileUpload(request, response, record, fieldName, valueIndex);
385            }
386    
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                    PortletPreferences preferences =
395                            PortletPreferencesLocalServiceUtil.getPreferences(
396                                    serviceContext.getPortletPreferencesIds());
397    
398                    if (!isEditable(
399                                    preferences, serviceContext.getPortletId(),
400                                    serviceContext.getScopeGroupId())) {
401    
402                            return record;
403                    }
404    
405                    boolean majorVersion = ParamUtil.getBoolean(
406                            serviceContext, "majorVersion");
407    
408                    DDLRecordSet recordSet = DDLRecordSetLocalServiceUtil.getDDLRecordSet(
409                            recordSetId);
410    
411                    DDMStructure ddmStructure = recordSet.getDDMStructure();
412    
413                    Fields fields = DDMUtil.getFields(
414                            ddmStructure.getStructureId(), serviceContext);
415    
416                    if (record != null) {
417                            if (checkPermission) {
418                                    record = DDLRecordServiceUtil.updateRecord(
419                                            recordId, majorVersion,
420                                            DDLRecordConstants.DISPLAY_INDEX_DEFAULT, fields,
421                                            mergeFields, serviceContext);
422                            }
423                            else {
424                                    record = DDLRecordLocalServiceUtil.updateRecord(
425                                            serviceContext.getUserId(), recordId, majorVersion,
426                                            DDLRecordConstants.DISPLAY_INDEX_DEFAULT, fields,
427                                            mergeFields, serviceContext);
428                            }
429                    }
430                    else {
431                            if (checkPermission) {
432                                    record = DDLRecordServiceUtil.addRecord(
433                                            serviceContext.getScopeGroupId(), recordSetId,
434                                            DDLRecordConstants.DISPLAY_INDEX_DEFAULT, fields,
435                                            serviceContext);
436                            }
437                            else {
438                                    record = DDLRecordLocalServiceUtil.addRecord(
439                                            serviceContext.getUserId(),
440                                            serviceContext.getScopeGroupId(), recordSetId,
441                                            DDLRecordConstants.DISPLAY_INDEX_DEFAULT, fields,
442                                            serviceContext);
443                            }
444    
445                    }
446    
447                    uploadRecordFieldFiles(record, serviceContext);
448    
449                    return record;
450            }
451    
452            public DDLRecord updateRecord(
453                            long recordId, long recordSetId, boolean mergeFields,
454                            ServiceContext serviceContext)
455                    throws Exception {
456    
457                    return updateRecord(
458                            recordId, recordSetId, mergeFields, true, serviceContext);
459            }
460    
461            public void uploadRecordFieldFile(
462                            DDLRecord record, String fieldName, ServiceContext serviceContext)
463                    throws Exception {
464    
465                    DDLRecordSet recordSet = record.getRecordSet();
466    
467                    DDMStructure ddmStructure = recordSet.getDDMStructure();
468    
469                    DDLRecordVersion recordVersion = record.getLatestRecordVersion();
470    
471                    DDMUtil.uploadFieldFile(
472                            ddmStructure.getStructureId(), recordVersion.getDDMStorageId(),
473                            record, fieldName, serviceContext);
474            }
475    
476            protected String getFileEntryTitle(String uuid, long groupId) {
477                    try {
478                            FileEntry fileEntry =
479                                    DLAppLocalServiceUtil.getFileEntryByUuidAndGroupId(
480                                            uuid, groupId);
481    
482                            return fileEntry.getTitle();
483                    }
484                    catch (Exception e) {
485                            return LanguageUtil.format(
486                                    LocaleUtil.getDefault(), "is-temporarily-unavailable",
487                                    "content");
488                    }
489            }
490    
491            protected boolean isEditable(
492                            String portletId, long groupId, boolean defaultValue)
493                    throws Exception {
494    
495                    String rootPortletId = PortletConstants.getRootPortletId(portletId);
496    
497                    if (rootPortletId.equals(PortletKeys.DYNAMIC_DATA_LISTS)) {
498                            return true;
499                    }
500    
501                    Group group = GroupLocalServiceUtil.fetchGroup(groupId);
502    
503                    if ((group == null) || group.isInStagingPortlet(portletId)) {
504                            return false;
505                    }
506    
507                    return defaultValue;
508            }
509    
510            protected void uploadRecordFieldFiles(
511                            DDLRecord record, ServiceContext serviceContext)
512                    throws Exception {
513    
514                    DDLRecordSet recordSet = record.getRecordSet();
515    
516                    DDMStructure ddmStructure = recordSet.getDDMStructure();
517    
518                    for (String fieldName : ddmStructure.getFieldNames()) {
519                            String fieldDataType = ddmStructure.getFieldDataType(fieldName);
520    
521                            if (fieldDataType.equals(FieldConstants.FILE_UPLOAD)) {
522                                    uploadRecordFieldFile(record, fieldName, serviceContext);
523                            }
524                    }
525            }
526    
527            private static Log _log = LogFactoryUtil.getLog(DDLImpl.class);
528    
529            private Transformer _transformer = new DDLTransformer();
530    
531    }