/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portlet.trash.service.impl; import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery; import com.liferay.portal.kernel.dao.orm.DefaultActionableDynamicQuery; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.exception.SystemException; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.model.Group; import com.liferay.portal.kernel.model.SystemEvent; import com.liferay.portal.kernel.model.User; import com.liferay.portal.kernel.search.BaseModelSearchResult; import com.liferay.portal.kernel.search.Document; import com.liferay.portal.kernel.search.Field; import com.liferay.portal.kernel.search.Hits; import com.liferay.portal.kernel.search.Indexable; import com.liferay.portal.kernel.search.IndexableType; import com.liferay.portal.kernel.search.Indexer; import com.liferay.portal.kernel.search.IndexerRegistryUtil; import com.liferay.portal.kernel.search.QueryConfig; import com.liferay.portal.kernel.search.SearchContext; import com.liferay.portal.kernel.search.Sort; import com.liferay.portal.kernel.trash.TrashHandler; import com.liferay.portal.kernel.trash.TrashHandlerRegistryUtil; import com.liferay.portal.kernel.trash.TrashRenderer; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.ObjectValuePair; import com.liferay.portal.kernel.util.OrderByComparator; import com.liferay.portal.kernel.util.UnicodeProperties; import com.liferay.portlet.trash.model.impl.TrashEntryImpl; import com.liferay.portlet.trash.service.base.TrashEntryLocalServiceBaseImpl; import com.liferay.trash.kernel.model.TrashEntry; import com.liferay.trash.kernel.model.TrashVersion; import com.liferay.trash.kernel.util.TrashUtil; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; /** * Provides the local service for accessing, adding, checking, and deleting * trash entries in the Recycle Bin. * * @author Zsolt Berentey */ public class TrashEntryLocalServiceImpl extends TrashEntryLocalServiceBaseImpl { /** * Moves an entry to trash. * * @param userId the primary key of the user removing the entity * @param groupId the primary key of the entry's group * @param className the class name of the entity * @param classPK the primary key of the entity * @param classUuid the UUID of the entity's class * @param referrerClassName the referrer class name used to add a deletion * {@link SystemEvent} * @param status the status of the entity prior to being moved to trash * @param statusOVPs the primary keys and statuses of any of the entry's * versions (e.g., {@link * com.liferay.portlet.documentlibrary.model.DLFileVersion}) * @param typeSettingsProperties the type settings properties * @return the trashEntry */ @Override public TrashEntry addTrashEntry( long userId, long groupId, String className, long classPK, String classUuid, String referrerClassName, int status, List<ObjectValuePair<Long, Integer>> statusOVPs, UnicodeProperties typeSettingsProperties) throws PortalException { User user = userPersistence.findByPrimaryKey(userId); long classNameId = classNameLocalService.getClassNameId(className); TrashEntry trashEntry = trashEntryPersistence.fetchByC_C( classNameId, classPK); if (trashEntry != null) { return trashEntry; } TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler( className); SystemEvent systemEvent = trashHandler.addDeletionSystemEvent( userId, groupId, classPK, classUuid, referrerClassName); long entryId = counterLocalService.increment(); trashEntry = trashEntryPersistence.create(entryId); trashEntry.setGroupId(groupId); trashEntry.setCompanyId(user.getCompanyId()); trashEntry.setUserId(user.getUserId()); trashEntry.setUserName(user.getFullName()); trashEntry.setCreateDate(new Date()); trashEntry.setClassNameId(classNameId); trashEntry.setClassPK(classPK); trashEntry.setSystemEventSetKey(systemEvent.getSystemEventSetKey()); if (typeSettingsProperties != null) { trashEntry.setTypeSettingsProperties(typeSettingsProperties); } trashEntry.setStatus(status); trashEntryPersistence.update(trashEntry); if (statusOVPs != null) { for (ObjectValuePair<Long, Integer> statusOVP : statusOVPs) { long versionId = counterLocalService.increment(); TrashVersion trashVersion = trashVersionPersistence.create( versionId); trashVersion.setEntryId(entryId); trashVersion.setClassNameId(classNameId); trashVersion.setClassPK(statusOVP.getKey()); trashVersion.setStatus(statusOVP.getValue()); trashVersionPersistence.update(trashVersion); } } return trashEntry; } @Override public void checkEntries() throws PortalException { ActionableDynamicQuery actionableDynamicQuery = trashEntryLocalService.getActionableDynamicQuery(); actionableDynamicQuery.setPerformActionMethod( new ActionableDynamicQuery.PerformActionMethod<TrashEntry>() { @Override public void performAction(TrashEntry trashEntry) throws PortalException { Date createDate = trashEntry.getCreateDate(); Group group = groupPersistence.fetchByPrimaryKey( trashEntry.getGroupId()); if (group == null) { return; } Date date = getMaxAge(group); if (createDate.before(date) || !TrashUtil.isTrashEnabled(group)) { TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler( trashEntry.getClassName()); if (trashHandler != null) { try { trashHandler.deleteTrashEntry( trashEntry.getClassPK()); } catch (Exception e) { _log.error(e, e); } } } } }); actionableDynamicQuery.setTransactionConfig( DefaultActionableDynamicQuery.REQUIRES_NEW_TRANSACTION_CONFIG); actionableDynamicQuery.performActions(); } @Override public void deleteEntries(long groupId) { List<TrashEntry> entries = getEntries(groupId); for (TrashEntry entry : entries) { deleteEntry(entry); } } /** * Deletes the trash entry with the primary key. * * @param entryId the primary key of the trash entry * @return the trash entry with the primary key */ @Override public TrashEntry deleteEntry(long entryId) { TrashEntry entry = trashEntryPersistence.fetchByPrimaryKey(entryId); return deleteEntry(entry); } /** * Deletes the trash entry with the entity class name and primary key. * * @param className the class name of entity * @param classPK the primary key of the entry * @return the trash entry with the entity class name and primary key */ @Override public TrashEntry deleteEntry(String className, long classPK) { long classNameId = classNameLocalService.getClassNameId(className); TrashEntry entry = trashEntryPersistence.fetchByC_C( classNameId, classPK); return deleteEntry(entry); } @Indexable(type = IndexableType.DELETE) @Override public TrashEntry deleteEntry(TrashEntry trashEntry) { if (trashEntry != null) { trashVersionPersistence.removeByEntryId(trashEntry.getEntryId()); trashEntry = trashEntryPersistence.remove(trashEntry); systemEventLocalService.deleteSystemEvents( trashEntry.getGroupId(), trashEntry.getSystemEventSetKey()); } return trashEntry; } /** * Returns the trash entry with the primary key. * * @param entryId the primary key of the entry * @return the trash entry with the primary key */ @Override public TrashEntry fetchEntry(long entryId) { return trashEntryPersistence.fetchByPrimaryKey(entryId); } /** * Returns the trash entry with the entity class name and primary key. * * @param className the class name of the entity * @param classPK the primary key of the entity * @return the trash entry with the entity class name and primary key */ @Override public TrashEntry fetchEntry(String className, long classPK) { long classNameId = classNameLocalService.getClassNameId(className); return trashEntryPersistence.fetchByC_C(classNameId, classPK); } /** * Returns the trash entries with the matching group ID. * * @param groupId the primary key of the group * @return the trash entries with the group ID */ @Override public List<TrashEntry> getEntries(long groupId) { return trashEntryPersistence.findByGroupId(groupId); } /** * Returns a range of all the trash entries matching the group ID. * * @param groupId the primary key of the group * @param start the lower bound of the range of trash entries to return * @param end the upper bound of the range of trash entries to return (not * inclusive) * @return the range of matching trash entries */ @Override public List<TrashEntry> getEntries(long groupId, int start, int end) { return trashEntryPersistence.findByGroupId(groupId, start, end); } /** * Returns a range of all the trash entries matching the group ID. * * @param groupId the primary key of the group * @param start the lower bound of the range of trash entries to return * @param end the upper bound of the range of trash entries to return (not * inclusive) * @param obc the comparator to order the trash entries (optionally * <code>null</code>) * @return the range of matching trash entries ordered by comparator * <code>obc</code> */ @Override public List<TrashEntry> getEntries( long groupId, int start, int end, OrderByComparator<TrashEntry> obc) { return trashEntryPersistence.findByGroupId(groupId, start, end, obc); } @Override public List<TrashEntry> getEntries(long groupId, String className) { long classNameId = classNameLocalService.getClassNameId(className); return trashEntryPersistence.findByG_C(groupId, classNameId); } /** * Returns the number of trash entries with the group ID. * * @param groupId the primary key of the group * @return the number of matching trash entries */ @Override public int getEntriesCount(long groupId) { return trashEntryPersistence.countByGroupId(groupId); } /** * Returns the trash entry with the primary key. * * @param entryId the primary key of the trash entry * @return the trash entry with the primary key */ @Override public TrashEntry getEntry(long entryId) throws PortalException { return trashEntryPersistence.findByPrimaryKey(entryId); } /** * Returns the entry with the entity class name and primary key. * * @param className the class name of the entity * @param classPK the primary key of the entity * @return the trash entry with the entity class name and primary key */ @Override public TrashEntry getEntry(String className, long classPK) throws PortalException { long classNameId = classNameLocalService.getClassNameId(className); return trashEntryPersistence.findByC_C(classNameId, classPK); } @Override public Hits search( long companyId, long groupId, long userId, String keywords, int start, int end, Sort sort) { try { Indexer<TrashEntry> indexer = IndexerRegistryUtil.nullSafeGetIndexer(TrashEntry.class); SearchContext searchContext = buildSearchContext( companyId, groupId, userId, keywords, start, end, sort); return indexer.search(searchContext); } catch (Exception e) { throw new SystemException(e); } } @Override public BaseModelSearchResult<TrashEntry> searchTrashEntries( long companyId, long groupId, long userId, String keywords, int start, int end, Sort sort) { try { Indexer<TrashEntry> indexer = IndexerRegistryUtil.nullSafeGetIndexer(TrashEntry.class); SearchContext searchContext = buildSearchContext( companyId, groupId, userId, keywords, start, end, sort); Hits hits = indexer.search(searchContext); List<TrashEntry> trashEntries = _getEntries(hits); return new BaseModelSearchResult<>(trashEntries, hits.getLength()); } catch (Exception e) { throw new SystemException(e); } } protected SearchContext buildSearchContext( long companyId, long groupId, long userId, String keywords, int start, int end, Sort sort) { SearchContext searchContext = new SearchContext(); searchContext.setCompanyId(companyId); searchContext.setEnd(end); searchContext.setKeywords(keywords); searchContext.setGroupIds(new long[] {groupId}); if (sort != null) { searchContext.setSorts(sort); } searchContext.setStart(start); searchContext.setUserId(userId); QueryConfig queryConfig = searchContext.getQueryConfig(); queryConfig.setHighlightEnabled(false); queryConfig.setScoreEnabled(false); return searchContext; } protected Date getMaxAge(Group group) throws PortalException { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); int maxAge = TrashUtil.getMaxAge(group); calendar.add(Calendar.MINUTE, -maxAge); return calendar.getTime(); } private List<TrashEntry> _getEntries(Hits hits) { List<TrashEntry> entries = new ArrayList<>(); for (Document document : hits.getDocs()) { String entryClassName = GetterUtil.getString( document.get(Field.ENTRY_CLASS_NAME)); long classPK = GetterUtil.getLong( document.get(Field.ENTRY_CLASS_PK)); TrashEntry entry = fetchEntry(entryClassName, classPK); if (entry != null) { entries.add(entry); continue; } try { String userName = GetterUtil.getString( document.get(Field.REMOVED_BY_USER_NAME)); Date removedDate = document.getDate(Field.REMOVED_DATE); entry = new TrashEntryImpl(); entry.setUserName(userName); entry.setCreateDate(removedDate); TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(entryClassName); TrashRenderer trashRenderer = trashHandler.getTrashRenderer( classPK); entry.setClassName(trashRenderer.getClassName()); entry.setClassPK(trashRenderer.getClassPK()); String rootEntryClassName = GetterUtil.getString( document.get(Field.ROOT_ENTRY_CLASS_NAME)); long rootEntryClassPK = GetterUtil.getLong( document.get(Field.ROOT_ENTRY_CLASS_PK)); TrashEntry rootTrashEntry = fetchEntry( rootEntryClassName, rootEntryClassPK); if (rootTrashEntry != null) { entry.setRootEntry(rootTrashEntry); } entries.add(entry); } catch (Exception e) { if (_log.isWarnEnabled()) { _log.warn( "Unable to find trash entry for " + entryClassName + " with primary key " + classPK); } } } return entries; } private static final Log _log = LogFactoryUtil.getLog( TrashEntryLocalServiceImpl.class); }