/*
* Copyright (C) 2016 LibreCCM Foundation.
*
* 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.contentsection;
import java.util.List;
import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege;
import org.librecms.contentsection.privileges.ItemPrivileges;
import java.util.Collections;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import javax.transaction.Transactional;
/**
* Provides methods for managing the {@link Asset} of an {@link AttachmentList}.
*
* @author Jens Pelzetter
*/
@RequestScoped
public class ItemAttachmentManager {
@Inject
private EntityManager entityManager;
@Inject
private AssetRepository assetRepo;
@Inject
private AssetManager assetManager;
public Optional> findById(final long attachmentId) {
final TypedQuery query = entityManager
.createNamedQuery("ItemAttachment.findById", ItemAttachment.class);
query.setParameter("attachmentId", attachmentId);
try {
return Optional.of(query.getSingleResult());
} catch (NoResultException ex) {
return Optional.empty();
}
}
/**
* Adds the provided {@link Asset} to the provided {@link AttachmentList}.
*
* @param asset The {@link Asset} to add.
* @param attachmentList The attachment list to which the asset is added.
*/
@Transactional(Transactional.TxType.REQUIRED)
@AuthorizationRequired
public void attachAsset(
final Asset asset,
@RequiresPrivilege(ItemPrivileges.EDIT)
final AttachmentList attachmentList) {
if (asset == null) {
throw new IllegalArgumentException("Can't attach asset null.");
}
if (attachmentList == null) {
throw new IllegalArgumentException(
"Can't attach an asset to attachment list null.");
}
// For shared assets (we assume that every asset already in the database
// is a shared one here) check of the asset is already attached.
if (asset.getObjectId() == 0) {
saveNonSharedAsset(asset);
} else {
final TypedQuery countQuery = entityManager.createNamedQuery(
"ItemAttachment.countByAssetIdAndList", Long.class);
countQuery.setParameter("asset", asset);
countQuery.setParameter("attachmentList", attachmentList);
final long count = countQuery.getSingleResult();
if (count > 0) {
//Asset is already attached.
return;
}
}
final ItemAttachment itemAttachment = new ItemAttachment<>();
itemAttachment.setUuid(UUID.randomUUID().toString());
itemAttachment.setAttachmentList(attachmentList);
itemAttachment.setAsset(asset);
itemAttachment.setSortKey(attachmentList.getAttachments().size());
asset.addItemAttachment(itemAttachment);
attachmentList.addAttachment(itemAttachment);
assetRepo.save(asset);
entityManager.merge(attachmentList);
entityManager.persist(itemAttachment);
}
@Transactional(Transactional.TxType.REQUIRES_NEW)
private void saveNonSharedAsset(final Asset asset) {
assetRepo.save(asset);
entityManager.flush();
}
/**
* Removes the provided {@link Asset} from the provided
* {@link AttachmentList}. If the asset is a non shared asset the asset is
* deleted.
*
* @param asset The {@link Asset} to remove.
* @param attachmentList The attachment list to which the asset is removed
* from.
*/
public void unattachAsset(final Asset asset,
final AttachmentList attachmentList) {
if (asset == null) {
throw new IllegalArgumentException("Can't unattach null.");
}
if (attachmentList == null) {
throw new IllegalArgumentException(
"Can't unattach an asset from list null.");
}
final TypedQuery countQuery = entityManager.createNamedQuery(
"ItemAttachment.countByAssetIdAndList", Long.class);
countQuery.setParameter("asset", asset);
countQuery.setParameter("attachmentList", attachmentList);
final long count = countQuery.getSingleResult();
if (count == 0) {
return;
}
@SuppressWarnings("rawtypes")
final TypedQuery query = entityManager
.createNamedQuery("ItemAttachment.findByAssetByAndList",
ItemAttachment.class);
query.setParameter("asset", asset);
query.setParameter("attachmentList", attachmentList);
@SuppressWarnings("rawtypes")
final List attachments = query.getResultList();
attachments.forEach((attachment) -> entityManager.remove(attachment));
if (!assetManager.isShared(asset)) {
entityManager.remove(asset);
}
}
/**
* Moves the {@link Asset} one position up in the provided
* {@link AttachmentList}.
*
* @param asset The asset to move up. If the asset is not part of
* the provided {@link AttachmentList} an
* {@link IllegalArgumentException} is thrown.
* @param attachmentList The attachment list in which the item is moved.
*/
@Transactional(Transactional.TxType.REQUIRED)
@AuthorizationRequired
public void moveUp(
final Asset asset,
@RequiresPrivilege(ItemPrivileges.EDIT)
final AttachmentList attachmentList) {
if (asset == null) {
throw new IllegalArgumentException("Can't move null.");
}
if (attachmentList == null) {
throw new IllegalArgumentException(
"Can't move up an asset in list null.");
}
final TypedQuery countQuery = entityManager.createNamedQuery(
"ItemAttachment.countByAssetIdAndList", Long.class);
countQuery.setParameter("asset", asset);
countQuery.setParameter("attachmentList", attachmentList);
final long count = countQuery.getSingleResult();
if (count == 0) {
return;
}
@SuppressWarnings("rawtypes")
final TypedQuery query = entityManager.createNamedQuery(
"ItemAttachment.findByAssetByAndList", ItemAttachment.class);
query.setParameter("asset", asset);
query.setParameter("attachmentList", attachmentList);
final ItemAttachment> selected = query.getSingleResult();
final Optional> attachment1 = attachmentList
.getAttachments().stream()
.filter(attachment -> {
return attachment.getSortKey() == selected.getSortKey();
})
.findFirst();
final Optional> attachment2 = attachmentList
.getAttachments().stream()
.filter(attachment -> {
return attachment.getSortKey() >= selected.getSortKey() + 1;
})
.findFirst();
if (!attachment2.isPresent()) {
return;
}
final long sortKey1 = attachment1.get().getSortKey();
final long sortKey2 = attachment2.get().getSortKey();
attachment1.get().setSortKey(sortKey2);
attachment2.get().setSortKey(sortKey1);
entityManager.merge(attachment1.get());
entityManager.merge(attachment2.get());
}
/**
* Moves the {@link Asset} one position down in the provided
* {@link AttachmentList}.
*
* @param asset The asset to move down. If the asset is not part of
* the provided {@link AttachmentList} an
* {@link IllegalArgumentException} is thrown.
* @param attachmentList The attachment list in which the item is moved.
*/
@Transactional(Transactional.TxType.REQUIRED)
@AuthorizationRequired
public void moveDown(
final Asset asset,
@RequiresPrivilege(ItemPrivileges.EDIT)
final AttachmentList attachmentList) {
if (asset == null) {
throw new IllegalArgumentException("Can't move down null.");
}
if (attachmentList == null) {
throw new IllegalArgumentException(
"Can't move down an asset in list null.");
}
final TypedQuery countQuery = entityManager.createNamedQuery(
"ItemAttachment.countByAssetIdAndList", Long.class);
countQuery.setParameter("asset", asset);
countQuery.setParameter("attachmentList", attachmentList);
final long count = countQuery.getSingleResult();
if (count == 0) {
return;
}
@SuppressWarnings("rawtypes")
final TypedQuery query = entityManager.createNamedQuery(
"ItemAttachment.findByAssetByAndList", ItemAttachment.class);
query.setParameter("asset", asset);
query.setParameter("attachmentList", attachmentList);
final ItemAttachment> selected = query.getSingleResult();
final Optional> attachment1 = attachmentList
.getAttachments().stream()
.filter(attachment -> {
return attachment.getSortKey() == selected.getSortKey();
})
.findFirst();
final List> lower = attachmentList
.getAttachments().stream()
.filter(attachment -> {
return attachment.getSortKey() <= selected.getSortKey() - 1;
})
.collect(Collectors.toList());
Collections.sort(lower);
final Optional> attachment2;
if (lower.isEmpty()) {
attachment2 = Optional.empty();
} else {
attachment2 = Optional.of(lower.get(lower.size() - 1));
}
if (!attachment2.isPresent()) {
return;
}
final long sortKey1 = attachment1.get().getSortKey();
final long sortKey2 = attachment2.get().getSortKey();
attachment1.get().setSortKey(sortKey2);
attachment2.get().setSortKey(sortKey1);
entityManager.merge(attachment1.get());
entityManager.merge(attachment2.get());
}
}