CCM NG/ccm-cms: Infrastructure for adding common authoring steps

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4881 8810af33-2d31-482b-a856-94f89814c4df
jensp 2017-07-19 15:06:13 +00:00
parent b76876fb73
commit cbbcbbb2b3
12 changed files with 593 additions and 225 deletions

View File

@ -20,7 +20,6 @@ package com.arsdigita.cms.ui.authoring;
import com.arsdigita.bebop.Component; import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.ControlLink; import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.GridPanel; import com.arsdigita.bebop.GridPanel;
import com.arsdigita.bebop.List; import com.arsdigita.bebop.List;
import com.arsdigita.bebop.Page; import com.arsdigita.bebop.Page;
@ -32,8 +31,6 @@ import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener; import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.ChangeEvent; import com.arsdigita.bebop.event.ChangeEvent;
import com.arsdigita.bebop.event.ChangeListener; import com.arsdigita.bebop.event.ChangeListener;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.Label; import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.list.ListCellRenderer; import com.arsdigita.bebop.list.ListCellRenderer;
import com.arsdigita.bebop.parameters.StringParameter; import com.arsdigita.bebop.parameters.StringParameter;
@ -61,8 +58,6 @@ import org.apache.logging.log4j.Logger;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.Iterator; import java.util.Iterator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Objects; import java.util.Objects;
import java.util.ResourceBundle; import java.util.ResourceBundle;
@ -77,6 +72,8 @@ import org.librecms.contenttypes.AuthoringKit;
import org.librecms.contenttypes.AuthoringKitInfo; import org.librecms.contenttypes.AuthoringKitInfo;
import org.librecms.contenttypes.AuthoringStepInfo; import org.librecms.contenttypes.AuthoringStepInfo;
import org.librecms.contenttypes.ContentTypeInfo; import org.librecms.contenttypes.ContentTypeInfo;
import org.librecms.ui.authoring.ContentItemAuthoringStepInfo;
import org.librecms.ui.authoring.ContentItemAuthoringStepManager;
import org.librecms.workflow.CmsTaskType; import org.librecms.workflow.CmsTaskType;
/** /**
@ -104,19 +101,17 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
private static final Logger LOGGER = LogManager private static final Logger LOGGER = LogManager
.getLogger(AuthoringKitWizard.class); .getLogger(AuthoringKitWizard.class);
// public final String SELECTED_LANGUAGE = "selectedLanguage"; private final static Class<?>[] ARGUMENTS = new Class<?>[]{
private static Class[] arguments = new Class[]{
ItemSelectionModel.class, ItemSelectionModel.class,
AuthoringKitWizard.class, AuthoringKitWizard.class,
StringParameter.class StringParameter.class
}; };
private static Class[] userDefinedArgs = new Class[]{ private static final Class<?>[] USER_DEFINED_ARGS = new Class<?>[]{
ItemSelectionModel.class, ItemSelectionModel.class,
AuthoringKitWizard.class, AuthoringKitWizard.class,
ContentType.class ContentType.class
}; };
private static final java.util.List<AssetStepEntry> ASSETS
= new ArrayList<AssetStepEntry>();
private final Object[] values; private final Object[] values;
private final ContentTypeInfo typeInfo; private final ContentTypeInfo typeInfo;
private final AuthoringKitInfo kitInfo; private final AuthoringKitInfo kitInfo;
@ -129,7 +124,7 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
private final GridPanel leftPanel; private final GridPanel leftPanel;
private final ModalPanel bodyPanel; private final ModalPanel bodyPanel;
private final SimpleContainer stepsContainer; private final SimpleContainer stepsContainer;
private final TaskFinishForm m_taskFinishForm; private final TaskFinishForm taskFinishForm;
private final StringParameter selectedLanguageParam; private final StringParameter selectedLanguageParam;
@ -188,7 +183,9 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
leftPanel.add(new AssignedTaskSection(workflowRequestLocal, leftPanel.add(new AssignedTaskSection(workflowRequestLocal,
assignedTaskTable)); assignedTaskTable));
final Section stepSection = new Section(gz("cms.ui.authoring.steps")); final Section stepSection = new Section(
new GlobalizedMessage("cms.ui.authoring.steps",
CmsConstants.CMS_BUNDLE));
leftPanel.add(stepSection); leftPanel.add(stepSection);
list = new List(); list = new List();
@ -198,12 +195,12 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
list.setCellRenderer(new ListCellRenderer() { list.setCellRenderer(new ListCellRenderer() {
@Override @Override
public Component getComponent(List list, public Component getComponent(final List list,
PageState state, final PageState state,
Object value, final Object value,
String key, final String key,
int index, final int index,
boolean isSelected) { final boolean isSelected) {
final Label label; final Label label;
if (value instanceof GlobalizedMessage) { if (value instanceof GlobalizedMessage) {
label = new Label((GlobalizedMessage) value); label = new Label((GlobalizedMessage) value);
@ -251,14 +248,13 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
* The "label" and "description" are only here for backwards * The "label" and "description" are only here for backwards
* compatibility * compatibility
*/ */
final ResourceBundle labelBundle = ResourceBundle.getBundle(step. final ResourceBundle labelBundle = ResourceBundle
getLabelBundle()); .getBundle(step.getLabelBundle());
final ResourceBundle descBundle = ResourceBundle.getBundle(step. final ResourceBundle descBundle = ResourceBundle
getDescriptionBundle()); .getBundle(step.getDescriptionBundle());
final String labelKey = step.getLabelKey(); final String labelKey = step.getLabelKey();
final String label = labelBundle.getString(labelKey); final String label = labelBundle.getString(labelKey);
final String descriptionKey = step.getDescriptionKey(); final String descriptionKey = step.getDescriptionKey();
final String description = descBundle.getString(descriptionKey);
final Class<? extends Component> componentClass = step. final Class<? extends Component> componentClass = step.
getComponent(); getComponent();
@ -269,25 +265,25 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
} }
panel = new StepComponent(compClassName); panel = new StepComponent(compClassName);
stepsContainer.add(panel); stepsContainer.add(panel);
final Component comp; final Component component;
if (compClassName.equals(SEC_PAGE_EDIT_DYN) if (compClassName.equals(SEC_PAGE_EDIT_DYN)
|| compClassName.equals(PAGE_EDIT_DYN)) { || compClassName.equals(PAGE_EDIT_DYN)) {
comp = instantiateUserDefinedStep(compClassName, typeInfo); component = instantiateUserDefinedStep(compClassName, typeInfo);
} else { } else {
comp = instantiateStep(compClassName); component = instantiateStep(compClassName);
} }
panel.add(comp); panel.add(component);
// XXX should be optional if (component instanceof AuthoringStepComponent) {
if (comp instanceof AuthoringStepComponent) { ((AuthoringStepComponent) component).addCompletionListener(
((AuthoringStepComponent) comp).addCompletionListener(
new StepCompletionListener()); new StepCompletionListener());
} }
final GlobalizedMessage gzLabel; final GlobalizedMessage gzLabel;
if (labelKey != null) { if (labelKey != null) {
if (step.getLabelBundle() == null) { if (step.getLabelBundle() == null) {
gzLabel = gz(labelKey); gzLabel = new GlobalizedMessage(labelKey,
CmsConstants.CMS_BUNDLE);
} else { } else {
gzLabel = new GlobalizedMessage(labelKey, gzLabel = new GlobalizedMessage(labelKey,
step.getLabelBundle()); step.getLabelBundle());
@ -302,9 +298,6 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
} }
} }
final Class<? extends ContentItem> typeClass = typeInfo
.getContentItemClass();
final java.util.List<String> skipSteps = cmsConfig.getSkipAssetSteps(); final java.util.List<String> skipSteps = cmsConfig.getSkipAssetSteps();
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
for (final String step : skipSteps) { for (final String step : skipSteps) {
@ -312,60 +305,43 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
} }
} }
for (final AssetStepEntry data : ASSETS) { for (final ContentItemAuthoringStepInfo stepInfo
: getContentItemAuthoringSteps()) {
final Class<?> baseObjectType;
try {
baseObjectType = Class.forName(data.getBaseDataObjectType());
} catch (ClassNotFoundException ex) {
throw new UncheckedWrapperException(ex);
}
//Class step = (Class) data[1];
Class step = data.getStep();
LOGGER.debug("possibly adding asset step " + step.getName());
if (!skipSteps.contains(step.getName())) {
GlobalizedMessage label = data.getLabel();
if (!typeClass.isAssignableFrom(baseObjectType)) {
continue;
}
if (panel != null) { if (panel != null) {
panel.setNextStepKey(step); panel.setNextStepKey(stepInfo.getStep());
} }
panel = new StepComponent(step);
panel = new StepComponent(stepInfo.getStep());
stepsContainer.add(panel); stepsContainer.add(panel);
Component comp = instantiateStep(step.getName()); final Component component = instantiateStep(stepInfo
if (comp instanceof AuthoringStepComponent) { .getStep().getName());
((AuthoringStepComponent) comp).addCompletionListener( if (component instanceof AuthoringStepComponent) {
new StepCompletionListener()); ((AuthoringStepComponent) component)
.addCompletionListener(new StepCompletionListener());
} }
panel.add(comp); panel.add(component);
labels.put(step, label); labels.put(stepInfo.getStep(),
} new GlobalizedMessage(stepInfo.getLabelKey(),
stepInfo.getLabelBundle()));
} }
list.addChangeListener(new StepListener()); list.addChangeListener(new StepListener());
m_taskFinishForm = new TaskFinishForm(new TaskSelectionRequestLocal()); taskFinishForm = new TaskFinishForm(new TaskSelectionRequestLocal());
bodyPanel.add(m_taskFinishForm); bodyPanel.add(taskFinishForm);
bodyPanel.connect(assignedTaskTable, 2, m_taskFinishForm); bodyPanel.connect(assignedTaskTable, 2, taskFinishForm);
bodyPanel.connect(m_taskFinishForm); bodyPanel.connect(taskFinishForm);
m_taskFinishForm.addProcessListener(new FormProcessListener() { taskFinishForm
.addProcessListener(
@Override event -> assignedTaskTable
public final void process(final FormSectionEvent event) .getRowSelectionModel()
throws FormProcessException { .clearSelection(event.getPageState())
final PageState state = event.getPageState(); );
assignedTaskTable.getRowSelectionModel().clearSelection(state);
}
});
} }
private final class StepListener implements ChangeListener { private final class StepListener implements ChangeListener {
@ -375,7 +351,7 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
final PageState state = event.getPageState(); final PageState state = event.getPageState();
final String key = list.getSelectedKey(state).toString(); final String key = list.getSelectedKey(state).toString();
final Iterator iter = stepsContainer.children(); final Iterator<?> iter = stepsContainer.children();
while (iter.hasNext()) { while (iter.hasNext()) {
final StepComponent step = (StepComponent) iter.next(); final StepComponent step = (StepComponent) iter.next();
@ -396,20 +372,22 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
private final class StepCompletionListener implements ActionListener { private final class StepCompletionListener implements ActionListener {
@Override @Override
@SuppressWarnings("unchecked")
public final void actionPerformed(final ActionEvent event) { public final void actionPerformed(final ActionEvent event) {
final PageState state = event.getPageState(); final PageState state = event.getPageState();
if (ContentItemPage.isStreamlinedCreationActive(state)) { if (ContentItemPage.isStreamlinedCreationActive(state)) {
final String key = list.getSelectedKey(state).toString(); final String key = list.getSelectedKey(state).toString();
final Iterator iter = stepsContainer.children(); final Iterator<?> iter = stepsContainer.children();
while (iter.hasNext()) { while (iter.hasNext()) {
final StepComponent step = (StepComponent) iter.next(); final StepComponent step = (StepComponent) iter.next();
if (step.getStepKey().toString().equals(key)) { if (step.getStepKey().toString().equals(key)) {
Object nextStep = step.getNextStepKey(); Object nextStep = step.getNextStepKey();
if (nextStep != null) { if (nextStep != null) {
list.getSelectionModel().setSelectedKey( list
state, nextStep.toString()); .getSelectionModel()
.setSelectedKey(state, nextStep.toString());
} }
} }
} }
@ -422,7 +400,7 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
public final void register(final Page page) { public final void register(final Page page) {
super.register(page); super.register(page);
final Iterator iter = stepsContainer.children(); final Iterator<?> iter = stepsContainer.children();
while (iter.hasNext()) { while (iter.hasNext()) {
final StepComponent child = (StepComponent) iter.next(); final StepComponent child = (StepComponent) iter.next();
@ -439,8 +417,9 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
final PageState state = event.getPageState(); final PageState state = event.getPageState();
if (state.isVisibleOnPage(AuthoringKitWizard.this)) { if (state.isVisibleOnPage(AuthoringKitWizard.this)) {
final SingleSelectionModel model = list. @SuppressWarnings("unchecked")
getSelectionModel(); final SingleSelectionModel<Object> model = list
.getSelectionModel();
if (!model.isSelected(state)) { if (!model.isSelected(state)) {
model.setSelectedKey(state, defaultKey); model.setSelectedKey(state, defaultKey);
@ -451,122 +430,13 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
}); });
} }
public static void registerAssetStep(final String baseObjectType, private java.util.List<ContentItemAuthoringStepInfo> getContentItemAuthoringSteps() {
final Class step,
final GlobalizedMessage label,
final GlobalizedMessage description,
final int sortKey) {
// cg - allow registered steps to be overridden by registering a step with the same label
// this is a bit of a hack used specifically for creating a specialised version of image
// step. There is no straightforward way of preventing the original image step from being
// registered, but I needed the image step to use a different step class if the specialised
// image step application was loaded. Solution is to ensure initialiser in new project
// runs after original ccm-ldn-image-step initializer and override the registered step here
LOGGER.debug("registering asset step - label: \"{}\"; "
+ "step class: \"%s\"",
label.localize(),
step.getName());
for (final AssetStepEntry data : ASSETS) { final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemAuthoringStepManager manager = cdiUtil
final String thisObjectType = data.getBaseDataObjectType(); .findBean(ContentItemAuthoringStepManager.class);
final GlobalizedMessage thisLabel = data.getLabel();
/**
* jensp 2011-11-14: The code above was only testing for the same
* label, but not for the same object type. I don't think that this
* was indented since this made it impossible to attach the same
* step to different object types. The orginal line was if
* (thisLabel.localize().equals(label.localize())) {
*
*/
if ((thisObjectType.equals(baseObjectType))
&& (thisLabel.localize().equals(label.localize()))) {
LOGGER.debug(
"registering authoring step with same label as previously registered step");
ASSETS.remove(data);
break;
}
}
ASSETS.add(
new AssetStepEntry(baseObjectType, step, label, description,
sortKey));
Collections.sort(ASSETS);
}
private static class AssetStepEntry implements Comparable<AssetStepEntry> {
private String baseDataObjectType;
private Class step;
private GlobalizedMessage label;
private GlobalizedMessage description;
private Integer sortKey;
public AssetStepEntry() {
super();
}
public AssetStepEntry(final String baseDataObjectType,
final Class step,
final GlobalizedMessage label,
final GlobalizedMessage description,
final Integer sortKey) {
this.baseDataObjectType = baseDataObjectType;
this.step = step;
this.label = label;
this.description = description;
this.sortKey = sortKey;
}
public String getBaseDataObjectType() {
return baseDataObjectType;
}
public void setBaseDataObjectType(final String baseDataObjectType) {
this.baseDataObjectType = baseDataObjectType;
}
public Class getStep() {
return step;
}
public void setStep(final Class step) {
this.step = step;
}
public GlobalizedMessage getLabel() {
return label;
}
public void setLabel(final GlobalizedMessage label) {
this.label = label;
}
public GlobalizedMessage getDescription() {
return description;
}
public void setDescription(final GlobalizedMessage description) {
this.description = description;
}
public Integer getSortKey() {
return sortKey;
}
public void setSortKey(final Integer sortKey) {
this.sortKey = sortKey;
}
@Override
public int compareTo(final AssetStepEntry other) {
if ((int) sortKey == (int) other.getSortKey()) {
return step.getName().compareTo(other.getStep().getName());
} else {
return sortKey.compareTo(other.getSortKey());
}
}
return manager.getContentItemAuthoringStepInfos();
} }
/** /**
@ -606,12 +476,12 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
LOGGER.debug("Instantiating kit wizard \"{}\" with arguments {}...", LOGGER.debug("Instantiating kit wizard \"{}\" with arguments {}...",
className, className,
arguments); ARGUMENTS);
try { try {
// Get the creation component // Get the creation component
final Class createClass = Class.forName(className); final Class<?> createClass = Class.forName(className);
final Constructor constr = createClass.getConstructor(arguments); final Constructor<?> constr = createClass.getConstructor(ARGUMENTS);
final Component component = (Component) constr.newInstance(values); final Component component = (Component) constr.newInstance(values);
return component; return component;
@ -645,12 +515,11 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
protected Component instantiateUserDefinedStep( protected Component instantiateUserDefinedStep(
final String className, final ContentTypeInfo originatingType) { final String className, final ContentTypeInfo originatingType) {
Object[] vals;
try { try {
// Get the creation component // Get the creation component
final Class createClass = Class.forName(className); final Class<?> createClass = Class.forName(className);
final Constructor constr = createClass.getConstructor( final Constructor<?> constr = createClass.getConstructor(
userDefinedArgs); USER_DEFINED_ARGS);
final Object[] userDefinedVals = new Object[]{selectionModel, final Object[] userDefinedVals = new Object[]{selectionModel,
this, this,
originatingType}; originatingType};
@ -658,8 +527,10 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
userDefinedVals); userDefinedVals);
return component; return component;
} catch (ClassNotFoundException | NoSuchMethodException } catch (ClassNotFoundException
| InstantiationException | IllegalAccessException | NoSuchMethodException
| InstantiationException
| IllegalAccessException
| InvocationTargetException ex) { | InvocationTargetException ex) {
throw new UncheckedWrapperException(ex); throw new UncheckedWrapperException(ex);
} }
@ -710,12 +581,4 @@ public class AuthoringKitWizard extends LayoutPanel implements Resettable {
} }
protected final static GlobalizedMessage gz(final String key) {
return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE);
}
protected final static String lz(final String key) {
return (String) gz(key).localize();
}
} }

View File

@ -25,7 +25,6 @@ import com.arsdigita.bebop.event.ActionListener;
* currently an optional interface. * currently an optional interface.
* *
* @author Scott Seago (sseago@redhat.com) * @author Scott Seago (sseago@redhat.com)
* @version $Revision: #4 $ $DateTime: 2004/08/17 23:15:09 $
*/ */
public interface AuthoringStepComponent { public interface AuthoringStepComponent {

View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2017 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.authoring.assets;
import com.arsdigita.bebop.Text;
import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.ui.authoring.AuthoringKitWizard;
import com.arsdigita.cms.ui.authoring.ResettableContainer;
import org.librecms.CmsConstants;
import org.librecms.ui.authoring.ContentItemAuthoringStep;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@ContentItemAuthoringStep(
labelBundle = CmsConstants.CMS_BUNDLE,
labelKey = "image_step.label",
descriptionBundle = CmsConstants.CMS_BUNDLE,
descriptionKey = "image_step.description")
public class ImageStep extends ResettableContainer {
public ImageStep(final ItemSelectionModel itemSelectionModel,
final AuthoringKitWizard authoringKitWizard,
final StringParameter selectedLanguage) {
super();
super.add(new Text("Image Step placeholder"));
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2017 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.authoring.assets;
import com.arsdigita.bebop.Text;
import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.ui.authoring.AuthoringKitWizard;
import com.arsdigita.cms.ui.authoring.ResettableContainer;
import org.librecms.CmsConstants;
import org.librecms.ui.authoring.ContentItemAuthoringStep;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@ContentItemAuthoringStep(
labelBundle = CmsConstants.CMS_BUNDLE,
labelKey = "related_info_step.label",
descriptionBundle = CmsConstants.CMS_BUNDLE,
descriptionKey = "related_info_step.description")
public class RelatedInfoStep extends ResettableContainer {
public RelatedInfoStep(final ItemSelectionModel itemSelectionModel,
final AuthoringKitWizard authoringKitWizard,
final StringParameter selectedLanguage) {
super();
super.add(new Text("Related Info Step placeholder"));
}
}

View File

@ -38,12 +38,12 @@ public class ContentSectionConfig {
/** /**
* A list of workflow tasks, and the associated events for which alerts have * A list of workflow tasks, and the associated events for which alerts have
* to be sent. Parameter name TASK_ALERTS in the old initializer system / * to be sent. Parameter name TASK_ALERTS in the old initialiser system /
* enterprise.init Specifies when to generate email alerts: by default, * enterprise.init Specifies when to generate email alerts: by default,
* generate email alerts on enable, finish, and rollback (happens on * generate email alerts on enable, finish, and rollback (happens on
* rejection) changes. There are four action types for each task type: * rejection) changes. There are four action types for each task type:
* enable, disable, finish, and rollback. Example: (Note that the values * enable, disable, finish, and rollback. Example: (Note that the values
* below are based on the task labels, and as such are not globalized.) * below are based on the task labels, and as such are not globalised.)
* <pre> * <pre>
* taskAlerts = { * taskAlerts = {
* { "Authoring", * { "Authoring",
@ -58,12 +58,12 @@ public class ContentSectionConfig {
* }; * };
* </pre> * </pre>
* *
* In the new Initializer system we use a specifically formatted String * In the new Initialiser system we use a specifically formatted String
* Array because we have no List parameter. Format: - A string for each task * Array because we have no List parameter. Format: - A string for each task
* to handle, possible values: Authoring, Approval, Deploy - Each Task * to handle, possible values: Authoring, Approval, Deploy - Each Task
* String: [taskName]:[alert_1]:...:[alert_n] The specially formatted string * String: [taskName]:[alert_1]:...:[alert_n] The specially formatted string
* is not handled by StringArray parameter, but forwarded untouched to the * is not handled by StringArray parameter, but forwarded untouched to the
* initializer which has the duty to process it! * initialiser which has the duty to process it!
* *
* Currently there is no way to persist taskAlerts section specific. So all * Currently there is no way to persist taskAlerts section specific. So all
* sections have to treated equally. Default values are provided here. * sections have to treated equally. Default values are provided here.
@ -78,7 +78,7 @@ public class ContentSectionConfig {
/** /**
* Should we send alerts about overdue tasks at all? Send alerts when a task * Should we send alerts about overdue tasks at all? Send alerts when a task
* is overdue (has remained in the \"enabled\" state for a long time) * is overdue (has remained in the \"enabled\" state for a long time)
* Parameter SEND_OVERDUE_ALERTS in the old initializer system, default * Parameter SEND_OVERDUE_ALERTS in the old initialiser system, default
* false * false
*/ */
@Setting @Setting
@ -99,7 +99,7 @@ public class ContentSectionConfig {
/** /**
* The time to wait between sending successive alerts on the same overdue * The time to wait between sending successive alerts on the same overdue
* task (in HOURS). Parameter name OVERDUE_ALERT_INTERVAL in old initializer * task (in HOURS). Parameter name OVERDUE_ALERT_INTERVAL in old initialiser
* system Description: Time to wait between sending overdue notifications on * system Description: Time to wait between sending overdue notifications on
* the same task (in hours) * the same task (in hours)
*/ */
@ -108,12 +108,21 @@ public class ContentSectionConfig {
/** /**
* The maximum number of alerts to send about any one overdue task. * The maximum number of alerts to send about any one overdue task.
* Parameter name MAX_ALERTS in old initializer system. Description: The * Parameter name MAX_ALERTS in old initialiser system. Description: The
* maximum number of alerts to send that a single task is overdue * maximum number of alerts to send that a single task is overdue
*/ */
@Setting @Setting
private int maxAlerts = 5; private int maxAlerts = 5;
/**
* Assets steps which are added which are present on all content items.
*/
@Setting
private List<String> defaultAuthoringSteps = Arrays
.asList(new String[]{
"com.arsdigita.cms.ui.authoring.assets.ImageStep",
"com.arsdigita.cms.ui.authoring.assets.RelatedInfoStep"});
public static ContentSectionConfig getConfig() { public static ContentSectionConfig getConfig() {
final ConfigurationManager confManager = CdiUtil.createCdiUtil() final ConfigurationManager confManager = CdiUtil.createCdiUtil()
.findBean(ConfigurationManager.class); .findBean(ConfigurationManager.class);
@ -164,4 +173,12 @@ public class ContentSectionConfig {
this.maxAlerts = maxAlerts; this.maxAlerts = maxAlerts;
} }
public List<String> getDefaultAuthoringSteps() {
return new ArrayList<>(defaultAuthoringSteps);
}
public void setDefaultAuthoringSteps(final List<String> defaultAuthoringSteps) {
this.defaultAuthoringSteps = new ArrayList<>(defaultAuthoringSteps);
}
} }

View File

@ -163,7 +163,7 @@ public class AuthoringStepInfo {
public String toString(final String data) { public String toString(final String data) {
return String.format("%s{ " return String.format("%s{ "
+ "labelBundle = \"%s\"," + "labelBundle = \"%s\", "
+ "labelKey = \"%s\", " + "labelKey = \"%s\", "
+ "descriptionBundle = \"%s\"," + "descriptionBundle = \"%s\","
+ "descriptionKey = \"%s\"," + "descriptionKey = \"%s\","

View File

@ -0,0 +1,74 @@
/*
* Copyright (C) 2017 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.ui.authoring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Provides meta information about an authoring step which is independent from
* the type of the content item.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentItemAuthoringStep {
/**
* 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 will be used. The default bundle is the fully
* qualified name of the authoring step 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 will be used. The default bundle is the fully
* qualified name of the authoring step class with the suffix
* {@code Bundle}.
*
* @return The bundle providing the description for the authoring step.
*/
String descriptionBundle() default "";
}

View File

@ -0,0 +1,161 @@
/*
* Copyright (C) 2017 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.ui.authoring;
import com.arsdigita.bebop.Component;
import java.util.Objects;
/**
* Information about a authoring step which is independent from the type of the
* content item.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ContentItemAuthoringStepInfo {
private Class<? extends Component> step;
/**
* 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;
public Class<? extends Component> getStep() {
return step;
}
public void setStep(Class<? extends Component> step) {
this.step = step;
}
public String getLabelBundle() {
return labelBundle;
}
public void setLabelBundle(String labelBundle) {
this.labelBundle = labelBundle;
}
public String getLabelKey() {
return labelKey;
}
public void setLabelKey(String labelKey) {
this.labelKey = labelKey;
}
public String getDescriptionBundle() {
return descriptionBundle;
}
public void setDescriptionBundle(String descriptionBundle) {
this.descriptionBundle = descriptionBundle;
}
public String getDescriptionKey() {
return descriptionKey;
}
public void setDescriptionKey(String descriptionKey) {
this.descriptionKey = descriptionKey;
}
@Override
public int hashCode() {
int hash = 7;
hash = 53 * hash + Objects.hashCode(step);
hash = 53 * hash + Objects.hashCode(labelBundle);
hash = 53 * hash + Objects.hashCode(labelKey);
hash = 53 * hash + Objects.hashCode(descriptionBundle);
hash = 53 * hash + Objects.hashCode(descriptionKey);
return hash;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof ContentItemAuthoringStepInfo)) {
return false;
}
final ContentItemAuthoringStepInfo other
= (ContentItemAuthoringStepInfo) 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;
}
return Objects.equals(step, other.getStep());
}
public boolean canEqual(final Object obj) {
return obj instanceof ContentItemAuthoringStep;
}
@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\","
+ "step = \"%s\"%s }",
super.toString(),
labelBundle,
labelKey,
descriptionBundle,
descriptionKey,
Objects.toString(step),
data);
}
}

View File

@ -0,0 +1,142 @@
/*
* Copyright (C) 2017 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.ui.authoring;
import com.arsdigita.bebop.Component;
import org.libreccm.configuration.ConfigurationManager;
import org.libreccm.core.UnexpectedErrorException;
import org.librecms.contentsection.ContentSectionConfig;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
/**
* Provides easy access to information about the default authoring step which
* are available for every content type.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
public class ContentItemAuthoringStepManager {
@Inject
private ConfigurationManager confManager;
private List<ContentItemAuthoringStepInfo> stepInfos;
@PostConstruct
protected void initialize() {
final ContentSectionConfig config = confManager
.findConfiguration(ContentSectionConfig.class);
final List<String> classNames = config.getDefaultAuthoringSteps();
stepInfos = classNames
.stream()
.map(className -> createStepInfo(className))
.collect(Collectors.toList());
}
public List<ContentItemAuthoringStepInfo> getContentItemAuthoringStepInfos() {
return Collections.unmodifiableList(stepInfos);
}
@SuppressWarnings("unchecked")
private ContentItemAuthoringStepInfo createStepInfo(final String className) {
Objects.requireNonNull(className);
if (className.isEmpty()) {
throw new IllegalArgumentException("The name of the authoring step "
+ "class can't be empty.");
}
final Class<? extends Component> clazz;
try {
clazz = (Class<? extends Component>) Class.forName(className);
} catch (ClassNotFoundException ex) {
throw new UnexpectedErrorException(String
.format("No class for class name \"%s\" available.",
className),
ex);
}
return createStepInfo(clazz);
}
private ContentItemAuthoringStepInfo createStepInfo(
final Class<? extends Component> clazz) {
final ContentItemAuthoringStepInfo stepInfo
= new ContentItemAuthoringStepInfo();
final ContentItemAuthoringStep step = clazz
.getAnnotation(ContentItemAuthoringStep.class);
final String defaultBundleName = String
.join("", clazz.getName(), "Bundle");
final String defaultLabelKey = String.join(".",
clazz.getSimpleName(),
"label");
final String defaultDescKey = String.join(".",
clazz.getSimpleName(),
"description");
if (step == null) {
stepInfo.setLabelBundle(defaultBundleName);
stepInfo.setDescriptionBundle(defaultBundleName);
stepInfo.setLabelKey(defaultLabelKey);
stepInfo.setDescriptionKey(defaultDescKey);
} else {
if (step.labelBundle() == null || step.labelBundle().isEmpty()) {
stepInfo.setLabelBundle(defaultBundleName);
} else {
stepInfo.setLabelBundle(step.labelBundle());
}
if (step.labelKey() == null || step.labelKey().isEmpty()) {
stepInfo.setLabelKey(defaultLabelKey);
} else {
stepInfo.setLabelKey(step.labelKey());
}
if (step.descriptionBundle() == null
|| step.descriptionBundle().isEmpty()) {
stepInfo.setDescriptionBundle(defaultBundleName);
} else {
stepInfo.setDescriptionBundle(step.descriptionBundle());
}
if (step.descriptionKey() == null
|| step.descriptionKey().isEmpty()) {
stepInfo.setDescriptionKey(defaultDescKey);
}
}
stepInfo.setStep(clazz);
return stepInfo;
}
}

View File

@ -379,3 +379,7 @@ cms.contenttypes.ui.mparticle.no_launch_date=Launch date is required
cms.contenttypes.ui.mparticle.an_item_with_name_already_exists=An item with this name already exists cms.contenttypes.ui.mparticle.an_item_with_name_already_exists=An item with this name already exists
cms.contenttypes.ui.mparticle.section_table.header_page_break=Page break cms.contenttypes.ui.mparticle.section_table.header_page_break=Page break
audio_asset.label=Audio audio_asset.label=Audio
image_step.label=Images
related_info_step.label=Related information
image_step.description=Attach images
related_info_step_description=Add related information

View File

@ -376,3 +376,7 @@ cms.contenttypes.ui.mparticle.no_launch_date=Es wurde kein Ver\u00f6ffentlichung
cms.contenttypes.ui.mparticle.an_item_with_name_already_exists=Ein Dokument mit diesem Namen existiert bereits. cms.contenttypes.ui.mparticle.an_item_with_name_already_exists=Ein Dokument mit diesem Namen existiert bereits.
cms.contenttypes.ui.mparticle.section_table.header_page_break=Seitenumbruch cms.contenttypes.ui.mparticle.section_table.header_page_break=Seitenumbruch
audio_asset.label=Audio audio_asset.label=Audio
image_step.label=Bilder
related_info_step.label=Weiterf\u00fchrende Informationen
image_step.description=Bilder hinzuf\u00fcgen
related_info_step_description=Weiterf\u00fchrende Informationen hinzuf\u00fcgen

View File

@ -335,3 +335,7 @@ cms.contenttypes.ui.mparticle.no_launch_date=Launch date is required
cms.contenttypes.ui.mparticle.an_item_with_name_already_exists=An item with this name already exists cms.contenttypes.ui.mparticle.an_item_with_name_already_exists=An item with this name already exists
cms.contenttypes.ui.mparticle.section_table.header_page_break=Page break cms.contenttypes.ui.mparticle.section_table.header_page_break=Page break
audio_asset.label=Audio audio_asset.label=Audio
image_step.label=Images
related_info_step.label=Related information
image_step.description=Attach images
related_info_step_description=Add related information