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.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.json.JSONArray;
020    import com.liferay.portal.kernel.json.JSONFactoryUtil;
021    import com.liferay.portal.kernel.json.JSONObject;
022    import com.liferay.portal.kernel.language.LanguageUtil;
023    import com.liferay.portal.kernel.servlet.ServletResponseUtil;
024    import com.liferay.portal.kernel.templateparser.Transformer;
025    import com.liferay.portal.kernel.upload.UploadPortletRequest;
026    import com.liferay.portal.kernel.util.GetterUtil;
027    import com.liferay.portal.kernel.util.MimeTypesUtil;
028    import com.liferay.portal.kernel.util.ParamUtil;
029    import com.liferay.portal.kernel.util.StreamUtil;
030    import com.liferay.portal.kernel.util.StringPool;
031    import com.liferay.portal.kernel.util.Validator;
032    import com.liferay.portal.kernel.xml.Document;
033    import com.liferay.portal.kernel.xml.Element;
034    import com.liferay.portal.kernel.xml.SAXReaderUtil;
035    import com.liferay.portal.model.CompanyConstants;
036    import com.liferay.portal.service.ServiceContext;
037    import com.liferay.portal.service.ServiceContextFactory;
038    import com.liferay.portal.theme.ThemeDisplay;
039    import com.liferay.portal.util.WebKeys;
040    import com.liferay.portlet.documentlibrary.DuplicateDirectoryException;
041    import com.liferay.portlet.documentlibrary.DuplicateFileException;
042    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
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.NoSuchTemplateException;
051    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
052    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
053    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
054    import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
055    import com.liferay.portlet.dynamicdatamapping.storage.Field;
056    import com.liferay.portlet.dynamicdatamapping.storage.FieldConstants;
057    import com.liferay.portlet.dynamicdatamapping.storage.Fields;
058    import com.liferay.portlet.dynamicdatamapping.storage.StorageEngineUtil;
059    import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
060    import com.liferay.portlet.journal.util.JournalUtil;
061    import com.liferay.util.portlet.PortletRequestUtil;
062    
063    import java.io.InputStream;
064    import java.io.Serializable;
065    
066    import java.util.Date;
067    import java.util.Iterator;
068    import java.util.List;
069    import java.util.Map;
070    import java.util.Set;
071    
072    import javax.portlet.RenderRequest;
073    import javax.portlet.RenderResponse;
074    
075    import javax.servlet.http.HttpServletRequest;
076    import javax.servlet.http.HttpServletResponse;
077    
078    /**
079     * @author Marcelllus Tavares
080     * @author Eduardo Lundgren
081     */
082    public class DDLImpl implements DDL {
083    
084            public void addAllReservedEls(
085                    Element rootElement, Map<String, String> tokens,
086                    DDLRecordSet recordSet) {
087    
088                    JournalUtil.addReservedEl(
089                            rootElement, tokens, DDLConstants.RESERVED_RECORD_SET_ID,
090                            String.valueOf(recordSet.getRecordSetId()));
091    
092                    JournalUtil.addReservedEl(
093                            rootElement, tokens, DDLConstants.RESERVED_RECORD_SET_NAME,
094                            recordSet.getName());
095    
096                    JournalUtil.addReservedEl(
097                            rootElement, tokens, DDLConstants.RESERVED_RECORD_SET_DESCRIPTION,
098                            recordSet.getDescription());
099    
100                    JournalUtil.addReservedEl(
101                            rootElement, tokens, DDLConstants.RESERVED_DDM_STRUCTURE_ID,
102                            String.valueOf(recordSet.getDDMStructureId()));
103            }
104    
105            public Fields getFields(
106                            UploadPortletRequest uploadPortletRequest, long ddmStructureId)
107                    throws PortalException, SystemException {
108    
109                    return getFields(uploadPortletRequest, ddmStructureId, 0);
110            }
111    
112            public Fields getFields(
113                            UploadPortletRequest uploadPortletRequest, long ddmStructureId,
114                            long ddmTemplateId)
115                    throws PortalException, SystemException {
116    
117                    DDMStructure ddmStructure = DDMStructureLocalServiceUtil.getStructure(
118                            ddmStructureId);
119    
120                    try {
121                            DDMTemplate ddmTemplate = DDMTemplateLocalServiceUtil.getTemplate(
122                                    ddmTemplateId);
123    
124                            ddmStructure.setXsd(ddmTemplate.getScript());
125                    }
126                    catch (NoSuchTemplateException nste) {
127                    }
128    
129                    Set<String> fieldNames = ddmStructure.getFieldNames();
130    
131                    Fields fields = new Fields();
132    
133                    for (String fieldName : fieldNames) {
134                            Field field = new Field();
135    
136                            field.setName(fieldName);
137    
138                            String fieldDataType = ddmStructure.getFieldDataType(fieldName);
139                            String fieldType = ddmStructure.getFieldType(fieldName);
140                            String fieldValue = uploadPortletRequest.getParameter(fieldName);
141    
142                            if (fieldDataType.equals(FieldConstants.FILE_UPLOAD)) {
143                                    continue;
144                            }
145    
146                            if (fieldType.equals("radio") || fieldType.equals("select")) {
147                                    String[] fieldValues = ParamUtil.getParameterValues(
148                                            uploadPortletRequest, fieldName);
149    
150                                    fieldValue = JSONFactoryUtil.serialize(fieldValues);
151                            }
152    
153                            if (fieldValue == null) {
154                                    continue;
155                            }
156    
157                            Serializable fieldValueSerializable =
158                                    FieldConstants.getSerializable(
159                                            fieldDataType, GetterUtil.getString(fieldValue));
160    
161                            field.setValue(fieldValueSerializable);
162    
163                            fields.put(field);
164                    }
165    
166                    return fields;
167            }
168    
169            public String getRecordFileUploadPath(DDLRecord record) {
170                    return "ddl_records/" + record.getRecordId();
171            }
172    
173            public JSONObject getRecordJSONObject(DDLRecord record) throws Exception {
174                    return getRecordJSONObject(record, false);
175            }
176    
177            public JSONObject getRecordJSONObject(
178                            DDLRecord record, boolean latestRecordVersion)
179                    throws Exception {
180    
181                    DDLRecordSet recordSet = record.getRecordSet();
182    
183                    DDMStructure ddmStructure = recordSet.getDDMStructure();
184    
185                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
186    
187                    for (String fieldName : ddmStructure.getFieldNames()) {
188                            jsonObject.put(fieldName, StringPool.BLANK);
189                    }
190    
191                    jsonObject.put("displayIndex", record.getDisplayIndex());
192                    jsonObject.put("recordId", record.getRecordId());
193    
194                    DDLRecordVersion recordVersion = record.getRecordVersion();
195    
196                    if (latestRecordVersion) {
197                            recordVersion = record.getLatestRecordVersion();
198                    }
199    
200                    Fields fields = StorageEngineUtil.getFields(
201                            recordVersion.getDDMStorageId());
202    
203                    Iterator<Field> itr = fields.iterator();
204    
205                    while (itr.hasNext()) {
206                            Field field = itr.next();
207    
208                            String fieldName = field.getName();
209                            String fieldType = field.getType();
210                            Object fieldValue = field.getValue();
211    
212                            if (fieldValue instanceof Date) {
213                                    jsonObject.put(fieldName, ((Date)fieldValue).getTime());
214                            }
215                            else if ((fieldType.equals("radio") ||
216                                              fieldType.equals("select")) &&
217                                             Validator.isNotNull(fieldValue)) {
218    
219                                    fieldValue = JSONFactoryUtil.createJSONArray(
220                                            String.valueOf(fieldValue));
221    
222                                    jsonObject.put(fieldName, (JSONArray)fieldValue);
223                            }
224                            else {
225                                    jsonObject.put(fieldName, String.valueOf(fieldValue));
226                            }
227                    }
228    
229                    return jsonObject;
230            }
231    
232            public JSONArray getRecordSetJSONArray(DDLRecordSet recordSet)
233                    throws Exception {
234    
235                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
236    
237                    DDMStructure ddmStructure = recordSet.getDDMStructure();
238    
239                    Map<String, Map<String, String>> fieldsMap =
240                            ddmStructure.getFieldsMap();
241    
242                    for (Map<String, String> fields : fieldsMap.values()) {
243                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
244    
245                            String dataType = fields.get(FieldConstants.DATA_TYPE);
246    
247                            jsonObject.put("dataType", dataType);
248    
249                            boolean editable = GetterUtil.getBoolean(
250                                    fields.get(FieldConstants.EDITABLE), true);
251    
252                            jsonObject.put("editable", editable);
253    
254                            String label = fields.get(FieldConstants.LABEL);
255    
256                            jsonObject.put("label", label);
257    
258                            String name = fields.get(FieldConstants.NAME);
259    
260                            jsonObject.put("name", name);
261    
262                            boolean required = GetterUtil.getBoolean(
263                                    fields.get(FieldConstants.REQUIRED));
264    
265                            jsonObject.put("required", required);
266    
267                            boolean sortable = GetterUtil.getBoolean(
268                                    fields.get(FieldConstants.SORTABLE), true);
269    
270                            jsonObject.put("sortable", sortable);
271    
272                            String type = fields.get(FieldConstants.TYPE);
273    
274                            jsonObject.put("type", type);
275    
276                            jsonArray.put(jsonObject);
277                    }
278    
279                    return jsonArray;
280            }
281    
282            public JSONArray getRecordsJSONArray(DDLRecordSet recordSet)
283                    throws Exception {
284    
285                    return getRecordsJSONArray(recordSet.getRecords(), false);
286            }
287    
288            public JSONArray getRecordsJSONArray(List<DDLRecord> records)
289                    throws Exception {
290    
291                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
292    
293                    for (DDLRecord record : records) {
294                            JSONObject jsonObject = getRecordJSONObject(record);
295    
296                            jsonArray.put(jsonObject);
297                    }
298    
299                    return jsonArray;
300            }
301    
302            public JSONArray getRecordsJSONArray(
303                            List<DDLRecord> records, boolean latestRecordVersion)
304                    throws Exception {
305    
306                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
307    
308                    for (DDLRecord record : records) {
309                            JSONObject jsonObject = getRecordJSONObject(
310                                    record, latestRecordVersion);
311    
312                            jsonArray.put(jsonObject);
313                    }
314    
315                    return jsonArray;
316            }
317    
318            public String getTemplateContent(
319                            long ddmTemplateId, DDLRecordSet recordSet,
320                            ThemeDisplay themeDisplay, RenderRequest renderRequest,
321                            RenderResponse renderResponse)
322                    throws Exception {
323    
324                    String viewMode = ParamUtil.getString(renderRequest, "viewMode");
325    
326                    String languageId = LanguageUtil.getLanguageId(renderRequest);
327    
328                    String xmlRequest = PortletRequestUtil.toXML(
329                            renderRequest, renderResponse);
330    
331                    if (Validator.isNull(xmlRequest)) {
332                            xmlRequest = "<request />";
333                    }
334    
335                    Map<String, String> tokens = JournalUtil.getTokens(
336                            recordSet.getGroupId(), themeDisplay, xmlRequest);
337    
338                    String xml = StringPool.BLANK;
339    
340                    Document document = SAXReaderUtil.createDocument();
341    
342                    Element rootElement = document.addElement("root");
343    
344                    Document requestDocument = SAXReaderUtil.read(xmlRequest);
345    
346                    rootElement.add(requestDocument.getRootElement().createCopy());
347    
348                    addAllReservedEls(rootElement, tokens, recordSet);
349    
350                    xml = DDMXMLUtil.formatXML(document);
351    
352                    DDMTemplate template = DDMTemplateLocalServiceUtil.getTemplate(
353                            ddmTemplateId);
354    
355                    return _transformer.transform(
356                            themeDisplay, tokens, viewMode, languageId, xml,
357                            template.getScript(), template.getLanguage());
358            }
359    
360            public void sendRecordFileUpload(
361                            HttpServletRequest request, HttpServletResponse response,
362                            DDLRecord record, String fieldName)
363                    throws Exception {
364    
365                    Serializable fieldValue = record.getFieldValue(fieldName);
366    
367                    JSONObject fileJSONObject = JSONFactoryUtil.createJSONObject(
368                            String.valueOf(fieldValue));
369    
370                    String fileName = fileJSONObject.getString("name");
371                    String filePath = fileJSONObject.getString("path");
372    
373                    InputStream is = DLStoreUtil.getFileAsStream(
374                            record.getCompanyId(), CompanyConstants.SYSTEM, filePath);
375                    long contentLength = DLStoreUtil.getFileSize(
376                            record.getCompanyId(), CompanyConstants.SYSTEM, filePath);
377                    String contentType = MimeTypesUtil.getContentType(fileName);
378    
379                    ServletResponseUtil.sendFile(
380                            request, response, fileName, is, contentLength, contentType);
381            }
382    
383            public void sendRecordFileUpload(
384                            HttpServletRequest request, HttpServletResponse response,
385                            long recordId, String fieldName)
386                    throws Exception {
387    
388                    DDLRecord record = DDLRecordServiceUtil.getRecord(recordId);
389    
390                    sendRecordFileUpload(request, response, record, fieldName);
391            }
392    
393            public String storeRecordFieldFile(
394                            DDLRecord record, String fieldName, InputStream inputStream)
395                    throws Exception {
396    
397                    DDLRecordVersion recordVersion = record.getLatestRecordVersion();
398    
399                    String dirName =
400                            getRecordFileUploadPath(record) + StringPool.SLASH +
401                                    recordVersion.getVersion();
402    
403                    try {
404                            DLStoreUtil.addDirectory(
405                                    record.getCompanyId(), CompanyConstants.SYSTEM, dirName);
406                    }
407                    catch (DuplicateDirectoryException dde) {
408                    }
409    
410                    String fileName = dirName + StringPool.SLASH + fieldName;
411    
412                    try {
413                            DLStoreUtil.addFile(
414                                    record.getCompanyId(), CompanyConstants.SYSTEM, fileName,
415                                    inputStream);
416                    }
417                    catch (DuplicateFileException dfe) {
418                    }
419    
420                    return fileName;
421            }
422    
423            public DDLRecord updateRecord(
424                            UploadPortletRequest uploadPortletRequest, long recordId,
425                            long recordSetId, boolean mergeFields)
426                    throws Exception {
427    
428                    return updateRecord(
429                            uploadPortletRequest, recordId, recordSetId, mergeFields, true);
430            }
431    
432            public DDLRecord updateRecord(
433                            UploadPortletRequest uploadPortletRequest, long recordId,
434                            long recordSetId, boolean mergeFields, boolean checkPermission)
435                    throws Exception {
436    
437                    ThemeDisplay themeDisplay =
438                            (ThemeDisplay)uploadPortletRequest.getAttribute(
439                                    WebKeys.THEME_DISPLAY);
440    
441                    boolean majorVersion = ParamUtil.getBoolean(
442                            uploadPortletRequest, "majorVersion");
443    
444                    DDLRecord record = DDLRecordLocalServiceUtil.fetchRecord(recordId);
445    
446                    DDLRecordSet recordSet =
447                            DDLRecordSetLocalServiceUtil.getDDLRecordSet(recordSetId);
448    
449                    DDMStructure ddmStructure = recordSet.getDDMStructure();
450    
451                    Fields fields = getFields(
452                            uploadPortletRequest, ddmStructure.getStructureId());
453    
454                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
455                            uploadPortletRequest);
456    
457                    if (record != null) {
458                            if (checkPermission) {
459                                    record = DDLRecordServiceUtil.updateRecord(
460                                            recordId, majorVersion,
461                                            DDLRecordConstants.DISPLAY_INDEX_DEFAULT, fields,
462                                            mergeFields, serviceContext);
463                            }
464                            else {
465                                    record = DDLRecordLocalServiceUtil.updateRecord(
466                                            themeDisplay.getUserId(), recordId, majorVersion,
467                                            DDLRecordConstants.DISPLAY_INDEX_DEFAULT, fields,
468                                            mergeFields, serviceContext);
469                            }
470                    }
471                    else {
472                            if (checkPermission) {
473                                    record = DDLRecordServiceUtil.addRecord(
474                                            themeDisplay.getScopeGroupId(), recordSetId,
475                                            DDLRecordConstants.DISPLAY_INDEX_DEFAULT, fields,
476                                            serviceContext);
477                            }
478                            else {
479                                    record = DDLRecordLocalServiceUtil.addRecord(
480                                            themeDisplay.getUserId(), themeDisplay.getScopeGroupId(),
481                                            recordSetId, DDLRecordConstants.DISPLAY_INDEX_DEFAULT,
482                                            fields, serviceContext);
483                            }
484    
485                    }
486    
487                    uploadRecordFieldFiles(record, uploadPortletRequest, serviceContext);
488    
489                    return record;
490            }
491    
492            public void uploadRecordFieldFile(
493                            DDLRecord record, String fieldName,
494                            UploadPortletRequest uploadPortletRequest,
495                            ServiceContext serviceContext)
496                    throws Exception {
497    
498                    Fields fields = new Fields();
499    
500                    String fileName = uploadPortletRequest.getFileName(fieldName);
501    
502                    Field field = record.getField(fieldName);
503    
504                    String fieldValue = StringPool.BLANK;
505    
506                    if (field != null) {
507                            fieldValue = String.valueOf(field.getValue());
508                    }
509    
510                    InputStream inputStream = null;
511    
512                    try {
513                            inputStream = uploadPortletRequest.getFileAsStream(fieldName, true);
514    
515                            if (inputStream != null) {
516                                    String filePath = storeRecordFieldFile(
517                                            record, fieldName, inputStream);
518    
519                                    JSONObject recordFileJSONObject =
520                                            JSONFactoryUtil.createJSONObject();
521    
522                                    recordFileJSONObject.put("name", fileName);
523                                    recordFileJSONObject.put("path", filePath);
524                                    recordFileJSONObject.put("recordId", record.getRecordId());
525    
526                                    fieldValue = recordFileJSONObject.toString();
527                            }
528    
529                            DDLRecordSet recordSet = record.getRecordSet();
530    
531                            DDMStructure ddmStructure = recordSet.getDDMStructure();
532    
533                            field = new Field(
534                                    ddmStructure.getStructureId(), fieldName, fieldValue);
535    
536                            fields.put(field);
537    
538                            DDLRecordVersion recordVersion = record.getLatestRecordVersion();
539    
540                            StorageEngineUtil.update(
541                                    recordVersion.getDDMStorageId(), fields, true, serviceContext);
542                    }
543                    finally {
544                            StreamUtil.cleanUp(inputStream);
545                    }
546            }
547    
548            public void uploadRecordFieldFiles(
549                            DDLRecord record, UploadPortletRequest uploadPortletRequest,
550                            ServiceContext serviceContext)
551                    throws Exception {
552    
553                    DDLRecordSet recordSet = record.getRecordSet();
554    
555                    DDMStructure ddmStructure = recordSet.getDDMStructure();
556    
557                    for (String fieldName : ddmStructure.getFieldNames()) {
558                            String fieldDataType = ddmStructure.getFieldDataType(fieldName);
559    
560                            if (fieldDataType.equals(FieldConstants.FILE_UPLOAD)) {
561                                    uploadRecordFieldFile(
562                                            record, fieldName, uploadPortletRequest, serviceContext);
563                            }
564                    }
565            }
566    
567            private Transformer _transformer = new DDLTransformer();
568    
569    }