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