diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemCreateForm.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemCreateForm.java new file mode 100644 index 000000000..938efc4da --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemCreateForm.java @@ -0,0 +1,29 @@ +/* + * 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 com.arsdigita.cms.ui.item; + +/** + * + * @author Jens Pelzetter + */ +public class ItemCreateForm { + + //Placeholder + +} diff --git a/ccm-cms/src/main/java/org/librecms/contenttypes/AuthoringKit.java b/ccm-cms/src/main/java/org/librecms/contenttypes/AuthoringKit.java new file mode 100644 index 000000000..e1be1afbf --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contenttypes/AuthoringKit.java @@ -0,0 +1,40 @@ +/* + * 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.contenttypes; + +import com.arsdigita.cms.ui.item.ItemCreateForm; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * + * @author Jens Pelzetter + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface AuthoringKit { + + Class createComponent(); + + AuthoringStep[] steps(); + +} diff --git a/ccm-cms/src/main/java/org/librecms/contenttypes/AuthoringKitInfo.java b/ccm-cms/src/main/java/org/librecms/contenttypes/AuthoringKitInfo.java new file mode 100644 index 000000000..24f6bbfd3 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contenttypes/AuthoringKitInfo.java @@ -0,0 +1,126 @@ +/* + * 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.contenttypes; + +import com.arsdigita.cms.ui.item.ItemCreateForm; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * Encapsulates the informations about an authoring kit. + * + * @author Jens Pelzetter + */ +public class AuthoringKitInfo { + + /** + * The create component (the form used to collect the mandatory data for + * the content type). + */ + private Class createComponent; + + /** + * The authoring steps of the authoring kit. + */ + private List authoringSteps; + + protected AuthoringKitInfo() { + authoringSteps = new ArrayList<>(); + } + + public Class getCreateComponent() { + return createComponent; + } + + public void setCreateComponent( + final Class createComponent) { + + this.createComponent = createComponent; + } + + public List getAuthoringSteps() { + return Collections.unmodifiableList(authoringSteps); + } + + protected void setAuthoringSteps( + final List authoringSteps) { + this.authoringSteps = authoringSteps; + } + + protected void addAuthoringStep(final AuthoringStepInfo authoringStep) { + authoringSteps.add(authoringStep); + } + + protected void removeAuthoringStep(final AuthoringStepInfo authoringStep) { + authoringSteps.remove(authoringStep); + } + + @Override + public int hashCode() { + int hash = 3; + hash = 59 * hash + Objects.hashCode(createComponent); + hash = 59 * hash + Objects.hashCode(authoringSteps); + return hash; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof AuthoringKitInfo)) { + return false; + } + final AuthoringKitInfo other = (AuthoringKitInfo) obj; + if (!other.canEqual(this)) { + return false; + } + if (!Objects.equals(this.createComponent, other.getCreateComponent())) { + return false; + } + return Objects.equals(this.authoringSteps, other.getAuthoringSteps()); + } + + public boolean canEqual(final Object obj) { + return obj instanceof AuthoringKitInfo; + } + + @Override + public final String toString() { + return toString(""); + } + + public String toString(final String data) { + return String.format("%s{ " + + "createComponent = \"%s\", " + + "authoringSteps = { %s }%s" + + " }", + super.toString(), + Objects.toString(createComponent), + Objects.toString(authoringSteps), + data); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/contenttypes/AuthoringStep.java b/ccm-cms/src/main/java/org/librecms/contenttypes/AuthoringStep.java new file mode 100644 index 000000000..ac25ed6df --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contenttypes/AuthoringStep.java @@ -0,0 +1,85 @@ +/* + * 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.contenttypes; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.Form; + +/** + * Annotation used inside the {@link AuthoringKit} annotation to describe the + * authoring steps belonging to an authoring kit. + * + * @author Jens Pelzetter + */ +public @interface AuthoringStep { + + /** + * Key of the label in the {@link #labelBundle()}. If blank (default) the + * simple name of the annotated class with the suffix {@code .label} is + * used. + * + * @return The label key of the authoring step. + */ + String labelKey() default ""; + + /** + * Bundle providing the localised label for the authoring step. If omitted + * the default bundle for the content type will be used. The default bundle + * is the fully qualified name of the content type class with the suffix + * {@code Bundle}. + * + * @return The bundle providing the label for the authoring step. + */ + String labelBundle() default ""; + + /** + * Key of the description in the {@link #descriptionBundle()}. If blank + * (default) the simple name of the annotated class with the suffix + * {@code .description} is used. + * + * @return The description key of the authoring step. + */ + String descriptionKey() default ""; + + /** + * Bundle providing the localised description for the authoring step. If + * omitted the default bundle for the content type will be used. The default + * bundle is the fully qualified name of the content type class with the + * suffix {@code Bundle}. + * + * @return The bundle providing the description for the authoring step. + */ + String descriptionBundle() default ""; + + /** + * The position of the authoring step. + * + * @return The position of the authoring step. + */ + int order(); + + /** + * The component (usually a {@link Form} providing the UI for the authoring + * step. + * + * @return The class providing the UI for the authoring step. + */ + Class component(); + +} diff --git a/ccm-cms/src/main/java/org/librecms/contenttypes/AuthoringStepInfo.java b/ccm-cms/src/main/java/org/librecms/contenttypes/AuthoringStepInfo.java new file mode 100644 index 000000000..97bdbc850 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contenttypes/AuthoringStepInfo.java @@ -0,0 +1,182 @@ +/* + * 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.contenttypes; + +import com.arsdigita.bebop.Component; + +import java.util.Objects; + +/** + * Encapsulates the information about an authoring step. + * + * @see AuthoringStep + * + * @author Jens Pelzetter + */ +public class AuthoringStepInfo { + + /** + * The bundle which provides the label for the authoring step. + */ + private String labelBundle; + /** + * The key of label for the authoring step in the {@link #labelBundle} + */ + private String labelKey; + /** + * The bundle which provides the description for the authoring step. + */ + private String descriptionBundle; + /** + * The key of the description for the authoring step in the + * {@link #descriptionBundle}. + */ + private String descriptionKey; + + private int order; + private Class component; + + protected AuthoringStepInfo() { + super(); + } + + public String getLabelBundle() { + return labelBundle; + } + + public void setLabelBundle(final String labelBundle) { + this.labelBundle = labelBundle; + } + + public String getLabelKey() { + return labelKey; + } + + public void setLabelKey(final String labelKey) { + this.labelKey = labelKey; + } + + public String getDescriptionBundle() { + return descriptionBundle; + } + + public void setDescriptionBundle(final String descriptionBundle) { + this.descriptionBundle = descriptionBundle; + } + + public String getDescriptionKey() { + return descriptionKey; + } + + public void setDescriptionKey(final String descriptionKey) { + this.descriptionKey = descriptionKey; + } + + public int getOrder() { + return order; + } + + public void setOrder(final int order) { + this.order = order; + } + + public Class getComponent() { + return component; + } + + public void setComponent(final Class component) { + this.component = component; + } + + @Override + public int hashCode() { + int hash = 5; + hash = 53 * hash + Objects.hashCode(labelBundle); + hash = 53 * hash + Objects.hashCode(labelKey); + hash = 53 * hash + Objects.hashCode(descriptionBundle); + hash = 53 * hash + Objects.hashCode(descriptionKey); + hash = 53 * hash + Objects.hashCode(order); + hash = 53 * hash + Objects.hashCode(component); + return hash; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof AuthoringStepInfo)) { + return false; + } + final AuthoringStepInfo other = (AuthoringStepInfo) obj; + if (!other.canEqual(this)) { + return false; + } + if (!Objects.equals(this.labelBundle, other.getLabelBundle())) { + return false; + } + if (!Objects.equals(this.labelKey, other.getLabelKey())) { + return false; + } + if (!Objects.equals(this.descriptionBundle, + other.getDescriptionBundle())) { + return false; + } + if (!Objects.equals(this.descriptionKey, other.getDescriptionKey())) { + return false; + } + + if (order != other.getOrder()) { + return false; + } + + return Objects.equals(this.component, other.getComponent()); + } + + public boolean canEqual(final Object obj) { + return obj instanceof AuthoringStepInfo; + } + + @Override + public final String toString() { + return toString(""); + } + + public String toString(final String data) { + return String.format("%s{ " + + "labelBundle = \"%s\"," + + "labelKey = \"%s\", " + + "descriptionBundle = \"%s\"," + + "descriptionKey = \"%s\"," + + "order = %d, " + + "component = \"%s\"%s }", + super.toString(), + labelBundle, + labelKey, + descriptionKey, + descriptionBundle, + order, + Objects.toString(component), + data); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/contenttypes/ContentTypeDescription.java b/ccm-cms/src/main/java/org/librecms/contenttypes/ContentTypeDescription.java new file mode 100644 index 000000000..9c4ee990b --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contenttypes/ContentTypeDescription.java @@ -0,0 +1,81 @@ +/* + * 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.contenttypes; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation can be used to customise the keys and bundles used to + * retrieve the label and the description of a content type. + * + * If the annotation is not present or if one of the values in this annotation + * is omitted the default values are used. + * + * @author Jens Pelzetter + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ContentTypeDescription { + + /** + * The key of the label for the content type in the label bundle. Default + * value is {@code label}. + * + * @return The key for label of the content type. + */ + String labelKey() default ""; + + /** + * The bundle which provides the label for the content type. Default is the + * fully qualified class name of the annotated content item class with the + * suffix {@code Bundle}. For example the default bundle for the content + * type {@code org.librecms.contenttypes.Article} is + * {@code org.librecms.contenttypes.ArticleBundle}. + * + * + * @return The fully qualified name of the bundle providing the label for + * the content type. + */ + String labelBundle() default ""; + + /** + * The key of the description for the content type in the label bundle. + * Default value is {@code descripion}. + * + * @return The key for description of the content type. + */ + String descriptionKey() default ""; + + /** + * The bundle which provides the description for the content type. Default + * is the fully qualified class name of the annotated content item class + * with the suffix {@code Bundle}. For example the default bundle for the + * content type {@code org.librecms.contenttypes.Article} is + * {@code org.librecms.contenttypes.ArticleBundle}. + * + * + * @return The fully qualified name of the bundle providing the label for + * the content type. + */ + String descriptionBundle() default ""; + +} diff --git a/ccm-cms/src/main/java/org/librecms/contenttypes/ContentTypeInfo.java b/ccm-cms/src/main/java/org/librecms/contenttypes/ContentTypeInfo.java new file mode 100644 index 000000000..8659430fc --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contenttypes/ContentTypeInfo.java @@ -0,0 +1,177 @@ +/* + * 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.contenttypes; + +import org.librecms.contentsection.ContentItem; + +import java.util.Objects; + +/** + * A class encapsulating all informations about a available Content Type. + * + * @author Jens Pelzetter + */ +public class ContentTypeInfo { + + /** + * The bundle which provides the localisable label for the content type. + */ + private String labelBundle; + /** + * The key of the label in the {@link #labelBundle}. + */ + private String labelKey; + /** + * The bundle which provides the description of the content type. + */ + private String descriptionBundle; + /** + * The key of the description of the content type in the + * {@link #descriptionBundle}. + */ + private String descriptionKey; + + private Class contentItemClass; + private AuthoringKitInfo authoringKit; + + public String getLabelBundle() { + return labelBundle; + } + + public void setLabelBundle(final String labelBundle) { + this.labelBundle = labelBundle; + } + + public String getLabelKey() { + return labelKey; + } + + public void setLabelKey(final String labelKey) { + this.labelKey = labelKey; + } + + public String getDescriptionBundle() { + return descriptionBundle; + } + + public void setDescriptionBundle(final String descriptionBundle) { + this.descriptionBundle = descriptionBundle; + } + + public String getDescriptionKey() { + return descriptionKey; + } + + public void setDescriptionKey(final String descriptionKey) { + this.descriptionKey = descriptionKey; + } + + public Class getContentItemClass() { + return contentItemClass; + } + + public void setContentItemClass( + final Class contentItemClass) { + this.contentItemClass = contentItemClass; + } + + public AuthoringKitInfo getAuthoringKit() { + return authoringKit; + } + + public void setAuthoringKit(final AuthoringKitInfo authoringKit) { + this.authoringKit = authoringKit; + } + + @Override + public int hashCode() { + int hash = 3; + hash = 97 * hash + Objects.hashCode(labelBundle); + hash = 97 * hash + Objects.hashCode(labelKey); + hash = 97 * hash + Objects.hashCode(descriptionBundle); + hash = 97 * hash + Objects.hashCode(descriptionKey); + hash = 97 * hash + Objects.hashCode(contentItemClass); + hash = 97 * hash + Objects.hashCode(authoringKit); + return hash; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof ContentTypeInfo)) { + return false; + } + final ContentTypeInfo other = (ContentTypeInfo) obj; + if (!other.canEqual(this)) { + return false; + } + if (!Objects.equals(labelBundle, other.getLabelBundle())) { + return false; + } + if (!Objects.equals(labelKey, other.getLabelKey())) { + return false; + } + if (!Objects.equals(descriptionBundle, other.getDescriptionBundle())) { + return false; + } + if (!Objects.equals(descriptionKey, other.getDescriptionKey())) { + return false; + } + + if (!Objects.equals(contentItemClass, other.getContentItemClass())) { + return false; + } + + return Objects.equals(authoringKit, other.getAuthoringKit()); + } + + public boolean canEqual(final Object obj) { + return obj instanceof ContentTypeInfo; + } + + @Override + public final String toString() { + return toString(""); + } + + public String toString(final String data) { + return String.format("%s{ " + + "labelBundle = \"%s\", " + + "labelKey = \"%s\", " + + "descriptionBundle = \"%s\", " + + "descriptionKey = \"%s\"," + + "contentItemClass = \"%s\", " + + "authoringKit = { %s }%s" + + " }", + super.toString(), + labelBundle, + labelKey, + descriptionBundle, + descriptionKey, + Objects.toString(contentItemClass), + Objects.toString(authoringKit), + data); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/contenttypes/ContentTypeManager.java b/ccm-cms/src/main/java/org/librecms/contenttypes/ContentTypeManager.java new file mode 100644 index 000000000..f196f4f27 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contenttypes/ContentTypeManager.java @@ -0,0 +1,220 @@ +/* + * 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.contenttypes; + +import org.libreccm.modules.CcmModule; +import org.librecms.contentsection.ContentItem; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.ServiceLoader; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.stream.Collectors; + +import javax.annotation.PostConstruct; +import javax.enterprise.context.RequestScoped; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +public class ContentTypeManager { + + private static final String DEFAULT_DESCRIPTION_KEY = "description"; + private static final String DEFAULT_LABEL_KEY = "label"; + + /** + * A list of all content type currently available. + */ + private List availableContentTypes; + + /** + * Initialises the class (is called by CDI). This method is called by the + * CDI container after an instance of this class has been created by the CDI + * container. This method fills the list {@link #availableContentTypes}. + */ + @PostConstruct + protected void initialize() { + final ServiceLoader modules = ServiceLoader.load( + CcmModule.class); + + final SortedSet> types = new TreeSet<>( + (type1, type2) -> type1.getName().compareTo(type2.getName()) + ); + + for (final CcmModule module : modules) { + final ContentTypes annotation = module.getClass().getAnnotation( + ContentTypes.class); + + if (annotation == null) { + continue; + } + + final List> moduleTypes = Arrays + .stream(annotation.value()).collect(Collectors.toList()); + + types.addAll(moduleTypes); + } + + availableContentTypes = types.stream() + .filter(type -> type.getAnnotation(AuthoringKit.class) != null) + .map(contentTypeClass -> createContentTypeInfo(contentTypeClass)) + .collect(Collectors.toList()); + } + + /** + * Helper method for creating the info object for a content type. + * + * @param contentTypeClass The class which provides the implementation of + * the content type. + * + * @return A {@link ContentTypeInfo} object describing the content type. + */ + private ContentTypeInfo createContentTypeInfo( + final Class contentTypeClass) { + + final ContentTypeInfo contentTypeInfo = new ContentTypeInfo(); + contentTypeInfo.setContentItemClass(contentTypeClass); + + final String defaultBundleName = String.join( + "", + contentTypeClass.getClass().getName(), + "Bundle"); + final ContentTypeDescription typeDesc = contentTypeClass.getAnnotation( + ContentTypeDescription.class); + if (typeDesc == null) { + contentTypeInfo.setLabelBundle(defaultBundleName); + contentTypeInfo.setDescriptionBundle(defaultBundleName); + contentTypeInfo.setLabelKey(DEFAULT_LABEL_KEY); + contentTypeInfo.setDescriptionKey(DEFAULT_DESCRIPTION_KEY); + } else { + if (typeDesc.labelBundle().isEmpty()) { + contentTypeInfo.setLabelBundle(defaultBundleName); + } else { + contentTypeInfo.setLabelBundle(typeDesc.labelBundle()); + } + + if (typeDesc.labelKey().isEmpty()) { + contentTypeInfo.setLabelKey(DEFAULT_LABEL_KEY); + } else { + contentTypeInfo.setLabelKey(typeDesc.labelKey()); + } + + if (typeDesc.descriptionBundle().isEmpty()) { + contentTypeInfo.setDescriptionBundle(defaultBundleName); + } else { + contentTypeInfo.setDescriptionBundle(typeDesc + .descriptionBundle()); + } + + if (typeDesc.descriptionKey().isEmpty()) { + contentTypeInfo.setDescriptionKey(DEFAULT_DESCRIPTION_KEY); + } else { + contentTypeInfo.setDescriptionKey(typeDesc.descriptionKey()); + } + } + + final AuthoringKit authoringKit = contentTypeClass.getAnnotation( + AuthoringKit.class); + final AuthoringKitInfo authoringKitInfo = new AuthoringKitInfo(); + authoringKitInfo.setCreateComponent(authoringKit.createComponent()); + + final List steps = Arrays.stream(authoringKit + .steps()) + .map(step -> createAuthoringStepInfo(contentTypeClass, step)) + .collect(Collectors.toList()); + authoringKitInfo.setAuthoringSteps(steps); + steps.sort((step1, step2) -> Integer.compare(step1.getOrder(), + step2.getOrder())); + + return contentTypeInfo; + } + + /** + * Helper method for creating an info object about an authoring step. + * + * @param contentTypeClass The class which provides the implementation of + * the content type. + * @param authoringStep The {@link AuthoringStep} annotation providing + * the information about the authoring step. + * + * @return An {@link AuthoringStepInfo} object describing the authoring + * step. + * + */ + private AuthoringStepInfo createAuthoringStepInfo( + final Class contentTypeClass, + final AuthoringStep authoringStep) { + + final AuthoringStepInfo stepInfo = new AuthoringStepInfo(); + + stepInfo.setComponent(authoringStep.component()); + stepInfo.setOrder(authoringStep.order()); + + final String defaultBundleName = String.join( + "", + contentTypeClass.getClass().getName(), + "Bundle"); + + if (authoringStep.labelBundle().isEmpty()) { + stepInfo.setLabelBundle(defaultBundleName); + } else { + stepInfo.setLabelBundle(authoringStep.labelBundle()); + } + + if (authoringStep.labelKey().isEmpty()) { + stepInfo.setLabelKey( + String.join(".", + authoringStep.component().getSimpleName(), + DEFAULT_LABEL_KEY)); + } else { + stepInfo.setLabelKey(authoringStep.labelKey()); + } + + if (authoringStep.descriptionBundle().isEmpty()) { + stepInfo.setDescriptionBundle(defaultBundleName); + } else { + stepInfo.setDescriptionBundle(authoringStep.descriptionBundle()); + } + + if (authoringStep.descriptionKey().isEmpty()) { + stepInfo.setDescriptionKey( + String.join(".", + authoringStep.component().getSimpleName(), + DEFAULT_DESCRIPTION_KEY)); + } else { + stepInfo.setDescriptionKey(authoringStep.descriptionKey()); + } + + return stepInfo; + } + + /** + * Retrieves a list of all content types currently available on the system. + * + * @return A list of all available content types. + */ + public List getAvailableContentTypes() { + return Collections.unmodifiableList(availableContentTypes); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/contenttypes/ContentTypes.java b/ccm-cms/src/main/java/org/librecms/contenttypes/ContentTypes.java new file mode 100644 index 000000000..5d41b9be2 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contenttypes/ContentTypes.java @@ -0,0 +1,40 @@ +/* + * 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.contenttypes; + +import org.librecms.contentsection.ContentItem; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation is used on module classes like {@link org.librecms.Cms} to + * inform the system which content types are provided by the module. + * + * @author Jens Pelzetter + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ContentTypes { + + Class[] value(); + +} diff --git a/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java b/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java index 36d67e916..2edbeba64 100644 --- a/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java +++ b/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java @@ -34,9 +34,11 @@ import org.libreccm.security.AuthorizationRequired; import org.libreccm.security.RequiresPrivilege; import java.util.Arrays; +import java.util.List; import java.util.ServiceLoader; import java.util.SortedSet; import java.util.TreeSet; +import java.util.stream.Collectors; /** * Maps between configuration classes and the settings stored in the database. @@ -67,9 +69,8 @@ public class ConfigurationManager { final ServiceLoader modules = ServiceLoader.load( CcmModule.class); - final SortedSet> configurations = new TreeSet<>((c1, c2) -> { - return c1.getName().compareTo(c2.getName()); - }); + final SortedSet> configurations = new TreeSet<>( + (conf1, conf2) -> conf1.getName().compareTo(conf2.getName())); for (CcmModule module : modules) { final Module annotation = module.getClass().getAnnotation( @@ -79,9 +80,10 @@ public class ConfigurationManager { continue; } - Arrays.stream(annotation.configurations()).forEach(c -> { - configurations.add(c); - }); + final List> moduleConfs = Arrays.stream( + annotation.configurations()).collect(Collectors.toList()); + + configurations.addAll(moduleConfs); } return configurations;