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.service.ServiceContext;
038    import com.liferay.portal.theme.ThemeDisplay;
039    import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
040    import com.liferay.portlet.dynamicdatalists.NoSuchRecordException;
041    import com.liferay.portlet.dynamicdatalists.model.DDLRecord;
042    import com.liferay.portlet.dynamicdatalists.model.DDLRecordConstants;
043    import com.liferay.portlet.dynamicdatalists.model.DDLRecordSet;
044    import com.liferay.portlet.dynamicdatalists.model.DDLRecordVersion;
045    import com.liferay.portlet.dynamicdatalists.service.DDLRecordLocalServiceUtil;
046    import com.liferay.portlet.dynamicdatalists.service.DDLRecordServiceUtil;
047    import com.liferay.portlet.dynamicdatalists.service.DDLRecordSetLocalServiceUtil;
048    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
049    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
050    import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
051    import com.liferay.portlet.dynamicdatamapping.storage.Field;
052    import com.liferay.portlet.dynamicdatamapping.storage.FieldConstants;
053    import com.liferay.portlet.dynamicdatamapping.storage.Fields;
054    import com.liferay.portlet.dynamicdatamapping.storage.StorageEngineUtil;
055    import com.liferay.portlet.dynamicdatamapping.util.DDMImpl;
056    import com.liferay.portlet.dynamicdatamapping.util.DDMUtil;
057    import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
058    import com.liferay.portlet.journal.util.JournalUtil;
059    import com.liferay.util.portlet.PortletRequestUtil;
060    
061    import java.util.ArrayList;
062    import java.util.Date;
063    import java.util.Iterator;
064    import java.util.List;
065    import java.util.Map;
066    
067    import javax.portlet.RenderRequest;
068    import javax.portlet.RenderResponse;
069    
070    import javax.servlet.http.HttpServletRequest;
071    import javax.servlet.http.HttpServletResponse;
072    
073    /**
074     * @author Marcelllus Tavares
075     * @author Eduardo Lundgren
076     */
077    public class DDLImpl implements DDL {
078    
079            public void addAllReservedEls(
080                    Element rootElement, Map<String, String> tokens,
081                    DDLRecordSet recordSet) {
082    
083                    JournalUtil.addReservedEl(
084                            rootElement, tokens, DDLConstants.RESERVED_RECORD_SET_ID,
085                            String.valueOf(recordSet.getRecordSetId()));
086    
087                    JournalUtil.addReservedEl(
088                            rootElement, tokens, DDLConstants.RESERVED_RECORD_SET_NAME,
089                            recordSet.getName());
090    
091                    JournalUtil.addReservedEl(
092                            rootElement, tokens, DDLConstants.RESERVED_RECORD_SET_DESCRIPTION,
093                            recordSet.getDescription());
094    
095                    JournalUtil.addReservedEl(
096                            rootElement, tokens, DDLConstants.RESERVED_DDM_STRUCTURE_ID,
097                            String.valueOf(recordSet.getDDMStructureId()));
098            }
099    
100            public JSONObject getRecordJSONObject(DDLRecord record) throws Exception {
101                    return getRecordJSONObject(record, false);
102            }
103    
104            public JSONObject getRecordJSONObject(
105                            DDLRecord record, boolean latestRecordVersion)
106                    throws Exception {
107    
108                    DDLRecordSet recordSet = record.getRecordSet();
109    
110                    DDMStructure ddmStructure = recordSet.getDDMStructure();
111    
112                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
113    
114                    for (String fieldName : ddmStructure.getFieldNames()) {
115                            jsonObject.put(fieldName, StringPool.BLANK);
116                    }
117    
118                    jsonObject.put("displayIndex", record.getDisplayIndex());
119                    jsonObject.put("recordId", record.getRecordId());
120    
121                    DDLRecordVersion recordVersion = record.getRecordVersion();
122    
123                    if (latestRecordVersion) {
124                            recordVersion = record.getLatestRecordVersion();
125                    }
126    
127                    Fields fields = StorageEngineUtil.getFields(
128                            recordVersion.getDDMStorageId());
129    
130                    Iterator<Field> itr = fields.iterator();
131    
132                    while (itr.hasNext()) {
133                            Field field = itr.next();
134    
135                            String fieldName = field.getName();
136                            String fieldType = field.getType();
137                            Object fieldValue = field.getValue();
138    
139                            if (fieldValue instanceof Date) {
140                                    jsonObject.put(fieldName, ((Date)fieldValue).getTime());
141                            }
142                            else if (fieldType.equals(DDMImpl.TYPE_DDM_DOCUMENTLIBRARY) &&
143                                             Validator.isNotNull(fieldValue)) {
144    
145                                    JSONObject fieldValueJSONObject =
146                                            JSONFactoryUtil.createJSONObject(
147                                                    String.valueOf(fieldValue));
148    
149                                    String uuid = fieldValueJSONObject.getString("uuid");
150                                    long groupId = fieldValueJSONObject.getLong("groupId");
151    
152                                    fieldValueJSONObject.put(
153                                            "title", getFileEntryTitle(uuid, groupId));
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 {
167                                    jsonObject.put(fieldName, String.valueOf(fieldValue));
168                            }
169                    }
170    
171                    return jsonObject;
172            }
173    
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            public JSONArray getRecordSetJSONArray(DDLRecordSet recordSet)
213                    throws Exception {
214    
215                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
216    
217                    DDMStructure ddmStructure = recordSet.getDDMStructure();
218    
219                    Map<String, Map<String, String>> fieldsMap =
220                            ddmStructure.getFieldsMap();
221    
222                    for (Map<String, String> fields : fieldsMap.values()) {
223                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
224    
225                            String dataType = fields.get(FieldConstants.DATA_TYPE);
226    
227                            jsonObject.put("dataType", dataType);
228    
229                            boolean editable = GetterUtil.getBoolean(
230                                    fields.get(FieldConstants.EDITABLE), true);
231    
232                            jsonObject.put("editable", editable);
233    
234                            String label = fields.get(FieldConstants.LABEL);
235    
236                            jsonObject.put("label", label);
237    
238                            String name = fields.get(FieldConstants.NAME);
239    
240                            jsonObject.put("name", name);
241    
242                            boolean required = GetterUtil.getBoolean(
243                                    fields.get(FieldConstants.REQUIRED));
244    
245                            jsonObject.put("required", required);
246    
247                            boolean sortable = GetterUtil.getBoolean(
248                                    fields.get(FieldConstants.SORTABLE), true);
249    
250                            jsonObject.put("sortable", sortable);
251    
252                            String type = fields.get(FieldConstants.TYPE);
253    
254                            jsonObject.put("type", type);
255    
256                            jsonArray.put(jsonObject);
257                    }
258    
259                    return jsonArray;
260            }
261    
262            public JSONArray getRecordsJSONArray(DDLRecordSet recordSet)
263                    throws Exception {
264    
265                    return getRecordsJSONArray(recordSet.getRecords(), false);
266            }
267    
268            public JSONArray getRecordsJSONArray(List<DDLRecord> records)
269                    throws Exception {
270    
271                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
272    
273                    for (DDLRecord record : records) {
274                            JSONObject jsonObject = getRecordJSONObject(record);
275    
276                            jsonArray.put(jsonObject);
277                    }
278    
279                    return jsonArray;
280            }
281    
282            public JSONArray getRecordsJSONArray(
283                            List<DDLRecord> records, boolean latestRecordVersion)
284                    throws Exception {
285    
286                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
287    
288                    for (DDLRecord record : records) {
289                            JSONObject jsonObject = getRecordJSONObject(
290                                    record, latestRecordVersion);
291    
292                            jsonArray.put(jsonObject);
293                    }
294    
295                    return jsonArray;
296            }
297    
298            public String getTemplateContent(
299                            long ddmTemplateId, DDLRecordSet recordSet,
300                            ThemeDisplay themeDisplay, RenderRequest renderRequest,
301                            RenderResponse renderResponse)
302                    throws Exception {
303    
304                    String viewMode = ParamUtil.getString(renderRequest, "viewMode");
305    
306                    String languageId = LanguageUtil.getLanguageId(renderRequest);
307    
308                    String xmlRequest = PortletRequestUtil.toXML(
309                            renderRequest, renderResponse);
310    
311                    if (Validator.isNull(xmlRequest)) {
312                            xmlRequest = "<request />";
313                    }
314    
315                    Map<String, String> tokens = JournalUtil.getTokens(
316                            recordSet.getGroupId(), themeDisplay, xmlRequest);
317    
318                    tokens.put("template_id", StringUtil.valueOf(ddmTemplateId));
319    
320                    String xml = StringPool.BLANK;
321    
322                    Document document = SAXReaderUtil.createDocument();
323    
324                    Element rootElement = document.addElement("root");
325    
326                    Document requestDocument = SAXReaderUtil.read(xmlRequest);
327    
328                    rootElement.add(requestDocument.getRootElement().createCopy());
329    
330                    addAllReservedEls(rootElement, tokens, recordSet);
331    
332                    xml = DDMXMLUtil.formatXML(document);
333    
334                    DDMTemplate template = DDMTemplateLocalServiceUtil.getTemplate(
335                            ddmTemplateId);
336    
337                    return _transformer.transform(
338                            themeDisplay, tokens, viewMode, languageId, xml,
339                            template.getScript(), template.getLanguage());
340            }
341    
342            public void sendRecordFileUpload(
343                            HttpServletRequest request, HttpServletResponse response,
344                            DDLRecord record, String fieldName)
345                    throws Exception {
346    
347                    Field field = record.getField(fieldName);
348    
349                    DDMUtil.sendFieldFile(request, response, field);
350            }
351    
352            public void sendRecordFileUpload(
353                            HttpServletRequest request, HttpServletResponse response,
354                            long recordId, String fieldName)
355                    throws Exception {
356    
357                    DDLRecord record = DDLRecordServiceUtil.getRecord(recordId);
358    
359                    sendRecordFileUpload(request, response, record, fieldName);
360            }
361    
362            public DDLRecord updateRecord(
363                            long recordId, long recordSetId, boolean mergeFields,
364                            boolean checkPermission, ServiceContext serviceContext)
365                    throws Exception {
366    
367                    boolean majorVersion = ParamUtil.getBoolean(
368                            serviceContext, "majorVersion");
369    
370                    DDLRecord record = DDLRecordLocalServiceUtil.fetchRecord(recordId);
371    
372                    DDLRecordSet recordSet = DDLRecordSetLocalServiceUtil.getDDLRecordSet(
373                            recordSetId);
374    
375                    DDMStructure ddmStructure = recordSet.getDDMStructure();
376    
377                    Fields fields = DDMUtil.getFields(
378                            ddmStructure.getStructureId(), serviceContext);
379    
380                    if (record != null) {
381                            if (checkPermission) {
382                                    record = DDLRecordServiceUtil.updateRecord(
383                                            recordId, majorVersion,
384                                            DDLRecordConstants.DISPLAY_INDEX_DEFAULT, fields,
385                                            mergeFields, serviceContext);
386                            }
387                            else {
388                                    record = DDLRecordLocalServiceUtil.updateRecord(
389                                            serviceContext.getUserId(), recordId, majorVersion,
390                                            DDLRecordConstants.DISPLAY_INDEX_DEFAULT, fields,
391                                            mergeFields, serviceContext);
392                            }
393                    }
394                    else {
395                            if (checkPermission) {
396                                    record = DDLRecordServiceUtil.addRecord(
397                                            serviceContext.getScopeGroupId(), recordSetId,
398                                            DDLRecordConstants.DISPLAY_INDEX_DEFAULT, fields,
399                                            serviceContext);
400                            }
401                            else {
402                                    record = DDLRecordLocalServiceUtil.addRecord(
403                                            serviceContext.getUserId(),
404                                            serviceContext.getScopeGroupId(), recordSetId,
405                                            DDLRecordConstants.DISPLAY_INDEX_DEFAULT, fields,
406                                            serviceContext);
407                            }
408    
409                    }
410    
411                    uploadRecordFieldFiles(record, serviceContext);
412    
413                    return record;
414            }
415    
416            public DDLRecord updateRecord(
417                            long recordId, long recordSetId, boolean mergeFields,
418                            ServiceContext serviceContext)
419                    throws Exception {
420    
421                    return updateRecord(
422                            recordId, recordSetId, mergeFields, true, serviceContext);
423            }
424    
425            public String uploadRecordFieldFile(
426                            DDLRecord record, String fieldName, ServiceContext serviceContext)
427                    throws Exception {
428    
429                    DDLRecordSet recordSet = record.getRecordSet();
430    
431                    DDMStructure ddmStructure = recordSet.getDDMStructure();
432    
433                    DDLRecordVersion recordVersion = record.getLatestRecordVersion();
434    
435                    return DDMUtil.uploadFieldFile(
436                            ddmStructure.getStructureId(), recordVersion.getDDMStorageId(),
437                            record, fieldName, serviceContext);
438            }
439    
440            protected String getFileEntryTitle(String uuid, long groupId) {
441                    try {
442                            FileEntry fileEntry =
443                                    DLAppLocalServiceUtil.getFileEntryByUuidAndGroupId(
444                                            uuid, groupId);
445    
446                            return fileEntry.getTitle();
447                    }
448                    catch (Exception e) {
449                            return LanguageUtil.format(
450                                    LocaleUtil.getDefault(), "is-temporarily-unavailable",
451                                    "content");
452                    }
453            }
454    
455            protected void uploadRecordFieldFiles(
456                            DDLRecord record, ServiceContext serviceContext)
457                    throws Exception {
458    
459                    DDLRecordSet recordSet = record.getRecordSet();
460    
461                    DDMStructure ddmStructure = recordSet.getDDMStructure();
462    
463                    for (String fieldName : ddmStructure.getFieldNames()) {
464                            String fieldDataType = ddmStructure.getFieldDataType(fieldName);
465    
466                            if (fieldDataType.equals(FieldConstants.FILE_UPLOAD)) {
467                                    uploadRecordFieldFile(record, fieldName, serviceContext);
468                            }
469                    }
470            }
471    
472            private static Log _log = LogFactoryUtil.getLog(DDLImpl.class);
473    
474            private Transformer _transformer = new DDLTransformer();
475    
476    }