CCM NG: Additional queries for ContentType

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4225 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2016-08-16 17:36:49 +00:00
parent 172b99bb0a
commit 0838a6df5f
3 changed files with 232 additions and 70 deletions

View File

@ -43,6 +43,12 @@ public class ContentItemManager {
@Inject @Inject
private ContentItemRepository contentItemRepo; private ContentItemRepository contentItemRepo;
@Inject
private ContentTypeRepository typeRepo;
@Inject
private ContentSectionManager sectionManager;
/** /**
* Creates a new content item in the provided content section and folder * Creates a new content item in the provided content section and folder
* with the default lifecycle and workflow. * with the default lifecycle and workflow.
@ -51,20 +57,36 @@ public class ContentItemManager {
* {@link ContentSection#rootDocumentsFolder} of the provided content * {@link ContentSection#rootDocumentsFolder} of the provided content
* section. Otherwise an {@link IllegalArgumentException} is thrown. * section. Otherwise an {@link IllegalArgumentException} is thrown.
* *
* @param <T> The type of the content item. * @param <T> The type of the content item.
* @param name The name (URL stub) of the new 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 folder The folder in which in the item is stored.
* @param type The type of the new content item. * @param type The type of the new content item.
* *
* @return The new content item. * @return The new content item.
*/ */
public <T extends ContentItem> T createContentItem( public <T extends ContentItem> T createContentItem(
final String name, final String name,
final ContentSection section, final ContentSection section,
final Category folder, final Category folder,
final Class<T> type) { final Class<T> type) {
throw new UnsupportedOperationException();
final Optional<ContentType> contentType = typeRepo
.findByContentSectionAndClass(section, type);
if (!contentType.isPresent()) {
throw new IllegalArgumentException(String.format(
"ContentSection \"%s\" has no content type for \"%s\".",
section.getLabel(),
type.getName()));
}
return createContentItem(name,
section,
folder,
contentType.get().getDefaultWorkflow(),
contentType.get().getDefaultLifecycle(),
type);
} }
/** /**
@ -79,23 +101,24 @@ public class ContentItemManager {
* {@link WorkflowTemplate} must be defined in the provided content section. * {@link WorkflowTemplate} must be defined in the provided content section.
* Otherwise an {@link IllegalArgumentException} is thrown. * Otherwise an {@link IllegalArgumentException} is thrown.
* *
* @param <T> The type of the content item. * @param <T> The type of the content item.
* @param name The name (URL stub) of the new 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
* @param folder The folder in which in the item is stored. * generated.
* @param folder The folder in which in the item is stored.
* @param workflowTemplate * @param workflowTemplate
* @param lifecycleDefinition * @param lifecycleDefinition
* @param type The type of the new content item. * @param type The type of the new content item.
* *
* @return The new content item. * @return The new content item.
*/ */
public <T extends ContentItem> T createContentItem( public <T extends ContentItem> T createContentItem(
final String name, final String name,
final ContentSection section, final ContentSection section,
final Category folder, final Category folder,
final WorkflowTemplate workflowTemplate, final WorkflowTemplate workflowTemplate,
final LifecycleDefinition lifecycleDefinition, final LifecycleDefinition lifecycleDefinition,
final Class<T> type) { final Class<T> type) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -104,7 +127,7 @@ public class ContentItemManager {
* only moves the draft version of the item. The live version is moved after * only moves the draft version of the item. The live version is moved after
* a the item is republished. * a the item is republished.
* *
* @param item The item to move. * @param item The item to move.
* @param targetFolder The folder to which the item is moved. * @param targetFolder The folder to which the item is moved.
*/ */
public void move(final ContentItem item, final Category targetFolder) { public void move(final ContentItem item, final Category targetFolder) {
@ -115,10 +138,11 @@ public class ContentItemManager {
* Creates an copy of the draft version of the item in the provided * Creates an copy of the draft version of the item in the provided
* {@code targetFolder}. * {@code targetFolder}.
* *
* @param item The item to copy. * @param item The item to copy.
* @param targetFolder The folder in which the copy is created. If the * @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 * target folder is the same folder as the folder of the
* index is appended to the name of the item. * original item an index is appended to the name of the
* item.
*/ */
public void copy(final ContentItem item, final Category targetFolder) { public void copy(final ContentItem item, final Category targetFolder) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
@ -151,7 +175,7 @@ public class ContentItemManager {
* @param item The item * @param item The item
* *
* @return {@code true} if the content item has a live version, * @return {@code true} if the content item has a live version,
* {@code false} if not. * {@code false} if not.
*/ */
public boolean isLive(final ContentItem item) { public boolean isLive(final ContentItem item) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
@ -160,48 +184,48 @@ public class ContentItemManager {
/** /**
* Retrieves the live version of the provided content item if any. * Retrieves the live version of the provided content item if any.
* *
* @param <T> Type of the content item. * @param <T> Type of the content item.
* @param item The item of which the live version should be retrieved. * @param item The item of which the live version should be retrieved.
* @param type Type of the content item. * @param type Type of the content item.
* *
* @return The live version of an item. If the item provided is already the * @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 * live version the provided item is returned, otherwise the live
* returned. If there is no live version an empty {@link Optional} is * version is returned. If there is no live version an empty
* returned. * {@link Optional} is returned.
*/ */
public <T extends ContentItem> Optional<T> getLiveVersion( public <T extends ContentItem> Optional<T> getLiveVersion(
final ContentItem item, final ContentItem item,
final Class<T> type) { final Class<T> type) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
/** /**
* Retrieves the pending versions of an item if there are any. * Retrieves the pending versions of an item if there are any.
* *
* @param <T> Type of the content item to retrieve. * @param <T> Type of the content item to retrieve.
* @param item The item of which the pending versions are retrieved. * @param item The item of which the pending versions are retrieved.
* @param type Type of the content item to retrieve. * @param type Type of the content item to retrieve.
* *
* @return A list of the pending versions of the item. * @return A list of the pending versions of the item.
*/ */
public <T extends ContentItem> List<T> getPendingVersions( public <T extends ContentItem> List<T> getPendingVersions(
final ContentItem item, final ContentItem item,
final Class<T> type) { final Class<T> type) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
/** /**
* Retrieves the draft version * Retrieves the draft version
* *
* @param <T> Type of the item. * @param <T> Type of the item.
* @param item The item of which the draft version is retrieved. * @param item The item of which the draft version is retrieved.
* @param type Type of the item. * @param type Type of the item.
* *
* @return The draft version of the provided content item. If the provided * @return The draft version of the provided content item. If the provided
* item is the draft version the provided item is simply returned. Otherwise * item is the draft version the provided item is simply returned.
* the draft version is retrieved from the database and is returned. Each * Otherwise the draft version is retrieved from the database and is
* content item has a draft version (otherwise something is seriously wrong * returned. Each content item has a draft version (otherwise
* with the database) this method will * something is seriously wrong with the database) this method will
* <b>never</b> return {@code null}. * <b>never</b> return {@code null}.
*/ */
public <T extends ContentItem> T getDraftVersion(final ContentItem item, public <T extends ContentItem> T getDraftVersion(final ContentItem item,
@ -219,7 +243,9 @@ public class ContentItemManager {
* {@code /research/computer-science/artificial-intelligence/neural-nets}. * {@code /research/computer-science/artificial-intelligence/neural-nets}.
* *
* @param item The item which path is generated. * @param item The item which path is generated.
*
* @return The path of the content item * @return The path of the content item
*
* @see #getItemPath(org.librecms.contentsection.ContentItem, boolean) * @see #getItemPath(org.librecms.contentsection.ContentItem, boolean)
*/ */
public String getItemPath(final ContentItem item) { public String getItemPath(final ContentItem item) {
@ -240,18 +266,20 @@ public class ContentItemManager {
* {@code info}, the path including the content section would be * {@code info}, the path including the content section would be
* {@link info:/research/computer-science/artificial-intelligence/neural-nets}. * {@link info:/research/computer-science/artificial-intelligence/neural-nets}.
* *
* @param item The item which path is generated. * @param item The item which path is generated.
* @param withContentSection Wether to include the content section into the * @param withContentSection Wether to include the content section into the
* path. * path.
*
* @return The path of the content item * @return The path of the content item
*
* @see #getItemPath(org.librecms.contentsection.ContentItem, boolean) * @see #getItemPath(org.librecms.contentsection.ContentItem, boolean)
*/ */
public String getItemPath(final ContentItem item, public String getItemPath(final ContentItem item,
final boolean withContentSection) { final boolean withContentSection) {
final List<Categorization> result = item.getCategories().stream(). final List<Categorization> result = item.getCategories().stream().
filter(categorization -> CmsConstants.CATEGORIZATION_TYPE_FOLDER. filter(categorization -> CmsConstants.CATEGORIZATION_TYPE_FOLDER.
equals(categorization.getType())) equals(categorization.getType()))
.collect(Collectors.toList()); .collect(Collectors.toList());
if (result.isEmpty()) { if (result.isEmpty()) {
return item.getDisplayName(); return item.getDisplayName();
@ -272,40 +300,41 @@ public class ContentItemManager {
if (withContentSection) { if (withContentSection) {
final String sectionName = item.getContentType(). final String sectionName = item.getContentType().
getContentSection().getDisplayName(); getContentSection().getDisplayName();
return String.format( return String.format(
"%s/%s", sectionName, path); "%s/%s", sectionName, path);
} else { } else {
return String.format("/%s", path); return String.format("/%s", path);
} }
} }
} }
/** /**
* Creates as list of the folders in which is item is placed. * Creates as list of the folders in which is item is placed.
* *
* @param item * @param item
* @return *
* @return
*/ */
public List<Category> getItemFolders(final ContentItem item) { public List<Category> getItemFolders(final ContentItem item) {
final List<Categorization> result = item.getCategories().stream(). final List<Categorization> result = item.getCategories().stream().
filter(categorization -> CmsConstants.CATEGORIZATION_TYPE_FOLDER. filter(categorization -> CmsConstants.CATEGORIZATION_TYPE_FOLDER.
equals(categorization.getType())) equals(categorization.getType()))
.collect(Collectors.toList()); .collect(Collectors.toList());
final List<Category> folders = new ArrayList<>(); final List<Category> folders = new ArrayList<>();
if (!result.isEmpty()) { if (!result.isEmpty()) {
Category current = result.get(0).getCategory(); Category current = result.get(0).getCategory();
folders.add(current); folders.add(current);
while(current.getParentCategory()!= null) { while (current.getParentCategory() != null) {
current = current.getParentCategory(); current = current.getParentCategory();
folders.add(current); folders.add(current);
} }
Collections.reverse(folders); Collections.reverse(folders);
return folders; return folders;
} }
return folders; return folders;
} }

View File

@ -52,9 +52,14 @@ import javax.persistence.Table;
@Table(name = "CONTENT_TYPES", schema = DB_SCHEMA) @Table(name = "CONTENT_TYPES", schema = DB_SCHEMA)
@NamedQueries({ @NamedQueries({
@NamedQuery( @NamedQuery(
name = "ContentType.findByContenSection", name = "ContentType.findByContentSection",
query = "SELECT c FROM ContentType c " query = "SELECT c FROM ContentType c "
+ "WHERE c.contentSection = :contentSection") + "WHERE c.contentSection = :contentSection"),
@NamedQuery(
name = "ContentType.findByContentSectionAndClass",
query = "SELECT c FROM ContentType c "
+ "WHERE c.contentSection = :contentSection "
+ "AND c.contentItemClass =:clazz")
}) })
public class ContentType extends CcmObject implements Serializable { public class ContentType extends CcmObject implements Serializable {
@ -165,7 +170,8 @@ public class ContentType extends CcmObject implements Serializable {
return defaultLifecycle; return defaultLifecycle;
} }
protected void setDefaultLifecycle(final LifecycleDefinition defaultLifecycle) { protected void setDefaultLifecycle(
final LifecycleDefinition defaultLifecycle) {
this.defaultLifecycle = defaultLifecycle; this.defaultLifecycle = defaultLifecycle;
} }

View File

@ -20,15 +20,19 @@ package org.librecms.contentsection;
import org.libreccm.core.AbstractEntityRepository; import org.libreccm.core.AbstractEntityRepository;
import java.util.List;
import java.util.Optional;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.persistence.TypedQuery;
/** /**
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
@RequestScoped @RequestScoped
public class ContentTypeRepository public class ContentTypeRepository
extends AbstractEntityRepository<Long, ContentType>{ extends AbstractEntityRepository<Long, ContentType> {
@Override @Override
public Class<ContentType> getEntityClass() { public Class<ContentType> getEntityClass() {
@ -39,5 +43,128 @@ public class ContentTypeRepository
public boolean isNew(final ContentType type) { public boolean isNew(final ContentType type) {
return type.getObjectId() == 0; return type.getObjectId() == 0;
} }
/**
* Finds all {@link ContentType}s of a specific content section.
*
* @param section The section whose {@link ContentTyp}s are retrieved. Can't
* be {@code null}.
*
* @return A list of all {@link ContentType}s of the provided section.
*/
public List<ContentType> findByContentSection(final ContentSection section) {
if (section == null) {
throw new IllegalArgumentException(
"Parameter section of method "
+ "ContentTypeRepo#findByContentSection("
+ "ContentSection section) can't be null.");
}
final TypedQuery<ContentType> query = getEntityManager()
.createNamedQuery("ContentType.findByContentSection",
ContentType.class);
query.setParameter("contentSection", section);
return query.getResultList();
}
/**
* Retrieves a specific {@link ContentType}.
*
* @param section The section associated with the {@link ContentType} to
* retrieve. Can't be {@code null}.
* @param clazz The subclass of the {@link ContentItem} class associated
* with the content type. Can't be {@code null}.
*
* @return The requested {@link ContentType} if their is a
* {@link ContentType} for the provided class in the provided
* section. Otherwise the returned {@link Optional} will be empty.
*/
public Optional<ContentType> findByContentSectionAndClass(
final ContentSection section,
final Class<? extends ContentItem> clazz) {
if (section == null) {
throw new IllegalArgumentException(
"Parameter section of method "
+ "ContentTypeRepo#findByContentSectionAndClass("
+ "ContentSection section, "
+ "Class<? extends ContentItem> clazz) can't be null.");
}
if (clazz == null) {
throw new IllegalArgumentException(
"Parameter clazz of method "
+ "ContentTypeRepo#findByContentSectionAndClass("
+ "ContentSection section, "
+ "Class<? extends ContentItem> clazz) can't be null.");
}
return findByContentSectionAndClass(section, clazz.getName());
}
/**
* Retrieves a specific {@link ContentType}.
*
* @param section The section associated with the {@link ContentType} to
* retrieve.
* @param className The name of the subclass of the {@link ContentItem}
* class associated with the content type. The class must
* be a subclass of {@link ContentItem}.
*
* @return The requested {@link ContentType} if their is a
* {@link ContentType} for the provided class in the provided
* section. Otherwise the returned {@link Optional} will be empty.
*/
public Optional<ContentType> findByContentSectionAndClass(
final ContentSection section,
final String className) {
if (section == null) {
throw new IllegalArgumentException(
"Parameter section of method "
+ "ContentTypeRepo#findByContentSectionAndClass("
+ "ContentSection section, "
+ "String className) can't be null.");
}
if (className == null || className.isEmpty()) {
throw new IllegalArgumentException(
"Parameter className of method "
+ "ContentTypeRepo#findByContentSectionAndClass("
+ "ContentSection section, "
+ "String className) can't be null.");
}
try {
final Class<?> clazz = Class.forName(className);
if (!clazz.isAssignableFrom(ContentItem.class)) {
throw new IllegalArgumentException(String.format(
"The provided class \"%s\" is not a subclass of \"%s\".",
className,
ContentItem.class.getName()));
}
} catch (ClassNotFoundException ex) {
throw new IllegalArgumentException(String.format(
"Class \"%s\" does not exist.", className));
}
final TypedQuery<ContentType> query = getEntityManager()
.createNamedQuery("ContentType.findByContentSectionAndClass",
ContentType.class);
query.setParameter("contentSection", section);
query.setParameter("clazz", className);
final List<ContentType> result = query.getResultList();
if (result.isEmpty()) {
return Optional.empty();
} else if (result.size() > 1) {
throw new RuntimeException(String.format(
"More than one ContentType for section \"%s\" and type \"%s\" "
+ "found. This is an invalid state. Check your installation"
+ "immediatly.",
section.getLabel(),
className));
} else {
return Optional.of(result.get(0));
}
}
} }