diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemManager.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemManager.java index 7dbfba6ce..4591657d5 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemManager.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemManager.java @@ -43,6 +43,12 @@ public class ContentItemManager { @Inject private ContentItemRepository contentItemRepo; + @Inject + private ContentTypeRepository typeRepo; + + @Inject + private ContentSectionManager sectionManager; + /** * Creates a new content item in the provided content section and folder * with the default lifecycle and workflow. @@ -51,20 +57,36 @@ public class ContentItemManager { * {@link ContentSection#rootDocumentsFolder} of the provided content * section. Otherwise an {@link IllegalArgumentException} is thrown. * - * @param The type of the content item. - * @param name The name (URL stub) of the new content item. + * @param 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 folder The folder in which in the item is stored. - * @param type The type of the new content item. + * @param folder The folder in which in the item is stored. + * @param type The type of the new content item. * * @return The new content item. */ public T createContentItem( - final String name, - final ContentSection section, - final Category folder, - final Class type) { - throw new UnsupportedOperationException(); + final String name, + final ContentSection section, + final Category folder, + final Class type) { + + final Optional 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. * Otherwise an {@link IllegalArgumentException} is thrown. * - * @param 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 folder The folder in which in the item is stored. + * @param 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 folder The folder in which in the item is stored. * @param workflowTemplate * @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. */ public T createContentItem( - final String name, - final ContentSection section, - final Category folder, - final WorkflowTemplate workflowTemplate, - final LifecycleDefinition lifecycleDefinition, - final Class type) { + final String name, + final ContentSection section, + final Category folder, + final WorkflowTemplate workflowTemplate, + final LifecycleDefinition lifecycleDefinition, + final Class type) { throw new UnsupportedOperationException(); } @@ -104,7 +127,7 @@ public class ContentItemManager { * only moves the draft version of the item. The live version is moved after * 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. */ 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 * {@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 - * 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. */ public void copy(final ContentItem item, final Category targetFolder) { throw new UnsupportedOperationException(); @@ -151,7 +175,7 @@ public class ContentItemManager { * @param item The item * * @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) { throw new UnsupportedOperationException(); @@ -160,48 +184,48 @@ public class ContentItemManager { /** * Retrieves the live version of the provided content item if any. * - * @param Type of the content item. + * @param Type of the content item. * @param item The item of which the live version should be retrieved. * @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. */ public Optional getLiveVersion( - final ContentItem item, - final Class type) { + final ContentItem item, + final Class type) { throw new UnsupportedOperationException(); } /** * Retrieves the pending versions of an item if there are any. * - * @param Type of the content item to retrieve. + * @param Type of the content item to retrieve. * @param item The item of which the pending versions are retrieved. * @param type Type of the content item to retrieve. * * @return A list of the pending versions of the item. */ public List getPendingVersions( - final ContentItem item, - final Class type) { + final ContentItem item, + final Class type) { throw new UnsupportedOperationException(); } /** * Retrieves the draft version * - * @param Type of the item. + * @param Type of the item. * @param item The item of which the draft version is retrieved. * @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 * never return {@code null}. */ public T getDraftVersion(final ContentItem item, @@ -219,7 +243,9 @@ public class ContentItemManager { * {@code /research/computer-science/artificial-intelligence/neural-nets}. * * @param item The item which path is generated. + * * @return The path of the content item + * * @see #getItemPath(org.librecms.contentsection.ContentItem, boolean) */ public String getItemPath(final ContentItem item) { @@ -240,18 +266,20 @@ public class ContentItemManager { * {@code info}, the path including the content section would be * {@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 - * path. + * path. + * * @return The path of the content item + * * @see #getItemPath(org.librecms.contentsection.ContentItem, boolean) */ public String getItemPath(final ContentItem item, final boolean withContentSection) { final List result = item.getCategories().stream(). - filter(categorization -> CmsConstants.CATEGORIZATION_TYPE_FOLDER. - equals(categorization.getType())) - .collect(Collectors.toList()); + filter(categorization -> CmsConstants.CATEGORIZATION_TYPE_FOLDER. + equals(categorization.getType())) + .collect(Collectors.toList()); if (result.isEmpty()) { return item.getDisplayName(); @@ -272,40 +300,41 @@ public class ContentItemManager { if (withContentSection) { final String sectionName = item.getContentType(). - getContentSection().getDisplayName(); + getContentSection().getDisplayName(); return String.format( - "%s/%s", sectionName, path); + "%s/%s", sectionName, path); } else { return String.format("/%s", path); } } } - + /** * Creates as list of the folders in which is item is placed. - * + * * @param item - * @return + * + * @return */ public List getItemFolders(final ContentItem item) { final List result = item.getCategories().stream(). - filter(categorization -> CmsConstants.CATEGORIZATION_TYPE_FOLDER. - equals(categorization.getType())) - .collect(Collectors.toList()); - + filter(categorization -> CmsConstants.CATEGORIZATION_TYPE_FOLDER. + equals(categorization.getType())) + .collect(Collectors.toList()); + final List folders = new ArrayList<>(); if (!result.isEmpty()) { - Category current = result.get(0).getCategory(); - folders.add(current); - - while(current.getParentCategory()!= null) { - current = current.getParentCategory(); - folders.add(current); - } - - Collections.reverse(folders); - return folders; - } + Category current = result.get(0).getCategory(); + folders.add(current); + + while (current.getParentCategory() != null) { + current = current.getParentCategory(); + folders.add(current); + } + + Collections.reverse(folders); + return folders; + } return folders; } diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentType.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentType.java index 1ac7a509a..f58f68343 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentType.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentType.java @@ -52,9 +52,14 @@ import javax.persistence.Table; @Table(name = "CONTENT_TYPES", schema = DB_SCHEMA) @NamedQueries({ @NamedQuery( - name = "ContentType.findByContenSection", + name = "ContentType.findByContentSection", 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 { @@ -165,7 +170,8 @@ public class ContentType extends CcmObject implements Serializable { return defaultLifecycle; } - protected void setDefaultLifecycle(final LifecycleDefinition defaultLifecycle) { + protected void setDefaultLifecycle( + final LifecycleDefinition defaultLifecycle) { this.defaultLifecycle = defaultLifecycle; } diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentTypeRepository.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentTypeRepository.java index a39638840..4f8db3f6a 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentTypeRepository.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentTypeRepository.java @@ -20,15 +20,19 @@ package org.librecms.contentsection; import org.libreccm.core.AbstractEntityRepository; +import java.util.List; +import java.util.Optional; + import javax.enterprise.context.RequestScoped; +import javax.persistence.TypedQuery; /** * * @author Jens Pelzetter */ @RequestScoped -public class ContentTypeRepository - extends AbstractEntityRepository{ +public class ContentTypeRepository + extends AbstractEntityRepository { @Override public Class getEntityClass() { @@ -39,5 +43,128 @@ public class ContentTypeRepository public boolean isNew(final ContentType type) { 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 findByContentSection(final ContentSection section) { + if (section == null) { + throw new IllegalArgumentException( + "Parameter section of method " + + "ContentTypeRepo#findByContentSection(" + + "ContentSection section) can't be null."); + } + + final TypedQuery 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 findByContentSectionAndClass( + final ContentSection section, + final Class clazz) { + + if (section == null) { + throw new IllegalArgumentException( + "Parameter section of method " + + "ContentTypeRepo#findByContentSectionAndClass(" + + "ContentSection section, " + + "Class clazz) can't be null."); + } + if (clazz == null) { + throw new IllegalArgumentException( + "Parameter clazz of method " + + "ContentTypeRepo#findByContentSectionAndClass(" + + "ContentSection section, " + + "Class 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 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 query = getEntityManager() + .createNamedQuery("ContentType.findByContentSectionAndClass", + ContentType.class); + query.setParameter("contentSection", section); + query.setParameter("clazz", className); + + final List 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)); + } + } + }