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