001    /**
002     * Copyright (c) 2000-present 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.portal.verify;
016    
017    import com.liferay.portal.kernel.dao.orm.QueryUtil;
018    import com.liferay.portal.kernel.json.JSONFactoryUtil;
019    import com.liferay.portal.kernel.json.JSONObject;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.repository.model.FileEntry;
023    import com.liferay.portal.kernel.repository.model.FileVersion;
024    import com.liferay.portal.kernel.repository.model.Folder;
025    import com.liferay.portal.kernel.util.CharPool;
026    import com.liferay.portal.kernel.util.GetterUtil;
027    import com.liferay.portal.kernel.util.MimeTypesUtil;
028    import com.liferay.portal.kernel.util.StringBundler;
029    import com.liferay.portal.kernel.util.StringPool;
030    import com.liferay.portal.kernel.util.Validator;
031    import com.liferay.portal.kernel.xml.Document;
032    import com.liferay.portal.kernel.xml.Element;
033    import com.liferay.portal.kernel.xml.Node;
034    import com.liferay.portal.kernel.xml.SAXReaderUtil;
035    import com.liferay.portal.kernel.xml.XPath;
036    import com.liferay.portal.model.BaseModel;
037    import com.liferay.portal.model.CompanyConstants;
038    import com.liferay.portal.service.ServiceContext;
039    import com.liferay.portal.util.PortalUtil;
040    import com.liferay.portlet.documentlibrary.NoSuchFolderException;
041    import com.liferay.portlet.documentlibrary.model.DLFileEntryMetadata;
042    import com.liferay.portlet.documentlibrary.model.DLFileVersion;
043    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
044    import com.liferay.portlet.documentlibrary.model.DLSyncConstants;
045    import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
046    import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
047    import com.liferay.portlet.documentlibrary.service.DLFileEntryMetadataLocalServiceUtil;
048    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
049    import com.liferay.portlet.dynamicdatalists.model.DDLRecord;
050    import com.liferay.portlet.dynamicdatalists.model.DDLRecordModel;
051    import com.liferay.portlet.dynamicdatalists.model.DDLRecordSet;
052    import com.liferay.portlet.dynamicdatalists.model.DDLRecordVersion;
053    import com.liferay.portlet.dynamicdatalists.service.DDLRecordLocalServiceUtil;
054    import com.liferay.portlet.dynamicdatamapping.model.DDMForm;
055    import com.liferay.portlet.dynamicdatamapping.model.DDMFormField;
056    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
057    import com.liferay.portlet.dynamicdatamapping.model.DDMStructureLink;
058    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
059    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants;
060    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLinkLocalServiceUtil;
061    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
062    import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
063    import com.liferay.portlet.dynamicdatamapping.storage.Field;
064    import com.liferay.portlet.dynamicdatamapping.storage.Fields;
065    import com.liferay.portlet.dynamicdatamapping.storage.StorageEngineUtil;
066    import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
067    
068    import java.io.File;
069    import java.io.Serializable;
070    
071    import java.util.HashMap;
072    import java.util.List;
073    import java.util.Map;
074    
075    /**
076     * @author Marcellus Tavares
077     */
078    public class VerifyDynamicDataMapping extends VerifyProcess {
079    
080            protected FileEntry addFileEntry(
081                            long companyId, long userId, long groupId, long folderId,
082                            String fileName, String filePath, int status)
083                    throws Exception {
084    
085                    String contentType = MimeTypesUtil.getContentType(fileName);
086    
087                    String title = fileName;
088    
089                    int index = title.indexOf(CharPool.PERIOD);
090    
091                    if (index > 0) {
092                            title = title.substring(0, index);
093                    }
094    
095                    try {
096                            File file = DLStoreUtil.getFile(
097                                    companyId, CompanyConstants.SYSTEM, filePath);
098    
099                            ServiceContext serviceContext = createServiceContext();
100    
101                            FileEntry fileEntry = DLAppLocalServiceUtil.addFileEntry(
102                                    userId, groupId, folderId, fileName, contentType, title,
103                                    StringPool.BLANK, StringPool.BLANK, file, serviceContext);
104    
105                            updateFileEntryStatus(fileEntry, status, serviceContext);
106    
107                            return fileEntry;
108                    }
109                    catch (Exception e) {
110                            if (_log.isWarnEnabled()) {
111                                    _log.warn("Unable to add file entry " + fileName, e);
112                            }
113    
114                            return null;
115                    }
116            }
117    
118            protected Folder addFolder(
119                            long userId, long groupId, long primaryKey, String fieldName)
120                    throws Exception {
121    
122                    Folder ddmFolder = addFolder(
123                            userId, groupId, DLFolderConstants.DEFAULT_PARENT_FOLDER_ID, "DDM",
124                            StringPool.BLANK);
125    
126                    Folder primaryKeyFolder = addFolder(
127                            userId, groupId, ddmFolder.getFolderId(),
128                            String.valueOf(primaryKey), StringPool.BLANK);
129    
130                    return addFolder(
131                            userId, groupId, primaryKeyFolder.getFolderId(), fieldName,
132                            StringPool.BLANK);
133            }
134    
135            protected Folder addFolder(
136                            long userId, long groupId, long parentFolderId, String name,
137                            String description)
138                    throws Exception {
139    
140                    try {
141                            return DLAppLocalServiceUtil.getFolder(
142                                    groupId, parentFolderId, name);
143                    }
144                    catch (NoSuchFolderException nsfe) {
145                            return DLAppLocalServiceUtil.addFolder(
146                                    userId, groupId, parentFolderId, name, description,
147                                    createServiceContext());
148                    }
149            }
150    
151            protected ServiceContext createServiceContext() {
152                    ServiceContext serviceContext = new ServiceContext();
153    
154                    serviceContext.setAddGroupPermissions(true);
155                    serviceContext.setAddGuestPermissions(true);
156    
157                    return serviceContext;
158            }
159    
160            @Override
161            protected void doVerify() throws Exception {
162                    setUpClassNameIds();
163    
164                    List<DDMStructure> ddmStructures =
165                            DDMStructureLocalServiceUtil.getStructures();
166    
167                    for (DDMStructure ddmStructure : ddmStructures) {
168                            verifyDDMStructure(ddmStructure);
169                            verifyDDMTemplates(ddmStructure);
170    
171                            updateFileUploadReferences(ddmStructure);
172                    }
173            }
174    
175            protected List<Node> getDynamicElementNodes(Document document) {
176                    XPath xPathSelector = SAXReaderUtil.createXPath("//dynamic-element");
177    
178                    return xPathSelector.selectNodes(document);
179            }
180    
181            protected String getFileUploadPath(BaseModel<?> baseModel)
182                    throws Exception {
183    
184                    StringBundler sb = new StringBundler(7);
185    
186                    long primaryKey = 0;
187    
188                    String version = StringPool.BLANK;
189    
190                    if (baseModel instanceof DDLRecordModel) {
191                            DDLRecord ddlRecord = (DDLRecord)baseModel;
192    
193                            primaryKey = ddlRecord.getPrimaryKey();
194    
195                            DDLRecordVersion ddlRecordVersion = ddlRecord.getRecordVersion();
196    
197                            version = ddlRecordVersion.getVersion();
198                    }
199                    else {
200                            DLFileEntryMetadata dlFileEntryMetadata =
201                                    (DLFileEntryMetadata)baseModel;
202    
203                            primaryKey = dlFileEntryMetadata.getPrimaryKey();
204    
205                            DLFileVersion dlFileVersion = dlFileEntryMetadata.getFileVersion();
206    
207                            version = dlFileVersion.getVersion();
208                    }
209    
210                    sb.append("ddm");
211                    sb.append(StringPool.SLASH);
212                    sb.append(baseModel.getModelClassName());
213                    sb.append(StringPool.SLASH);
214                    sb.append(primaryKey);
215                    sb.append(StringPool.SLASH);
216                    sb.append(version);
217    
218                    return sb.toString();
219            }
220    
221            protected List<DDMTemplate> getFormDDMTemplates(DDMStructure ddmStructure)
222                    throws Exception {
223    
224                    return DDMTemplateLocalServiceUtil.getTemplates(
225                            ddmStructure.getGroupId(), _ddmStructureClassNameId,
226                            ddmStructure.getStructureId(),
227                            DDMTemplateConstants.TEMPLATE_TYPE_FORM);
228            }
229    
230            protected String getJSON(FileEntry fileEntry) {
231                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
232    
233                    jsonObject.put("groupId", fileEntry.getGroupId());
234                    jsonObject.put("uuid", fileEntry.getUuid());
235    
236                    return jsonObject.toString();
237            }
238    
239            protected boolean hasDefaultMetadataElement(
240                    Element dynamicElementElement, String defaultLanguageId) {
241    
242                    List<Element> metadataElements = dynamicElementElement.elements(
243                            "meta-data");
244    
245                    for (Element metadataElement : metadataElements) {
246                            String languageId = metadataElement.attributeValue("locale");
247    
248                            if (languageId.equals(defaultLanguageId)) {
249                                    return true;
250                            }
251                    }
252    
253                    return false;
254            }
255    
256            protected boolean hasFileUploadFields(DDMStructure ddmStructure)
257                    throws Exception {
258    
259                    Map<String, DDMFormField> ddmFormFieldsMap =
260                            ddmStructure.getFullHierarchyDDMFormFieldsMap(true);
261    
262                    for (DDMFormField ddmFormField : ddmFormFieldsMap.values()) {
263                            String dataType = ddmFormField.getDataType();
264    
265                            if (Validator.equals(dataType, "file-upload")) {
266                                    return true;
267                            }
268                    }
269    
270                    return false;
271            }
272    
273            protected void setUpClassNameIds() {
274                    _ddlRecordSetClassNameId = PortalUtil.getClassNameId(
275                            DDLRecordSet.class);
276                    _ddmStructureClassNameId = PortalUtil.getClassNameId(
277                            DDMStructure.class);
278                    _dlFileEntryMetadataClassNameId = PortalUtil.getClassNameId(
279                            DLFileEntryMetadata.class);
280            }
281    
282            protected void updateDDLFileUploadReferences(long ddlRecordSetId)
283                    throws Exception {
284    
285                    List<DDLRecord> ddlRecords = DDLRecordLocalServiceUtil.getRecords(
286                            ddlRecordSetId);
287    
288                    for (DDLRecord ddlRecord : ddlRecords) {
289                            updateFileUploadReferences(
290                                    ddlRecord.getCompanyId(), ddlRecord.getDDMStorageId(),
291                                    ddlRecord.getUserId(), ddlRecord.getGroupId(), ddlRecord,
292                                    ddlRecord.getStatus());
293                    }
294            }
295    
296            protected void updateDDMStructure(
297                            DDMStructure ddmStructure, DDMForm ddmForm)
298                    throws Exception {
299    
300                    ddmStructure.updateDDMForm(ddmForm);
301    
302                    DDMStructureLocalServiceUtil.updateDDMStructure(ddmStructure);
303            }
304    
305            protected void updateDDMTemplate(DDMTemplate template, String script)
306                    throws Exception {
307    
308                    if (script.equals(template.getScript())) {
309                            return;
310                    }
311    
312                    template.setScript(script);
313    
314                    DDMTemplateLocalServiceUtil.updateDDMTemplate(template);
315            }
316    
317            protected void updateDLFileUploadReferences(long dlFileEntryMetadataId)
318                    throws Exception {
319    
320                    DLFileEntryMetadata dlFileEntryMetadata =
321                            DLFileEntryMetadataLocalServiceUtil.getFileEntryMetadata(
322                                    dlFileEntryMetadataId);
323    
324                    FileEntry fileEntry = DLAppLocalServiceUtil.getFileEntry(
325                            dlFileEntryMetadata.getFileEntryId());
326    
327                    FileVersion fileVersion = fileEntry.getFileVersion();
328    
329                    updateFileUploadReferences(
330                            fileEntry.getCompanyId(), dlFileEntryMetadata.getDDMStorageId(),
331                            fileEntry.getUserId(), fileEntry.getGroupId(), dlFileEntryMetadata,
332                            fileVersion.getStatus());
333            }
334    
335            protected void updateFieldValues(
336                            long storageId, Map<String, String> fieldValues)
337                    throws Exception {
338    
339                    Fields fields = new Fields();
340    
341                    for (Map.Entry<String, String> entry : fieldValues.entrySet()) {
342                            Field field = new Field(
343                                    storageId, entry.getKey(), entry.getValue());
344    
345                            fields.put(field);
346                    }
347    
348                    ServiceContext serviceContext = new ServiceContext();
349    
350                    StorageEngineUtil.update(storageId, fields, true, serviceContext);
351            }
352    
353            protected void updateFileEntryStatus(
354                            FileEntry fileEntry, int status, ServiceContext serviceContext)
355                    throws Exception {
356    
357                    FileVersion fileVersion = fileEntry.getFileVersion();
358    
359                    Map<String, Serializable> workflowContext =
360                            new HashMap<String, Serializable>();
361    
362                    workflowContext.put("event", DLSyncConstants.EVENT_ADD);
363    
364                    DLFileEntryLocalServiceUtil.updateStatus(
365                            fileVersion.getUserId(), fileVersion.getFileVersionId(), status,
366                            serviceContext, workflowContext);
367            }
368    
369            protected void updateFileUploadReferences(DDMForm ddmForm)
370                    throws Exception {
371    
372                    List<DDMFormField> ddmFormFields = ddmForm.getDDMFormFields();
373    
374                    for (DDMFormField ddmFormField : ddmFormFields) {
375                            updateFileUploadReferences(ddmFormField);
376                    }
377            }
378    
379            protected void updateFileUploadReferences(DDMFormField ddmFormField) {
380                    String dataType = ddmFormField.getDataType();
381    
382                    if (Validator.equals(dataType, "file-upload")) {
383                            ddmFormField.setDataType("document-library");
384                            ddmFormField.setType("ddm-documentlibrary");
385                    }
386            }
387    
388            protected void updateFileUploadReferences(DDMStructure ddmStructure)
389                    throws Exception {
390    
391                    if (!hasFileUploadFields(ddmStructure)) {
392                            return;
393                    }
394    
395                    List<DDMStructureLink> ddmStructureLinks =
396                            DDMStructureLinkLocalServiceUtil.getStructureLinks(
397                                    ddmStructure.getStructureId(), QueryUtil.ALL_POS,
398                                    QueryUtil.ALL_POS);
399    
400                    for (DDMStructureLink ddmStructureLink : ddmStructureLinks) {
401                            updateFileUploadReferences(ddmStructureLink);
402                    }
403    
404                    DDMForm ddmForm = ddmStructure.getDDMForm();
405    
406                    updateFileUploadReferences(ddmForm);
407    
408                    updateDDMStructure(ddmStructure, ddmForm);
409    
410                    List<DDMTemplate> ddmTemplates = getFormDDMTemplates(ddmStructure);
411    
412                    for (DDMTemplate ddmTemplate : ddmTemplates) {
413                            String script = updateFileUploadReferences(ddmTemplate.getScript());
414    
415                            updateDDMTemplate(ddmTemplate, script);
416                    }
417            }
418    
419            protected void updateFileUploadReferences(DDMStructureLink ddmStructureLink)
420                    throws Exception {
421    
422                    long classNameId = ddmStructureLink.getClassNameId();
423    
424                    if (classNameId == _ddlRecordSetClassNameId) {
425                            updateDDLFileUploadReferences(ddmStructureLink.getClassPK());
426                    }
427                    else if (classNameId == _dlFileEntryMetadataClassNameId) {
428                            updateDLFileUploadReferences(ddmStructureLink.getClassPK());
429                    }
430            }
431    
432            protected void updateFileUploadReferences(Element dynamicElementElement) {
433                    String dataType = dynamicElementElement.attributeValue("dataType");
434    
435                    if (Validator.equals(dataType, "file-upload")) {
436                            dynamicElementElement.addAttribute("dataType", "document-library");
437                            dynamicElementElement.addAttribute("type", "ddm-documentlibrary");
438                    }
439            }
440    
441            protected void updateFileUploadReferences(
442                            long companyId, long storageId, long userId, long groupId,
443                            BaseModel<?> baseModel, int status)
444                    throws Exception {
445    
446                    Map<String, String> fieldValues = new HashMap<String, String>();
447    
448                    Fields fields = StorageEngineUtil.getFields(storageId);
449    
450                    for (Field field : fields) {
451                            String dataType = field.getDataType();
452    
453                            if (!dataType.equals("file-upload") ||
454                                    Validator.isNull(field.getValue())) {
455    
456                                    continue;
457                            }
458    
459                            long primaryKey = GetterUtil.getLong(baseModel.getPrimaryKeyObj());
460    
461                            Folder folder = addFolder(
462                                    userId, groupId, primaryKey, field.getName());
463    
464                            String valueString = String.valueOf(field.getValue());
465    
466                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject(
467                                    valueString);
468    
469                            String filePath =
470                                    getFileUploadPath(baseModel) + StringPool.SLASH +
471                                            field.getName();
472    
473                            FileEntry fileEntry = addFileEntry(
474                                    companyId, userId, groupId, folder.getFolderId(),
475                                    jsonObject.getString("name"), filePath, status);
476    
477                            if (fileEntry != null) {
478                                    fieldValues.put(field.getName(), getJSON(fileEntry));
479                            }
480                    }
481    
482                    updateFieldValues(storageId, fieldValues);
483            }
484    
485            protected String updateFileUploadReferences(String xsd) throws Exception {
486                    Document document = SAXReaderUtil.read(xsd);
487    
488                    List<Node> nodes = getDynamicElementNodes(document);
489    
490                    for (Node node : nodes) {
491                            Element dynamicElementElement = (Element)node;
492    
493                            updateFileUploadReferences(dynamicElementElement);
494                    }
495    
496                    return DDMXMLUtil.formatXML(document.asXML());
497            }
498    
499            protected DDMForm verifyDDMForm(DDMForm ddmForm) {
500                    List<DDMFormField> ddmFormFields = ddmForm.getDDMFormFields();
501    
502                    for (DDMFormField ddmFormField : ddmFormFields) {
503                            verifyDDMFormField(ddmFormField);
504                    }
505    
506                    return ddmForm;
507            }
508    
509            protected void verifyDDMFormField(DDMFormField ddmFormField) {
510                    String dataType = ddmFormField.getDataType();
511    
512                    if (Validator.equals(dataType, "image")) {
513                            ddmFormField.setNamespace("ddm");
514                            ddmFormField.setType("ddm-image");
515                    }
516            }
517    
518            protected void verifyDDMStructure(DDMStructure ddmStructure)
519                    throws Exception {
520    
521                    DDMForm ddmForm = verifyDDMForm(ddmStructure.getDDMForm());
522    
523                    updateDDMStructure(ddmStructure, ddmForm);
524            }
525    
526            protected void verifyDDMTemplate(DDMTemplate ddmTemplate) throws Exception {
527                    if (ddmTemplate.getType() != DDMTemplateConstants.TEMPLATE_TYPE_FORM) {
528                            return;
529                    }
530    
531                    String script = verifySchema(
532                            ddmTemplate.getScript(), ddmTemplate.getDefaultLanguageId());
533    
534                    updateDDMTemplate(ddmTemplate, script);
535            }
536    
537            protected void verifyDDMTemplates(DDMStructure ddmStructure)
538                    throws Exception {
539    
540                    List<DDMTemplate> ddmTemplates = getFormDDMTemplates(ddmStructure);
541    
542                    for (DDMTemplate ddmTemplate : ddmTemplates) {
543                            verifyDDMTemplate(ddmTemplate);
544                    }
545            }
546    
547            protected void verifyDynamicElement(
548                    Element dynamicElementElement, String defaultLanguageId) {
549    
550                    String dataType = dynamicElementElement.attributeValue("dataType");
551    
552                    if (Validator.equals(dataType, "image")) {
553                            dynamicElementElement.addAttribute("fieldNamespace", "ddm");
554                            dynamicElementElement.addAttribute("type", "ddm-image");
555                    }
556    
557                    verifyMetadataElement(dynamicElementElement, defaultLanguageId);
558            }
559    
560            protected void verifyMetadataElement(
561                    Element dynamicElementElement, String defaultLanguageId) {
562    
563                    boolean hasDefaultMetadataElement = hasDefaultMetadataElement(
564                            dynamicElementElement, defaultLanguageId);
565    
566                    if (hasDefaultMetadataElement) {
567                            return;
568                    }
569    
570                    Element metadataElement = dynamicElementElement.addElement("meta-data");
571    
572                    metadataElement.addAttribute("locale", defaultLanguageId);
573    
574                    Element entryElement = metadataElement.addElement("entry");
575    
576                    entryElement.addAttribute("name", "label");
577                    entryElement.addCDATA(StringPool.BLANK);
578            }
579    
580            protected String verifySchema(String xsd, String defaultLanguageId)
581                    throws Exception {
582    
583                    Document document = SAXReaderUtil.read(xsd);
584    
585                    List<Node> nodes = getDynamicElementNodes(document);
586    
587                    for (Node node : nodes) {
588                            Element dynamicElementElement = (Element)node;
589    
590                            verifyDynamicElement(dynamicElementElement, defaultLanguageId);
591                    }
592    
593                    return DDMXMLUtil.formatXML(document.asXML());
594            }
595    
596            private static final Log _log = LogFactoryUtil.getLog(
597                    VerifyDynamicDataMapping.class);
598    
599            private long _ddlRecordSetClassNameId;
600            private long _ddmStructureClassNameId;
601            private long _dlFileEntryMetadataClassNameId;
602    
603    }