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