001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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.repository.model.FileEntry;
021    import com.liferay.portal.kernel.repository.model.FileVersion;
022    import com.liferay.portal.kernel.repository.model.Folder;
023    import com.liferay.portal.kernel.util.CharPool;
024    import com.liferay.portal.kernel.util.GetterUtil;
025    import com.liferay.portal.kernel.util.MimeTypesUtil;
026    import com.liferay.portal.kernel.util.StringBundler;
027    import com.liferay.portal.kernel.util.StringPool;
028    import com.liferay.portal.kernel.util.Validator;
029    import com.liferay.portal.kernel.xml.Document;
030    import com.liferay.portal.kernel.xml.Element;
031    import com.liferay.portal.kernel.xml.Node;
032    import com.liferay.portal.kernel.xml.SAXReaderUtil;
033    import com.liferay.portal.kernel.xml.XPath;
034    import com.liferay.portal.model.BaseModel;
035    import com.liferay.portal.model.CompanyConstants;
036    import com.liferay.portal.service.ServiceContext;
037    import com.liferay.portal.util.PortalUtil;
038    import com.liferay.portlet.documentlibrary.NoSuchFolderException;
039    import com.liferay.portlet.documentlibrary.model.DLFileEntryMetadata;
040    import com.liferay.portlet.documentlibrary.model.DLFileVersion;
041    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
042    import com.liferay.portlet.documentlibrary.model.DLSyncConstants;
043    import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
044    import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
045    import com.liferay.portlet.documentlibrary.service.DLFileEntryMetadataLocalServiceUtil;
046    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
047    import com.liferay.portlet.dynamicdatalists.model.DDLRecord;
048    import com.liferay.portlet.dynamicdatalists.model.DDLRecordModel;
049    import com.liferay.portlet.dynamicdatalists.model.DDLRecordSet;
050    import com.liferay.portlet.dynamicdatalists.model.DDLRecordVersion;
051    import com.liferay.portlet.dynamicdatalists.service.DDLRecordLocalServiceUtil;
052    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
053    import com.liferay.portlet.dynamicdatamapping.model.DDMStructureLink;
054    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
055    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants;
056    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLinkLocalServiceUtil;
057    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
058    import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
059    import com.liferay.portlet.dynamicdatamapping.storage.Field;
060    import com.liferay.portlet.dynamicdatamapping.storage.FieldConstants;
061    import com.liferay.portlet.dynamicdatamapping.storage.Fields;
062    import com.liferay.portlet.dynamicdatamapping.storage.StorageEngineUtil;
063    import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
064    
065    import java.io.File;
066    import java.io.Serializable;
067    
068    import java.util.HashMap;
069    import java.util.List;
070    import java.util.Map;
071    
072    /**
073     * @author Marcellus Tavares
074     */
075    public class VerifyDynamicDataMapping extends VerifyProcess {
076    
077            protected FileEntry addFileEntry(
078                            long companyId, long userId, long groupId, long folderId,
079                            String fileName, String filePath, int status)
080                    throws Exception {
081    
082                    String contentType = MimeTypesUtil.getContentType(fileName);
083    
084                    String title = fileName;
085    
086                    int index = title.indexOf(CharPool.PERIOD);
087    
088                    if (index > 0) {
089                            title = title.substring(0, index);
090                    }
091    
092                    File file = DLStoreUtil.getFile(
093                            companyId, CompanyConstants.SYSTEM, filePath);
094    
095                    ServiceContext serviceContext = createServiceContext();
096    
097                    FileEntry fileEntry = DLAppLocalServiceUtil.addFileEntry(
098                            userId, groupId, folderId, fileName, contentType, title,
099                            StringPool.BLANK, StringPool.BLANK, file, serviceContext);
100    
101                    updateFileEntryStatus(fileEntry, status, serviceContext);
102    
103                    return fileEntry;
104            }
105    
106            protected Folder addFolder(
107                            long userId, long groupId, long primaryKey, String fieldName)
108                    throws Exception {
109    
110                    Folder ddmFolder = addFolder(
111                            userId, groupId, DLFolderConstants.DEFAULT_PARENT_FOLDER_ID, "DDM",
112                            StringPool.BLANK);
113    
114                    Folder primaryKeyFolder = addFolder(
115                            userId, groupId, ddmFolder.getFolderId(),
116                            String.valueOf(primaryKey), StringPool.BLANK);
117    
118                    return addFolder(
119                            userId, groupId, primaryKeyFolder.getFolderId(), fieldName,
120                            StringPool.BLANK);
121            }
122    
123            protected Folder addFolder(
124                            long userId, long groupId, long parentFolderId, String name,
125                            String description)
126                    throws Exception {
127    
128                    try {
129                            return DLAppLocalServiceUtil.getFolder(
130                                    groupId, parentFolderId, name);
131                    }
132                    catch (NoSuchFolderException nsfe) {
133                            return DLAppLocalServiceUtil.addFolder(
134                                    userId, groupId, parentFolderId, name, description,
135                                    createServiceContext());
136                    }
137            }
138    
139            protected boolean createDefaultMetadataElement(
140                    Element dynamicElementElement, String defaultLanguageId) {
141    
142                    boolean hasDefaultMetadataElement = hasDefaultMetadataElement(
143                            dynamicElementElement, defaultLanguageId);
144    
145                    if (hasDefaultMetadataElement) {
146                            return false;
147                    }
148    
149                    Element metadataElement = dynamicElementElement.addElement("meta-data");
150    
151                    metadataElement.addAttribute("locale", defaultLanguageId);
152    
153                    Element entryElement = metadataElement.addElement("entry");
154    
155                    entryElement.addAttribute("name", "label");
156                    entryElement.addCDATA(StringPool.BLANK);
157    
158                    return true;
159            }
160    
161            protected ServiceContext createServiceContext() {
162                    ServiceContext serviceContext = new ServiceContext();
163    
164                    serviceContext.setAddGroupPermissions(true);
165                    serviceContext.setAddGuestPermissions(true);
166    
167                    return serviceContext;
168            }
169    
170            @Override
171            protected void doVerify() throws Exception {
172                    setUpClassNameIds();
173    
174                    List<DDMStructure> structures =
175                            DDMStructureLocalServiceUtil.getStructures();
176    
177                    for (DDMStructure structure : structures) {
178                            verifyStructure(structure);
179    
180                            updateFileUploadReferences(structure);
181                    }
182            }
183    
184            protected String getFileUploadPath(BaseModel<?> baseModel)
185                    throws Exception {
186    
187                    StringBundler sb = new StringBundler(7);
188    
189                    long primaryKey = 0;
190    
191                    String version = StringPool.BLANK;
192    
193                    if (baseModel instanceof DDLRecordModel) {
194                            DDLRecord ddlRecord = (DDLRecord)baseModel;
195    
196                            primaryKey = ddlRecord.getPrimaryKey();
197    
198                            DDLRecordVersion ddlRecordVersion = ddlRecord.getRecordVersion();
199    
200                            version = ddlRecordVersion.getVersion();
201                    }
202                    else {
203                            DLFileEntryMetadata dlFileEntryMetadata =
204                                    (DLFileEntryMetadata)baseModel;
205    
206                            primaryKey = dlFileEntryMetadata.getPrimaryKey();
207    
208                            DLFileVersion dlFileVersion = dlFileEntryMetadata.getFileVersion();
209    
210                            version = dlFileVersion.getVersion();
211                    }
212    
213                    sb.append("ddm");
214                    sb.append(StringPool.SLASH);
215                    sb.append(baseModel.getModelClassName());
216                    sb.append(StringPool.SLASH);
217                    sb.append(primaryKey);
218                    sb.append(StringPool.SLASH);
219                    sb.append(version);
220    
221                    return sb.toString();
222            }
223    
224            protected String getJSON(FileEntry fileEntry) {
225                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
226    
227                    jsonObject.put("groupId", fileEntry.getGroupId());
228                    jsonObject.put("uuid", fileEntry.getUuid());
229    
230                    return jsonObject.toString();
231            }
232    
233            protected boolean hasDefaultMetadataElement(
234                    Element dynamicElementElement, String defaultLanguageId) {
235    
236                    List<Element> metadataElements = dynamicElementElement.elements(
237                            "meta-data");
238    
239                    for (Element metadataElement : metadataElements) {
240                            String languageId = metadataElement.attributeValue("locale");
241    
242                            if (languageId.equals(defaultLanguageId)) {
243                                    return true;
244                            }
245                    }
246    
247                    return false;
248            }
249    
250            protected boolean hasFileUploadFields(DDMStructure structure)
251                    throws Exception {
252    
253                    Map<String, Map<String, String>> fieldsMap = structure.getFieldsMap();
254    
255                    for (Map<String, String> field : fieldsMap.values()) {
256                            String dataType = field.get(FieldConstants.DATA_TYPE);
257    
258                            if (dataType.equals("file-upload")) {
259                                    return true;
260                            }
261                    }
262    
263                    return false;
264            }
265    
266            protected void setUpClassNameIds() {
267                    _ddlRecordSetClassNameId = PortalUtil.getClassNameId(
268                            DDLRecordSet.class);
269                    _ddmStructureClassNameId = PortalUtil.getClassNameId(
270                            DDMStructure.class);
271                    _dlFileEntryMetadataClassNameId = PortalUtil.getClassNameId(
272                            DLFileEntryMetadata.class);
273            }
274    
275            protected void updateDDLFileUploadReferences(long ddlRecordSetId)
276                    throws Exception {
277    
278                    List<DDLRecord> ddlRecords = DDLRecordLocalServiceUtil.getRecords(
279                            ddlRecordSetId);
280    
281                    for (DDLRecord ddlRecord : ddlRecords) {
282                            updateFileUploadReferences(
283                                    ddlRecord.getCompanyId(), ddlRecord.getDDMStorageId(),
284                                    ddlRecord.getUserId(), ddlRecord.getGroupId(), ddlRecord,
285                                    ddlRecord.getStatus());
286                    }
287            }
288    
289            protected void updateDLFileUploadReferences(long dlFileEntryMetadataId)
290                    throws Exception {
291    
292                    DLFileEntryMetadata dlFileEntryMetadata =
293                            DLFileEntryMetadataLocalServiceUtil.getFileEntryMetadata(
294                                    dlFileEntryMetadataId);
295    
296                    FileEntry fileEntry = DLAppLocalServiceUtil.getFileEntry(
297                            dlFileEntryMetadata.getFileEntryId());
298    
299                    FileVersion fileVersion = fileEntry.getFileVersion();
300    
301                    updateFileUploadReferences(
302                            fileEntry.getCompanyId(), dlFileEntryMetadata.getDDMStorageId(),
303                            fileEntry.getUserId(), fileEntry.getGroupId(), dlFileEntryMetadata,
304                            fileVersion.getStatus());
305            }
306    
307            protected void updateFieldValues(
308                            long storageId, Map<String, String> fieldValues)
309                    throws Exception {
310    
311                    Fields fields = new Fields();
312    
313                    for (Map.Entry<String, String> entry : fieldValues.entrySet()) {
314                            Field field = new Field(
315                                    storageId, entry.getKey(), entry.getValue());
316    
317                            fields.put(field);
318                    }
319    
320                    ServiceContext serviceContext = new ServiceContext();
321    
322                    StorageEngineUtil.update(storageId, fields, true, serviceContext);
323            }
324    
325            protected void updateFileEntryStatus(
326                            FileEntry fileEntry, int status, ServiceContext serviceContext)
327                    throws Exception {
328    
329                    FileVersion fileVersion = fileEntry.getFileVersion();
330    
331                    Map<String, Serializable> workflowContext =
332                            new HashMap<String, Serializable>();
333    
334                    workflowContext.put("event", DLSyncConstants.EVENT_ADD);
335    
336                    DLFileEntryLocalServiceUtil.updateStatus(
337                            fileVersion.getUserId(), fileVersion.getFileVersionId(), status,
338                            workflowContext, serviceContext);
339            }
340    
341            protected void updateFileUploadReferences(DDMStructure structure)
342                    throws Exception {
343    
344                    if (!hasFileUploadFields(structure)) {
345                            return;
346                    }
347    
348                    List<DDMStructureLink> structureLinks =
349                            DDMStructureLinkLocalServiceUtil.getStructureLinks(
350                                    structure.getStructureId(), QueryUtil.ALL_POS,
351                                    QueryUtil.ALL_POS);
352    
353                    for (DDMStructureLink structureLink : structureLinks) {
354                            updateFileUploadReferences(structureLink);
355                    }
356    
357                    updateStructure(structure, updateXSD(structure.getXsd()));
358    
359                    List<DDMTemplate> templates = DDMTemplateLocalServiceUtil.getTemplates(
360                            structure.getGroupId(), _ddmStructureClassNameId,
361                            structure.getStructureId(),
362                            DDMTemplateConstants.TEMPLATE_TYPE_FORM);
363    
364                    for (DDMTemplate template : templates) {
365                            updateTemplate(template, updateXSD(template.getScript()));
366                    }
367            }
368    
369            protected void updateFileUploadReferences(DDMStructureLink structureLink)
370                    throws Exception {
371    
372                    long classNameId = structureLink.getClassNameId();
373    
374                    if (classNameId == _ddlRecordSetClassNameId) {
375                            updateDDLFileUploadReferences(structureLink.getClassPK());
376                    }
377                    else if (classNameId == _dlFileEntryMetadataClassNameId) {
378                            updateDLFileUploadReferences(structureLink.getClassPK());
379                    }
380            }
381    
382            protected void updateFileUploadReferences(
383                            long companyId, long storageId, long userId, long groupId,
384                            BaseModel<?> baseModel, int status)
385                    throws Exception {
386    
387                    Map<String, String> fieldValues = new HashMap<String, String>();
388    
389                    Fields fields = StorageEngineUtil.getFields(storageId);
390    
391                    for (Field field : fields) {
392                            String dataType = field.getDataType();
393    
394                            if (!dataType.equals("file-upload") || (field.getValue() == null)) {
395                                    continue;
396                            }
397    
398                            long primaryKey = GetterUtil.getLong(baseModel.getPrimaryKeyObj());
399    
400                            Folder folder = addFolder(
401                                    userId, groupId, primaryKey, field.getName());
402    
403                            String valueString = String.valueOf(field.getValue());
404    
405                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject(
406                                    valueString);
407    
408                            String filePath =
409                                    getFileUploadPath(baseModel) + StringPool.SLASH +
410                                            field.getName();
411    
412                            FileEntry fileEntry = addFileEntry(
413                                    companyId, userId, groupId, folder.getFolderId(),
414                                    jsonObject.getString("name"), filePath, status);
415    
416                            fieldValues.put(field.getName(), getJSON(fileEntry));
417                    }
418    
419                    updateFieldValues(storageId, fieldValues);
420            }
421    
422            protected void updateStructure(DDMStructure structure, String xsd)
423                    throws Exception {
424    
425                    xsd = DDMXMLUtil.formatXML(xsd);
426    
427                    structure.setXsd(xsd);
428    
429                    DDMStructureLocalServiceUtil.updateDDMStructure(structure);
430            }
431    
432            protected void updateTemplate(DDMTemplate template, String script)
433                    throws Exception {
434    
435                    script = DDMXMLUtil.formatXML(script);
436    
437                    template.setScript(script);
438    
439                    DDMTemplateLocalServiceUtil.updateDDMTemplate(template);
440            }
441    
442            protected String updateXSD(String xsd) throws Exception {
443                    Document document = SAXReaderUtil.read(xsd);
444    
445                    Element rootElement = document.getRootElement();
446    
447                    List<Element> dynamicElementElements = rootElement.elements(
448                            "dynamic-element");
449    
450                    for (Element dynamicElementElement : dynamicElementElements) {
451                            updateXSDDynamicElement(dynamicElementElement);
452                    }
453    
454                    return document.asXML();
455            }
456    
457            protected void updateXSDDynamicElement(Element element) {
458                    String dataType = element.attributeValue("dataType");
459    
460                    if (Validator.equals(dataType, "file-upload")) {
461                            element.addAttribute("dataType", "document-library");
462                            element.addAttribute("type", "ddm-documentlibrary");
463                    }
464    
465                    List<Element> dynamicElementElements = element.elements(
466                            "dynamic-element");
467    
468                    for (Element dynamicElementElement : dynamicElementElements) {
469                            updateXSDDynamicElement(dynamicElementElement);
470                    }
471            }
472    
473            protected void verifyStructure(DDMStructure structure) throws Exception {
474                    boolean modified = false;
475    
476                    String defaultLanguageId = structure.getDefaultLanguageId();
477    
478                    XPath xPathSelector = SAXReaderUtil.createXPath("//dynamic-element");
479    
480                    Document document = structure.getDocument();
481    
482                    List<Node> nodes = xPathSelector.selectNodes(document);
483    
484                    for (Node node : nodes) {
485                            Element dynamicElementElement = (Element)node;
486    
487                            if (createDefaultMetadataElement(
488                                            dynamicElementElement, defaultLanguageId)) {
489    
490                                    modified = true;
491                            }
492                    }
493    
494                    if (modified) {
495                            updateStructure(structure, document.asXML());
496                    }
497            }
498    
499            private long _ddlRecordSetClassNameId;
500            private long _ddmStructureClassNameId;
501            private long _dlFileEntryMetadataClassNameId;
502    
503    }