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.portlet.documentlibrary.lar;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.lar.BaseStagedModelDataHandler;
020    import com.liferay.portal.kernel.lar.ExportImportPathUtil;
021    import com.liferay.portal.kernel.lar.PortletDataContext;
022    import com.liferay.portal.kernel.lar.PortletDataException;
023    import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
024    import com.liferay.portal.kernel.log.Log;
025    import com.liferay.portal.kernel.log.LogFactoryUtil;
026    import com.liferay.portal.kernel.repository.model.Folder;
027    import com.liferay.portal.kernel.trash.TrashHandler;
028    import com.liferay.portal.kernel.trash.TrashHandlerRegistryUtil;
029    import com.liferay.portal.kernel.util.GetterUtil;
030    import com.liferay.portal.kernel.util.MapUtil;
031    import com.liferay.portal.kernel.util.StringPool;
032    import com.liferay.portal.kernel.util.StringUtil;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portal.kernel.xml.Element;
035    import com.liferay.portal.model.Repository;
036    import com.liferay.portal.repository.liferayrepository.LiferayRepository;
037    import com.liferay.portal.repository.liferayrepository.model.LiferayFolder;
038    import com.liferay.portal.service.RepositoryLocalServiceUtil;
039    import com.liferay.portal.service.ServiceContext;
040    import com.liferay.portal.util.PortalUtil;
041    import com.liferay.portlet.documentlibrary.model.DLFileEntryType;
042    import com.liferay.portlet.documentlibrary.model.DLFileEntryTypeConstants;
043    import com.liferay.portlet.documentlibrary.model.DLFolder;
044    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
045    import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
046    import com.liferay.portlet.documentlibrary.service.DLFileEntryTypeLocalServiceUtil;
047    import com.liferay.portlet.documentlibrary.service.DLFolderLocalServiceUtil;
048    
049    import java.util.ArrayList;
050    import java.util.List;
051    import java.util.Map;
052    
053    /**
054     * @author Mate Thurzo
055     */
056    public class FolderStagedModelDataHandler
057            extends BaseStagedModelDataHandler<Folder> {
058    
059            public static final String[] CLASS_NAMES = {
060                    DLFolder.class.getName(), Folder.class.getName(),
061                    LiferayFolder.class.getName()
062            };
063    
064            @Override
065            public void deleteStagedModel(
066                            String uuid, long groupId, String className, String extraData)
067                    throws PortalException, SystemException {
068    
069                    Folder folder = FolderUtil.fetchByUUID_R(uuid, groupId);
070    
071                    if (folder != null) {
072                            DLAppLocalServiceUtil.deleteFolder(folder.getFolderId());
073                    }
074            }
075    
076            @Override
077            public String[] getClassNames() {
078                    return CLASS_NAMES;
079            }
080    
081            @Override
082            public String getDisplayName(Folder folder) {
083                    return folder.getName();
084            }
085    
086            @Override
087            protected void doExportStagedModel(
088                            PortletDataContext portletDataContext, Folder folder)
089                    throws Exception {
090    
091                    Element folderElement = portletDataContext.getExportDataElement(folder);
092    
093                    String folderPath = ExportImportPathUtil.getModelPath(folder);
094    
095                    if (!folder.isDefaultRepository()) {
096                            Repository repository = RepositoryLocalServiceUtil.getRepository(
097                                    folder.getRepositoryId());
098    
099                            StagedModelDataHandlerUtil.exportReferenceStagedModel(
100                                    portletDataContext, folder, repository,
101                                    PortletDataContext.REFERENCE_TYPE_STRONG);
102    
103                            portletDataContext.addClassedModel(
104                                    folderElement, folderPath, folder);
105    
106                            long liferayRepositoryClassNameId = PortalUtil.getClassNameId(
107                                    LiferayRepository.class.getName());
108    
109                            if (repository.getClassNameId() != liferayRepositoryClassNameId) {
110                                    return;
111                            }
112                    }
113    
114                    if (folder.getParentFolderId() !=
115                                    DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
116    
117                            StagedModelDataHandlerUtil.exportReferenceStagedModel(
118                                    portletDataContext, folder, folder.getParentFolder(),
119                                    PortletDataContext.REFERENCE_TYPE_PARENT);
120                    }
121    
122                    exportFolderFileEntryTypes(portletDataContext, folderElement, folder);
123    
124                    portletDataContext.addClassedModel(
125                            folderElement, folderPath, folder, DLFolder.class);
126            }
127    
128            @Override
129            protected void doImportCompanyStagedModel(
130                            PortletDataContext portletDataContext, String uuid, long folderId)
131                    throws Exception {
132    
133                    Folder existingFolder = FolderUtil.fetchByUUID_R(
134                            uuid, portletDataContext.getCompanyGroupId());
135    
136                    Map<Long, Long> folderIds =
137                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
138                                    Folder.class);
139    
140                    folderIds.put(folderId, existingFolder.getFolderId());
141            }
142    
143            @Override
144            protected void doImportStagedModel(
145                            PortletDataContext portletDataContext, Folder folder)
146                    throws Exception {
147    
148                    if (!folder.isDefaultRepository()) {
149                            StagedModelDataHandlerUtil.importReferenceStagedModel(
150                                    portletDataContext, folder, Repository.class,
151                                    folder.getRepositoryId());
152    
153                            return;
154                    }
155    
156                    long userId = portletDataContext.getUserId(folder.getUserUuid());
157    
158                    if (folder.getParentFolderId() !=
159                                    DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
160    
161                            StagedModelDataHandlerUtil.importReferenceStagedModel(
162                                    portletDataContext, folder, DLFolder.class,
163                                    folder.getParentFolderId());
164                    }
165    
166                    Map<Long, Long> folderIds =
167                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
168                                    Folder.class);
169    
170                    long parentFolderId = MapUtil.getLong(
171                            folderIds, folder.getParentFolderId(), folder.getParentFolderId());
172    
173                    ServiceContext serviceContext = portletDataContext.createServiceContext(
174                            folder, DLFolder.class);
175    
176                    serviceContext.setUserId(userId);
177    
178                    Folder importedFolder = null;
179    
180                    if (portletDataContext.isDataStrategyMirror()) {
181                            Folder existingFolder = FolderUtil.fetchByUUID_R(
182                                    folder.getUuid(), portletDataContext.getScopeGroupId());
183    
184                            if (existingFolder == null) {
185                                    String name = getFolderName(
186                                            null, portletDataContext.getScopeGroupId(), parentFolderId,
187                                            folder.getName(), 2);
188    
189                                    serviceContext.setUuid(folder.getUuid());
190    
191                                    importedFolder = DLAppLocalServiceUtil.addFolder(
192                                            userId, portletDataContext.getScopeGroupId(),
193                                            parentFolderId, name, folder.getDescription(),
194                                            serviceContext);
195                            }
196                            else {
197                                    String name = getFolderName(
198                                            folder.getUuid(), portletDataContext.getScopeGroupId(),
199                                            parentFolderId, folder.getName(), 2);
200    
201                                    importedFolder = DLAppLocalServiceUtil.updateFolder(
202                                            existingFolder.getFolderId(), parentFolderId, name,
203                                            folder.getDescription(), serviceContext);
204                            }
205                    }
206                    else {
207                            String name = getFolderName(
208                                    null, portletDataContext.getScopeGroupId(), parentFolderId,
209                                    folder.getName(), 2);
210    
211                            importedFolder = DLAppLocalServiceUtil.addFolder(
212                                    userId, portletDataContext.getScopeGroupId(), parentFolderId,
213                                    name, folder.getDescription(), serviceContext);
214                    }
215    
216                    Element folderElement = portletDataContext.getImportDataElement(folder);
217    
218                    importFolderFileEntryTypes(
219                            portletDataContext, folderElement, folder, importedFolder,
220                            serviceContext);
221    
222                    portletDataContext.importClassedModel(
223                            folder, importedFolder, DLFolder.class);
224    
225                    folderIds.put(folder.getFolderId(), importedFolder.getFolderId());
226            }
227    
228            @Override
229            protected void doRestoreStagedModel(
230                            PortletDataContext portletDataContext, Folder folder)
231                    throws Exception {
232    
233                    long userId = portletDataContext.getUserId(folder.getUserUuid());
234    
235                    Folder existingFolder = FolderUtil.fetchByUUID_R(
236                            folder.getUuid(), portletDataContext.getScopeGroupId());
237    
238                    if ((existingFolder == null) ||
239                            !(existingFolder.getModel() instanceof DLFolder)) {
240    
241                            return;
242                    }
243    
244                    DLFolder dlFolder = (DLFolder)existingFolder.getModel();
245    
246                    if (!dlFolder.isInTrash()) {
247                            return;
248                    }
249    
250                    TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
251                            DLFolder.class.getName());
252    
253                    if (trashHandler.isRestorable(existingFolder.getFolderId())) {
254                            trashHandler.restoreTrashEntry(
255                                    userId, existingFolder.getFolderId());
256                    }
257            }
258    
259            protected void exportFolderFileEntryTypes(
260                            PortletDataContext portletDataContext, Element folderElement,
261                            Folder folder)
262                    throws Exception {
263    
264                    if (!folder.isDefaultRepository()) {
265                            return;
266                    }
267    
268                    List<DLFileEntryType> dlFileEntryTypes =
269                            DLFileEntryTypeLocalServiceUtil.getFolderFileEntryTypes(
270                                    new long[] {
271                                            portletDataContext.getCompanyGroupId(),
272                                            portletDataContext.getScopeGroupId()
273                                    },
274                                    folder.getFolderId(), false);
275    
276                    long defaultFileEntryTypeId =
277                            DLFileEntryTypeLocalServiceUtil.getDefaultFileEntryTypeId(
278                                    folder.getFolderId());
279    
280                    String defaultFileEntryTypeUuid = StringPool.BLANK;
281    
282                    for (DLFileEntryType dlFileEntryType : dlFileEntryTypes) {
283                            if (dlFileEntryType.getFileEntryTypeId() ==
284                                            DLFileEntryTypeConstants.
285                                                    FILE_ENTRY_TYPE_ID_BASIC_DOCUMENT) {
286    
287                                    folderElement.addAttribute("basic-document", "true");
288    
289                                    continue;
290                            }
291    
292                            if (defaultFileEntryTypeId ==
293                                            dlFileEntryType.getFileEntryTypeId()) {
294    
295                                    defaultFileEntryTypeUuid = dlFileEntryType.getUuid();
296                            }
297    
298                            if (dlFileEntryType.isExportable()) {
299                                    StagedModelDataHandlerUtil.exportReferenceStagedModel(
300                                            portletDataContext, folder, dlFileEntryType,
301                                            PortletDataContext.REFERENCE_TYPE_STRONG);
302                            }
303                    }
304    
305                    folderElement.addAttribute(
306                            "defaultFileEntryTypeUuid", defaultFileEntryTypeUuid);
307            }
308    
309            /**
310             * @see com.liferay.portal.lar.PortletImporter#getAssetCategoryName(String,
311             *      long, long, String, long, int)
312             * @see com.liferay.portal.lar.PortletImporter#getAssetVocabularyName(
313             *      String, long, String, int)
314             */
315            protected String getFolderName(
316                            String uuid, long groupId, long parentFolderId, String name,
317                            int count)
318                    throws Exception {
319    
320                    Folder folder = FolderUtil.fetchByR_P_N(groupId, parentFolderId, name);
321    
322                    if (folder == null) {
323                            return name;
324                    }
325    
326                    if (Validator.isNotNull(uuid) && uuid.equals(folder.getUuid())) {
327                            return name;
328                    }
329    
330                    name = StringUtil.appendParentheticalSuffix(name, count);
331    
332                    return getFolderName(uuid, groupId, parentFolderId, name, ++count);
333            }
334    
335            protected void importFolderFileEntryTypes(
336                            PortletDataContext portletDataContext, Element folderElement,
337                            Folder folder, Folder importedFolder, ServiceContext serviceContext)
338                    throws Exception {
339    
340                    if (!folder.isDefaultRepository()) {
341                            return;
342                    }
343    
344                    List<Long> currentFolderFileEntryTypeIds = new ArrayList<Long>();
345    
346                    String defaultFileEntryTypeUuid = GetterUtil.getString(
347                            folderElement.attributeValue("defaultFileEntryTypeUuid"));
348    
349                    long defaultFileEntryTypeId = 0;
350    
351                    List<Element> referenceElements =
352                            portletDataContext.getReferenceElements(
353                                    folder, DLFileEntryType.class);
354    
355                    for (Element referenceElement : referenceElements) {
356                            long referenceDlFileEntryTypeId = GetterUtil.getLong(
357                                    referenceElement.attributeValue("class-pk"));
358                            String referenceDlFileEntryTypeUuid =
359                                    referenceElement.attributeValue("uuid");
360    
361                            StagedModelDataHandlerUtil.importReferenceStagedModel(
362                                    portletDataContext, folder, DLFileEntryType.class,
363                                    referenceDlFileEntryTypeId);
364    
365                            Map<Long, Long> dlFileEntryTypeIds =
366                                    (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
367                                            DLFileEntryType.class);
368    
369                            long dlFileEntryTypeId = MapUtil.getLong(
370                                    dlFileEntryTypeIds, referenceDlFileEntryTypeId,
371                                    referenceDlFileEntryTypeId);
372    
373                            DLFileEntryType existingDLFileEntryType =
374                                    DLFileEntryTypeLocalServiceUtil.fetchDLFileEntryType(
375                                            dlFileEntryTypeId);
376    
377                            if (existingDLFileEntryType == null) {
378                                    continue;
379                            }
380    
381                            currentFolderFileEntryTypeIds.add(
382                                    existingDLFileEntryType.getFileEntryTypeId());
383    
384                            if (defaultFileEntryTypeUuid.equals(referenceDlFileEntryTypeUuid)) {
385                                    defaultFileEntryTypeId =
386                                            existingDLFileEntryType.getFileEntryTypeId();
387                            }
388                    }
389    
390                    if (GetterUtil.getBoolean(
391                                    folderElement.attributeValue("basic-document"))) {
392    
393                            currentFolderFileEntryTypeIds.add(
394                                    DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_BASIC_DOCUMENT);
395                    }
396    
397                    if (!currentFolderFileEntryTypeIds.isEmpty()) {
398                            DLFolder dlFolder = (DLFolder)importedFolder.getModel();
399    
400                            dlFolder.setDefaultFileEntryTypeId(defaultFileEntryTypeId);
401                            dlFolder.setOverrideFileEntryTypes(true);
402    
403                            DLFolderLocalServiceUtil.updateDLFolder(dlFolder);
404    
405                            DLFileEntryTypeLocalServiceUtil.updateFolderFileEntryTypes(
406                                    dlFolder, currentFolderFileEntryTypeIds, defaultFileEntryTypeId,
407                                    serviceContext);
408                    }
409            }
410    
411            @Override
412            protected void validateExport(
413                            PortletDataContext portletDataContext, Folder folder)
414                    throws PortletDataException {
415    
416                    if ((folder.getGroupId() != portletDataContext.getGroupId()) &&
417                            (folder.getGroupId() != portletDataContext.getScopeGroupId())) {
418    
419                            PortletDataException pde = new PortletDataException(
420                                    PortletDataException.INVALID_GROUP);
421    
422                            pde.setStagedModel(folder);
423    
424                            throw pde;
425                    }
426    
427                    TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
428                            DLFolder.class.getName());
429    
430                    if (trashHandler != null) {
431                            try {
432                                    if (trashHandler.isInTrash(folder.getFolderId()) ||
433                                            trashHandler.isInTrashContainer(folder.getFolderId())) {
434    
435                                            throw new PortletDataException(
436                                                    PortletDataException.STATUS_IN_TRASH);
437                                    }
438                            }
439                            catch (PortletDataException pde) {
440                                    throw pde;
441                            }
442                            catch (Exception e) {
443                                    if (_log.isDebugEnabled()) {
444                                            _log.debug(e, e);
445                                    }
446                                    else if (_log.isWarnEnabled()) {
447                                            _log.warn(
448                                                    "Unable to check trash status for folder " +
449                                                            folder.getFolderId());
450                                    }
451                            }
452                    }
453            }
454    
455            @Override
456            protected boolean validateMissingReference(
457                            String uuid, long companyId, long groupId)
458                    throws Exception {
459    
460                    DLFolder dlFolder =
461                            DLFolderLocalServiceUtil.fetchDLFolderByUuidAndGroupId(
462                                    uuid, groupId);
463    
464                    if (dlFolder == null) {
465                            return false;
466                    }
467    
468                    return true;
469            }
470    
471            private static Log _log = LogFactoryUtil.getLog(
472                    FolderStagedModelDataHandler.class);
473    
474    }