CCM NG/ccm-cms: Optimised ContentItemManger#publish

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4429 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2016-11-03 11:58:59 +00:00
parent 48588b8a1f
commit aa95d07092
4 changed files with 508 additions and 426 deletions

View File

@ -135,6 +135,11 @@ public class AssetManager {
* {@code false if not}.
*/
public boolean isShared(final Asset asset) {
if (asset == null) {
throw new IllegalArgumentException(
"Can't determine if null is a shared asset.");
}
return getAssetFolder(asset).isPresent();
}
@ -149,8 +154,8 @@ public class AssetManager {
final List<Asset> orphaned = assets.stream()
.filter(asset -> asset.getCategories().isEmpty()
&& asset.getItemAttachments().isEmpty())
.collect(Collectors.toList());
&& asset.getItemAttachments().isEmpty()).
collect(Collectors.toList());
orphaned.forEach(orphan -> assetRepo.delete(orphan));
}
@ -394,6 +399,10 @@ public class AssetManager {
*/
@Transactional(Transactional.TxType.REQUIRED)
public boolean isAssetInUse(final Asset asset) {
if (asset == null) {
throw new IllegalArgumentException("Can't verify if null is in use.");
}
return !asset.getItemAttachments().isEmpty();
}
@ -416,8 +425,7 @@ public class AssetManager {
/**
* Returns the path of an item as String.
*
* @param asset The {@link Asset} for which the path is
* generated.
* @param asset The {@link Asset} for which the path is generated.
* @param withContentSection Whether to include the content section into the
* path or not.
*
@ -521,6 +529,15 @@ public class AssetManager {
* shared asset an empty {@link Optional} is returned.
*/
public Optional<Folder> getAssetFolder(final Asset asset) {
if (asset == null) {
throw new IllegalArgumentException(
"Can't retrieve the folder for asset null.");
}
if (asset.getCategories() == null) {
return Optional.empty();
}
return asset.getCategories().stream()
.filter(categorization -> {
return CATEGORIZATION_TYPE_FOLDER.equals(

View File

@ -64,7 +64,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
@ -170,8 +169,7 @@ public class ContentItemManager {
*
* @param <T> The type of the content item.
* @param name The name (URL stub) of the new content item.
* @param section The content section in which the item is
* generated.
* @param section The content section in which the item is generated.
* @param folder The folder in which in the item is stored.
* @param workflowTemplate The template for the workflow to apply to the new
* item.
@ -321,9 +319,8 @@ public class ContentItemManager {
*
* @param item The item to copy.
* @param targetFolder The folder in which the copy is created. If the
* target folder is the same folder as the folder of the
* original item an index is appended to the name of the
* item.
* target folder is the same folder as the folder of the original item an
* index is appended to the name of the item.
*
* @return The copy of the item
*/
@ -447,9 +444,7 @@ public class ContentItemManager {
throw new RuntimeException(ex);
}
source.getAvailableLocales().forEach(
locale -> target.addValue(locale,
source.getValue(locale)));
copyLocalizedString(source, target);
} else if (propType != null
&& propType.isAssignableFrom(ContentItem.class)) {
@ -564,25 +559,19 @@ public class ContentItemManager {
return result;
}
private void copyAttachmentList(final AttachmentList list,
private void copyAttachmentList(final AttachmentList sourceList,
final ContentItem target) {
final AttachmentList targetList = new AttachmentList();
for (final Locale locale : list.getDescription().getAvailableLocales()) {
targetList.getDescription().addValue(
locale, list.getDescription().getValue(locale));
}
copyLocalizedString(sourceList.getDescription(), targetList.getDescription());
targetList.setItem(target);
targetList.setName(list.getName());
targetList.setOrder(list.getOrder());
for (Map.Entry<Locale, String> title : list.getTitle().getValues()
.entrySet()) {
targetList.getTitle().addValue(title.getKey(), title.getValue());
}
targetList.setName(sourceList.getName());
targetList.setOrder(sourceList.getOrder());
copyLocalizedString(sourceList.getTitle(), targetList.getTitle());
targetList.setUuid(UUID.randomUUID().toString());
entityManager.persist(list);
entityManager.persist(sourceList);
for (ItemAttachment<?> attachment : list.getAttachments()) {
for (ItemAttachment<?> attachment : sourceList.getAttachments()) {
if (assetManager.isShared(attachment.getAsset())) {
copySharedAssetAttachment(attachment, targetList);
} else {
@ -590,7 +579,7 @@ public class ContentItemManager {
}
}
entityManager.merge(list);
entityManager.merge(sourceList);
}
private void copySharedAssetAttachment(final ItemAttachment<?> attachment,
@ -616,6 +605,39 @@ public class ContentItemManager {
throw new UncheckedWrapperException(ex);
}
copyAsset(source, target);
entityManager.persist(target);
final ItemAttachment<Asset> targetAttachment = new ItemAttachment<>();
targetAttachment.setAsset(target);
targetAttachment.setSortKey(attachment.getSortKey());
targetAttachment.setUuid(UUID.randomUUID().toString());
entityManager.persist(targetAttachment);
targetAttachment.setAttachmentList(targetList);
targetList.addAttachment(targetAttachment);
entityManager.merge(targetAttachment);
}
public void copyAsset(final Asset source, final Asset target) {
if (source == null) {
throw new IllegalArgumentException("Source Asset can't be null.");
}
if (target == null) {
throw new IllegalArgumentException("Target Asset can't be null.");
}
if (!source.getClass().equals(target.getClass())) {
throw new IllegalArgumentException(String.format(
"Asset belong to different classes. source is instance of "
+ "\"%s\", target is instance of \"%s\". It is not "
+ "possible to use assets of diffierent classes "
+ "with this method",
source.getClass().getName(),
target.getClass().getName()));
}
final BeanInfo beanInfo;
try {
beanInfo = Introspector.getBeanInfo(source.getClass());
@ -623,8 +645,8 @@ public class ContentItemManager {
throw new UncheckedWrapperException(ex);
}
for (final PropertyDescriptor propertyDescriptor : beanInfo
.getPropertyDescriptors()) {
for (final PropertyDescriptor propertyDescriptor : beanInfo.
getPropertyDescriptors()) {
final String propertyName = propertyDescriptor.getName();
if ("objectId".equals(propertyName)
|| "uuid".equals(propertyName)
@ -653,9 +675,7 @@ public class ContentItemManager {
throw new UncheckedWrapperException(ex);
}
sourceStr.getAvailableLocales().forEach(
locale -> targetStr.addValue(locale,
sourceStr.getValue(locale)));
copyLocalizedString(sourceStr, targetStr);
} else {
final Object value;
try {
@ -669,18 +689,16 @@ public class ContentItemManager {
}
}
if (target.getUuid() == null || target.getUuid().isEmpty()) {
target.setUuid(UUID.randomUUID().toString());
}
}
entityManager.persist(target);
final ItemAttachment<Asset> targetAttachment = new ItemAttachment<>();
targetAttachment.setAsset(target);
targetAttachment.setSortKey(attachment.getSortKey());
targetAttachment.setUuid(UUID.randomUUID().toString());
entityManager.persist(targetAttachment);
targetAttachment.setAttachmentList(targetList);
targetList.addAttachment(targetAttachment);
entityManager.merge(targetAttachment);
private void copyLocalizedString(final LocalizedString source,
final LocalizedString target) {
for (final Locale locale : source.getAvailableLocales()) {
target.addValue(locale, source.getValue(locale));
}
}
/**
@ -726,6 +744,7 @@ public class ContentItemManager {
@RequiresPrivilege(ItemPrivileges.PUBLISH)
final ContentItem item,
final LifecycleDefinition lifecycleDefinition) {
if (item == null) {
throw new IllegalArgumentException(
"The item to publish can't be null.");
@ -741,17 +760,15 @@ public class ContentItemManager {
final ContentItem liveItem;
if (isLive(item)) {
final ContentItem oldLiveItem = getLiveVersion(
item, ContentItem.class).get();
unpublish(oldLiveItem);
}
// else {
liveItem = getLiveVersion(item, ContentItem.class).get();
// unpublish(oldLiveItem);
} else {
try {
liveItem = draftItem.getClass().newInstance();
} catch (InstantiationException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
// }
}
liveItem.setVersion(ContentItemVersion.PUBLISHING);
liveItem.setItemUuid(draftItem.getItemUuid());
@ -781,10 +798,78 @@ public class ContentItemManager {
categorization.getCategory(),
categorization.getType()));
for (AttachmentList attachmentList : item.getAttachments()) {
copyAttachmentList(attachmentList, liveItem);
for (int i = 0; i < draftItem.getAttachments().size(); i++) {
final AttachmentList sourceList = draftItem.getAttachments().get(i);
final AttachmentList targetList;
if (liveItem.getAttachments().size() < i + 1) {
targetList = new AttachmentList();
copyLocalizedString(sourceList.getDescription(),
targetList.getDescription());
targetList.setItem(liveItem);
liveItem.addAttachmentList(targetList);
targetList.setName(sourceList.getName());
copyLocalizedString(sourceList.getTitle(),
targetList.getTitle());
targetList.setOrder(sourceList.getOrder());
targetList.setUuid(UUID.randomUUID().toString());
} else {
targetList = liveItem.getAttachments().get(i);
}
for (int j = 0; j < sourceList.getAttachments().size(); j++) {
final ItemAttachment<?> sourceAttachment = sourceList.
getAttachments().get(j);
final ItemAttachment<Asset> targetAttachment;
if (targetList.getAttachments().size() < j + 1) {
targetAttachment = new ItemAttachment<>();
} else {
targetAttachment = (ItemAttachment<Asset>) targetList.
getAttachments().get(j);
}
if (!sourceAttachment.getAsset().equals(targetAttachment)) {
final Asset oldTargetAsset = targetAttachment.getAsset();
if (oldTargetAsset != null
&& !assetManager.isShared(oldTargetAsset)) {
targetAttachment.setAsset(null);
oldTargetAsset.removeItemAttachment(targetAttachment);
entityManager.remove(oldTargetAsset);
}
final Asset sourceAsset = sourceAttachment.getAsset();
final Asset targetAsset;
if (assetManager.isShared(sourceAttachment.getAsset())) {
targetAsset = sourceAttachment.getAsset();
} else {
try {
targetAsset = sourceAttachment.getAsset().getClass().
newInstance();
} catch (InstantiationException | IllegalAccessException ex) {
throw new UncheckedWrapperException(ex);
}
copyAsset(sourceAsset, targetAsset);
entityManager.persist(targetAsset);
}
targetAttachment.setAsset(targetAsset);
targetAttachment.setAttachmentList(targetList);
targetAttachment.setSortKey(sourceAttachment.getSortKey());
targetAttachment.setUuid(UUID.randomUUID().toString());
}
targetList.addAttachment(targetAttachment);
entityManager.persist(targetAttachment);
entityManager.merge(targetList);
}
}
// for (AttachmentList attachmentList : item.getAttachments()) {
// copyAttachmentList(attachmentList, liveItem);
// }
final BeanInfo beanInfo;
try {
beanInfo = Introspector.getBeanInfo(item.getClass());
@ -819,9 +904,7 @@ public class ContentItemManager {
throw new RuntimeException(ex);
}
source.getAvailableLocales().forEach(
locale -> target.addValue(locale, source.
getValue(locale)));
copyLocalizedString(source, target);
} else if (propType != null
&& propType.isAssignableFrom(ContentItem.class)) {
final ContentItem linkedItem;
@ -1060,9 +1143,9 @@ public class ContentItemManager {
* @param type Type of the content item.
*
* @return The live version of an item. If the item provided is already the
* live version the provided item is returned, otherwise the live
* version is returned. If there is no live version an empty
* {@link Optional} is returned.
* live version the provided item is returned, otherwise the live version is
* returned. If there is no live version an empty {@link Optional} is
* returned.
*/
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@ -1120,10 +1203,10 @@ public class ContentItemManager {
* @param type Type of the item.
*
* @return The draft version of the provided content item. If the provided
* item is the draft version the provided item is simply returned.
* Otherwise the draft version is retrieved from the database and is
* returned. Each content item has a draft version (otherwise
* something is seriously wrong with the database) this method will
* item is the draft version the provided item is simply returned. Otherwise
* the draft version is retrieved from the database and is returned. Each
* content item has a draft version (otherwise something is seriously wrong
* with the database) this method will
* <b>never</b> return {@code null}.
*/
@AuthorizationRequired

View File

@ -157,12 +157,12 @@
<ccm_core.ccm_objects_aud object_id="-10200"
rev="0"
revtype="0"
revend="6"
revend="5"
display_name="article2" />
<ccm_core.ccm_objects_aud object_id="-99200"
rev="0"
revtype="0"
revend="6"
revend="5"
display_name="article2" />
<ccm_core.ccm_objects_aud object_id="-10300"
rev="0"
@ -173,16 +173,13 @@
revtype="0"
display_name="news1" />
<ccm_core.ccm_objects_aud object_id="-10200"
rev="6"
rev="5"
revtype="1"
display_name="article2" />
<ccm_core.ccm_objects_aud object_id="-99300"
rev="6"
revtype="0"
display_name="article2" />
<ccm_core.ccm_objects_aud object_id="-99200"
rev="6"
revtype="2" />
rev="5"
revtype="1"
display_name="article2" />
<ccm_core.ccm_objects_aud object_id="-11100"
rev="0"
revtype="0"
@ -387,14 +384,12 @@
version="DRAFT"
content_type_id="-20200"/>
<ccm_cms.content_items_aud object_id="-10200"
rev="6"
rev="5"
item_uuid="acae860f-2ffa-450d-b486-054292f0dae6"
version="DRAFT"
content_type_id="-20100"/>
<ccm_cms.content_items_aud object_id="-99200"
rev="6" />
<ccm_cms.content_items_aud object_id="-99300"
rev="6"
rev="5"
item_uuid="00000000-0000-0000-0000-000000000000"
version="LIVE"
content_type_id="-20100"/>
@ -424,7 +419,7 @@
object_id="-10200"
localized_value="article2"
locale="en"
revend="6"
revend="5"
revtype="0" />
<ccm_cms.content_item_names_aud rev="0"
object_id="-10300"
@ -441,23 +436,23 @@
localized_value="article2"
locale="en"
revtype="0"
revend="6"/>
<ccm_cms.content_item_names_aud rev="6"
revend="5"/>
<ccm_cms.content_item_names_aud rev="5"
object_id="-10200"
localized_value="article2-edited"
locale="en"
revtype="0" />
<ccm_cms.content_item_names_aud rev="6"
<ccm_cms.content_item_names_aud rev="5"
object_id="-10200"
localized_value="article2"
locale="en"
revtype="2" />
<ccm_cms.content_item_names_aud rev="6"
<ccm_cms.content_item_names_aud rev="5"
object_id="-99300"
localized_value="article2-edited"
locale="en"
revtype="0" />
<ccm_cms.content_item_names_aud rev="6"
<ccm_cms.content_item_names_aud rev="5"
object_id="-99200"
localized_value="article2"
locale="en"
@ -504,22 +499,22 @@
localized_value="Article 2 Title"
locale="en"
revtype="0" />
<ccm_cms.content_item_titles_aud rev="6"
<ccm_cms.content_item_titles_aud rev="5"
object_id="-10200"
localized_value="Article has been edited"
locale="en"
revtype="0" />
<ccm_cms.content_item_titles_aud rev="6"
<ccm_cms.content_item_titles_aud rev="5"
object_id="-10200"
localized_value="Article 2"
locale="en"
revtype="2" />
<ccm_cms.content_item_titles_aud rev="6"
<ccm_cms.content_item_titles_aud rev="5"
object_id="-99300"
localized_value="Article has been edited"
locale="en"
revtype="0" />
<ccm_cms.content_item_titles_aud rev="6"
<ccm_cms.content_item_titles_aud rev="5"
object_id="-99200"
localized_value="Article 2 Title"
locale="en"
@ -568,29 +563,16 @@
revtype="0" />
<ccm_cms.article_texts_aud
rev="0"
revend="6"
object_id="-99200"
localized_value="Duis quis tincidunt elit. In pharetra justo sit amet ipsum dictum, at."
locale="en"
revtype="0" />
<ccm_cms.article_texts_aud
rev="6"
object_id="-99200"
localized_value="Duis quis tincidunt elit. In pharetra justo sit amet ipsum dictum, at."
locale="en"
revtype="2" />
<ccm_cms.article_texts_aud
rev="0"
object_id="-10300"
localized_value="Etiam euismod lacus laoreet sodales ultricies. Pellentesque non elit vitae purus sagittis."
locale="en"
revtype="0" />
<ccm_cms.article_texts_aud
rev="6"
object_id="-99300"
localized_value="Duis quis tincidunt elit. In pharetra justo sit amet ipsum dictum, at."
locale="en"
revtype="0" />
<ccm_cms.news object_id="-10400"
news_date="2016-08-08"