CCM NG/ccm-cms: More forms and related classes

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4451 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2016-11-22 12:06:55 +00:00
parent a124b1ebd8
commit e2765a9109
9 changed files with 1638 additions and 1087 deletions

View File

@ -1,684 +0,0 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.authoring;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.GridPanel;
import com.arsdigita.bebop.List;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Resettable;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.SingleSelectionModel;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.ChangeEvent;
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.list.ListCellRenderer;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentType;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.ui.ContentItemPage;
import com.arsdigita.cms.ui.item.ItemWorkflowRequestLocal;
import com.arsdigita.cms.ui.workflow.AssignedTaskSection;
import com.arsdigita.cms.ui.workflow.AssignedTaskTable;
import com.arsdigita.cms.ui.workflow.TaskFinishForm;
import com.arsdigita.cms.ui.workflow.TaskRequestLocal;
import com.arsdigita.cms.ui.workflow.WorkflowRequestLocal;
import com.arsdigita.cms.util.GlobalizationUtil;
import com.arsdigita.cms.workflow.CMSTask;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.persistence.metadata.MetadataRoot;
import com.arsdigita.persistence.metadata.ObjectType;
import com.arsdigita.toolbox.ui.LayoutPanel;
import com.arsdigita.toolbox.ui.ModalPanel;
import com.arsdigita.toolbox.ui.Section;
import com.arsdigita.util.Assert;
import com.arsdigita.util.SequentialMap;
import com.arsdigita.util.UncheckedWrapperException;
import org.apache.logging.log4j.Logger;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Collections;
import org.apache.logging.log4j.LogManager;
import org.librecms.contenttypes.AuthoringKitInfo;
import org.librecms.contenttypes.ContentTypeInfo;
/**
* This class represents a single authoring kit. The wizard accepts a
* {@link ContentType} in the constructor; it then extracts
* the {@link AuthoringKit} for the content type, and creates the
* components for all the steps in the kit.</p>
*
* Note that the individual authoring kit steps must provide the following
* constructor:
*
* <blockquote><pre><code>
* public TheClass(ItemSelectionModel model, AuthoringKitWizard parent) { ... }
* </code></pre></blockquote>
*
* This constructor will be called when the component is automatically
* instantiated by the <code>AuthoringKitWizard</code>.</p>
*
*/
public class AuthoringKitWizard extends LayoutPanel implements Resettable {
/** Private Logger instance for this class */
private static final Logger LOGGER = LogManager.getLogger(
AuthoringKitWizard.class);
private static Class[] s_args = new Class[]{
ItemSelectionModel.class,
AuthoringKitWizard.class
};
private static Class[] s_userDefinedArgs = new Class[]{
ItemSelectionModel.class,
AuthoringKitWizard.class,
ContentType.class
};
//private static final ArrayList s_assets = new ArrayList();
private static final java.util.List<AssetStepEntry> s_assets = new
ArrayList<AssetStepEntry>();
private final Object[] m_vals;
private final ContentTypeInfo m_type;
private final AuthoringKitInfo m_kit;
private final ItemSelectionModel m_sel;
private final WorkflowRequestLocal m_workflow;
private final AssignedTaskTable m_tasks;
private final SequentialMap m_labels;
private final List m_list;
private String m_defaultKey;
private final GridPanel m_left;
private final ModalPanel m_body;
private final SimpleContainer m_steps;
private final TaskFinishForm m_taskFinishForm;
/**
* The name of the state parameter that determines whether the
* wizard is in item creation mode or item editing mode.
*/
public static final String IS_EDITING = "is_edit";
/**
* The key for the item creation step.
*/
public static final String CREATION = "_creation_";
/**
* Construct a new AuthoringKitWizard. Add all the steps in the
* authoring kit to the wizard.
*
* @param type The content type of the items that this wizard will
* handle
* @param model
*/
public AuthoringKitWizard(final ContentTypeInfo type,
final ItemSelectionModel model) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Authoring kit wizard for type " + type + " "
+ "undergoing creation");
}
m_type = type;
m_kit = type.getAuthoringKit();
m_sel = model;
m_vals = new Object[]{m_sel, this};
m_workflow = new ItemWorkflowRequestLocal();
m_labels = new SequentialMap();
m_left = new GridPanel(1);
setLeft(m_left);
m_tasks = new AssignedTaskTable(m_workflow);
m_left.add(new AssignedTaskSection(m_workflow, m_tasks));
final Section stepSection = new Section(gz("cms.ui.authoring.steps"));
m_left.add(stepSection);
m_list = new List();
stepSection.setBody(m_list);
m_list.setListData(m_labels);
m_list.setCellRenderer(new ListCellRenderer() {
public Component getComponent(
List list,
PageState state,
Object value,
String key,
int index,
boolean isSelected) {
Label l = null;
if (value instanceof GlobalizedMessage) {
l = new Label((GlobalizedMessage) value);
} else {
l = new Label((String) value);
}
if (isSelected) {
l.setFontWeight(Label.BOLD);
return l;
}
return new ControlLink(l);
}
});
m_body = new ModalPanel();
setBody(m_body);
m_steps = new SimpleContainer();
m_body.add(m_steps);
m_body.setDefault(m_steps);
final AuthoringStepCollection steps = m_kit.getSteps();
if (Assert.isEnabled()) {
Assert.isTrue(!steps.isEmpty(),
"The authoring kit for " + type.getID() + " "
+ "(java class " + type.getClassName() + ") "
+ "has no steps.");
}
StepComponent panel = null;
while (steps.next()) {
final AuthoringStep step = steps.getAuthoringStep();
final String key = step.getID().toString();
if (m_defaultKey == null) {
m_defaultKey = key;
}
/**
* The "label" and "description" are only here for backwards
* compatibility
*/
final String label = step.getLabel();
final String labelKey = step.getLabelKey();
final String labelBundle = step.getLabelBundle();
final String description = step.getDescription();
final String descriptionKey = step.getDescription();
final String descriptionBundle = step.getDescription();
final String str = step.getComponent();
if (panel != null) {
panel.setNextStepKey(step.getID());
}
panel = new StepComponent(step.getID());
m_steps.add(panel);
final Component comp;
if (str.equals("com.arsdigita.cms.ui.authoring."
+ "SecondaryPageEditDynamic")
|| str.equals("com.arsdigita.cms.ui.authoring."
+ "PageEditDynamic")) {
comp = instantiateUserDefinedStep(str, m_type);
} else {
comp = instantiateStep(str);
}
panel.add(comp);
// XXX should be optional
if (comp instanceof AuthoringStepComponent) {
((AuthoringStepComponent) comp).addCompletionListener(
new StepCompletionListener());
}
GlobalizedMessage gzLabel = null;
if (labelKey != null) {
if (labelBundle == null) {
gzLabel = gz(labelKey);
} else {
gzLabel = new GlobalizedMessage(labelKey, labelBundle);
}
}
m_labels.put(key,
gzLabel == null ? (Object) label : (Object) gzLabel);
}
ObjectType thisType = MetadataRoot.getMetadataRoot().getObjectType(type.
getAssociatedObjectType());
Collection skipSteps = ContentSection.getConfig().getAssetStepsToSkip(
type);
Iterator it = skipSteps.iterator();
if (LOGGER.isDebugEnabled()) {
while (it.hasNext()) {
LOGGER.debug("skip step " + it.next());
}
}
//Iterator assets = s_assets.iterator();
Iterator<AssetStepEntry> assets = s_assets.iterator();
while (assets.hasNext()) {
//Object[] data = (Object[]) assets.next();
final AssetStepEntry data = assets.next();
//String baseObjectType = (String) data[0];
final String baseObjectType = data.getBaseDataObjectType();
//Class step = (Class) data[1];
Class step = data.getStep();
LOGGER.debug("possibly adding asset step " + step.getName());
if (!skipSteps.contains(step.getName())) {
//GlobalizedMessage label = (GlobalizedMessage) data[2];
GlobalizedMessage label = data.getLabel();
if (!thisType.isSubtypeOf(baseObjectType)) {
continue;
}
if (panel != null) {
panel.setNextStepKey(step);
}
panel = new StepComponent(step);
m_steps.add(panel);
Component comp = instantiateStep(step.getName());
if (comp instanceof AuthoringStepComponent) {
((AuthoringStepComponent) comp).addCompletionListener(
new StepCompletionListener());
}
panel.add(comp);
m_labels.put(step, label);
}
}
m_list.addChangeListener(new StepListener());
m_taskFinishForm = new TaskFinishForm(new TaskSelectionRequestLocal());
m_body.add(m_taskFinishForm);
m_body.connect(m_tasks, 2, m_taskFinishForm);
m_body.connect(m_taskFinishForm);
m_taskFinishForm.addProcessListener(new FormProcessListener() {
public final void process(final FormSectionEvent e)
throws FormProcessException {
final PageState state = e.getPageState();
m_tasks.getRowSelectionModel().clearSelection(state);
}
});
}
/**
*
*/
private final class StepListener implements ChangeListener {
public final void stateChanged(final ChangeEvent e) {
final PageState state = e.getPageState();
final String key = m_list.getSelectedKey(state).toString();
final Iterator iter = m_steps.children();
while (iter.hasNext()) {
final StepComponent step = (StepComponent) iter.next();
if (step.getStepKey().toString().equals(key)) {
step.setVisible(state, true);
} else {
step.setVisible(state, false);
}
}
}
}
/**
*
*/
private final class StepCompletionListener implements ActionListener {
public final void actionPerformed(final ActionEvent e) {
final PageState state = e.getPageState();
if (ContentItemPage.isStreamlinedCreationActive(state)) {
final String key = m_list.getSelectedKey(state).toString();
final Iterator iter = m_steps.children();
while (iter.hasNext()) {
final StepComponent step = (StepComponent) iter.next();
if (step.getStepKey().toString().equals(key)) {
Object nextStep = step.getNextStepKey();
if (nextStep != null) {
m_list.getSelectionModel().setSelectedKey(state,
nextStep.
toString());
}
}
}
}
}
}
/**
*
* @param page
*/
@Override
public final void register(final Page page) {
super.register(page);
final Iterator iter = m_steps.children();
while (iter.hasNext()) {
final StepComponent child = (StepComponent) iter.next();
page.setVisibleDefault(child, false);
}
page.addActionListener(new ActionListener() {
public final void actionPerformed(final ActionEvent e) {
final PageState state = e.getPageState();
if (state.isVisibleOnPage(AuthoringKitWizard.this)) {
final SingleSelectionModel model =
m_list.getSelectionModel();
if (!model.isSelected(state)) {
model.setSelectedKey(state, m_defaultKey);
}
}
}
});
}
/**
*
* @param baseObjectType
* @param step
* @param label
* @param description
* @param sortKey
*/
public static void registerAssetStep(String baseObjectType,
Class step,
GlobalizedMessage label,
GlobalizedMessage description,
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: "
+ label.localize()
+ " step class: "
+ step.getName());
//Iterator assets = s_assets.iterator();
Iterator<AssetStepEntry> assets = s_assets.iterator();
while (assets.hasNext()) {
//Object[] data = (Object[]) assets.next();
//String thisObjectType = (String) data[0];
//GlobalizedMessage thisLabel = (GlobalizedMessage) data[2];
final AssetStepEntry data = assets.next();
String thisObjectType = data.getBaseDataObjectType();
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");
s_assets.remove(data);
break;
}
}
s_assets.add(new AssetStepEntry(baseObjectType, step, label, description, sortKey));
Collections.sort(s_assets);
//s_assets.add(new Object[]{baseObjectType, step, label, description});
}
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;
}
public int compareTo(final AssetStepEntry other) {
if (sortKey == other.getSortKey()) {
return step.getName().compareTo(other.getStep().getName());
} else {
return sortKey.compareTo(other.getSortKey());
}
}
}
/**
* @return The content type handled by this wizard
*/
public ContentType getContentType() {
return m_type;
}
/**
*
* @return
*/
public List getList() {
return m_list;
}
/**
* @return The authoring kit which is represented by this wizard
*/
public AuthoringKit getAuthoringKit() {
return m_kit;
}
/**
* @return The ItemSelectionModel used by the steps in this wizard
*/
public ItemSelectionModel getItemSelectionModel() {
return m_sel;
}
/**
* Instantiate the specified authoring kit step. Will throw a
* RuntimeException on failure.
*
* @param className The Java class name of the step
*/
protected Component instantiateStep(String name) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Instantiating kit wizard '" + name + "' with "
+ "arguments " + s_args);
}
Object[] vals;
try {
// Get the creation component
Class createClass = Class.forName(name);
Constructor constr = createClass.getConstructor(s_args);
Component c = (Component) constr.newInstance(m_vals);
return c;
} catch (Exception e) {
Throwable cause = e.getCause(); // JDK1.4
if (cause == null) {
cause = e;
}
throw new UncheckedWrapperException(
"Failed to instantiate authoring kit component " + m_kit.
getCreateComponent() + ": " + e.getMessage(), cause);
}
}
/**
* Instantiate the specified authoring kit step for a user defined content type.
* Will throw a
* RuntimeException on failure.
*
* @param className The Java class name of the step
* @param description The step description, which for dynamically generated
* steps will be the object type which originally defined the step.
*/
protected Component instantiateUserDefinedStep(String name,
ContentType originatingType) {
Object[] vals;
try {
// Get the creation component
Class createClass = Class.forName(name);
Constructor constr = createClass.getConstructor(s_userDefinedArgs);
Object[] userDefinedVals =
new Object[]{m_sel, this, originatingType};
Component c = (Component) constr.newInstance(userDefinedVals);
return c;
} catch (ClassNotFoundException cnfe) {
throw new UncheckedWrapperException(cnfe);
} catch (NoSuchMethodException nsme) {
throw new UncheckedWrapperException(nsme);
} catch (InstantiationException ie) {
throw new UncheckedWrapperException(ie);
} catch (IllegalAccessException iae) {
throw new UncheckedWrapperException(iae);
} catch (InvocationTargetException ite) {
throw new UncheckedWrapperException(ite);
}
}
// /**
// * Tell the parent page to redirect back to its return URL
// *
// * @param state The page state
// */
// public static void redirectBack(PageState state) {
// ((ContentItemPage)state.getPage()).redirectBack(state);
// }
/**
* Reset the state of this wizard
*/
public final void reset(PageState state) {
m_list.setSelectedKey(state, m_defaultKey);
}
private final class StepComponent extends SimpleContainer {
private final Object m_key;
private Object m_nextKey;
public StepComponent(Object key) {
m_key = key;
}
public Object getStepKey() {
return m_key;
}
public Object getNextStepKey() {
return m_nextKey;
}
public void setNextStepKey(Object nextKey) {
m_nextKey = nextKey;
}
}
private final class TaskSelectionRequestLocal extends TaskRequestLocal {
protected final Object initialValue(final PageState state) {
final String id = m_tasks.getRowSelectionModel().getSelectedKey(
state).toString();
return new CMSTask(new BigDecimal(id));
}
}
protected final static GlobalizedMessage gz(final String key) {
return GlobalizationUtil.globalize(key);
}
protected final static String lz(final String key) {
return (String) gz(key).localize();
}
}

View File

@ -0,0 +1,684 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.authoring;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.GridPanel;
import com.arsdigita.bebop.List;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Resettable;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.SingleSelectionModel;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.ChangeEvent;
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.list.ListCellRenderer;
import org.librecms.contentsection.ContentType;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.ui.ContentItemPage;
import com.arsdigita.cms.ui.item.ItemWorkflowRequestLocal;
import com.arsdigita.cms.ui.workflow.AssignedTaskSection;
import com.arsdigita.cms.ui.workflow.AssignedTaskTable;
import com.arsdigita.cms.ui.workflow.TaskFinishForm;
import com.arsdigita.cms.ui.workflow.TaskRequestLocal;
import com.arsdigita.cms.ui.workflow.WorkflowRequestLocal;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.kernel.KernelConfig;
import com.arsdigita.toolbox.ui.LayoutPanel;
import com.arsdigita.toolbox.ui.ModalPanel;
import com.arsdigita.toolbox.ui.Section;
import com.arsdigita.util.Assert;
import com.arsdigita.util.SequentialMap;
import com.arsdigita.util.UncheckedWrapperException;
import org.apache.logging.log4j.Logger;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Locale;
import java.util.Objects;
import java.util.ResourceBundle;
import org.apache.logging.log4j.LogManager;
import org.arsdigita.cms.CMSConfig;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.configuration.ConfigurationManager;
import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentItem;
import org.librecms.contenttypes.AuthoringKit;
import org.librecms.contenttypes.AuthoringKitInfo;
import org.librecms.contenttypes.AuthoringStepInfo;
import org.librecms.contenttypes.ContentTypeInfo;
import org.librecms.workflow.CmsTaskType;
/**
* This class represents a single authoring kit. The wizard accepts a
* {@link ContentType} in the constructor; it then extracts the
* {@link AuthoringKit} for the content type, and creates the components for all
* the steps in the kit.
*
* Note that the individual authoring kit steps must provide the following
* constructor:
*
* <blockquote><pre><code>
* public TheClass(ItemSelectionModel model, AuthoringKitWizard parent) { ... }
* </code></pre></blockquote>
*
* This constructor will be called when the component is automatically
* instantiated by the <code>AuthoringKitWizard</code>.
*
*/
public class AuthoringKitWizard extends LayoutPanel implements Resettable {
/**
* Private Logger instance for this class
*/
private static final Logger LOGGER = LogManager.getLogger(
AuthoringKitWizard.class);
private static Class[] arguments = new Class[]{
ItemSelectionModel.class,
AuthoringKitWizard.class
};
private static Class[] userDefinedArgs = new Class[]{
ItemSelectionModel.class,
AuthoringKitWizard.class,
ContentType.class
};
private static final java.util.List<AssetStepEntry> ASSETS = new ArrayList<AssetStepEntry>();
private final Object[] values;
private final ContentTypeInfo typeInfo;
private final AuthoringKitInfo kitInfo;
private final ItemSelectionModel selectionModel;
private final WorkflowRequestLocal workflowRequestLocal;
private final AssignedTaskTable assignedTaskTable;
private final SequentialMap labels;
private final List list;
private String defaultKey;
private final GridPanel leftPanel;
private final ModalPanel bodyPanel;
private final SimpleContainer stepsContainer;
private final TaskFinishForm m_taskFinishForm;
/**
* The name of the state parameter that determines whether the wizard is in
* item creation mode or item editing mode.
*/
public static final String IS_EDITING = "is_edit";
/**
* The key for the item creation step.
*/
public static final String CREATION = "_creation_";
private final static String SEC_PAGE_EDIT_DYN = "com.arsdigita.cms.ui.authoring.SecondaryPageEditDynamic";
private final static String PAGE_EDIT_DYN = "com.arsdigita.cms.ui.authoring.PageEditDynamic";
/**
* Construct a new AuthoringKitWizard. Add all the steps in the authoring
* kit to the wizard.
*
* @param typeInfo The content type of the items that this wizard will
* handle
* @param selectionModel
*/
public AuthoringKitWizard(final ContentTypeInfo typeInfo,
final ItemSelectionModel selectionModel) {
LOGGER.debug("Authoring kit wizard for type {} undergoing creation...",
Objects.toString(typeInfo));
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ConfigurationManager confManager = cdiUtil.findBean(
ConfigurationManager.class);
this.typeInfo = typeInfo;
kitInfo = typeInfo.getAuthoringKit();
this.selectionModel = selectionModel;
values = new Object[]{selectionModel, this};
workflowRequestLocal = new ItemWorkflowRequestLocal();
labels = new SequentialMap();
leftPanel = new GridPanel(1);
setLeft(leftPanel);
assignedTaskTable = new AssignedTaskTable(workflowRequestLocal);
leftPanel.add(new AssignedTaskSection(workflowRequestLocal,
assignedTaskTable));
final Section stepSection = new Section(gz("cms.ui.authoring.steps"));
leftPanel.add(stepSection);
list = new List();
stepSection.setBody(list);
list.setListData(labels);
list.setCellRenderer(new ListCellRenderer() {
@Override
public Component getComponent(List list,
PageState state,
Object value,
String key,
int index,
boolean isSelected) {
final Label label;
if (value instanceof GlobalizedMessage) {
label = new Label((GlobalizedMessage) value);
} else {
label = new Label((String) value);
}
if (isSelected) {
label.setFontWeight(Label.BOLD);
return label;
}
return new ControlLink(label);
}
});
bodyPanel = new ModalPanel();
setBody(bodyPanel);
stepsContainer = new SimpleContainer();
bodyPanel.add(stepsContainer);
bodyPanel.setDefault(stepsContainer);
final java.util.List<AuthoringStepInfo> steps = kitInfo.
getAuthoringSteps();
if (Assert.isEnabled()) {
Assert.isTrue(!steps.isEmpty(),
String.format("The authoring kit for content type "
+ "s\"%s\" has no steps.",
typeInfo.getContentItemClass().getName()));
}
final CMSConfig cmsConfig = confManager.findConfiguration(
CMSConfig.class);
StepComponent panel = null;
for (final AuthoringStepInfo step : steps) {
final String key = step.getComponent().getName();
if (defaultKey == null) {
defaultKey = key;
}
/**
* The "label" and "description" are only here for backwards
* compatibility
*/
final ResourceBundle labelBundle = ResourceBundle.getBundle(step.
getLabelBundle());
final ResourceBundle descBundle = ResourceBundle.getBundle(step.
getDescriptionBundle());
final String labelKey = step.getLabelKey();
final String label = labelBundle.getString(labelKey);
final String descriptionKey = step.getDescriptionKey();
final String description = descBundle.getString(descriptionKey);
final Class<? extends Component> componentClass = step.
getComponent();
final String compClassName = componentClass.getName();
if (panel != null) {
panel.setNextStepKey(step.getClass().getName());
}
panel = new StepComponent(compClassName);
stepsContainer.add(panel);
final Component comp;
if (compClassName.equals(SEC_PAGE_EDIT_DYN)
|| compClassName.equals(PAGE_EDIT_DYN)) {
comp = instantiateUserDefinedStep(compClassName, typeInfo);
} else {
comp = instantiateStep(compClassName);
}
panel.add(comp);
// XXX should be optional
if (comp instanceof AuthoringStepComponent) {
((AuthoringStepComponent) comp).addCompletionListener(
new StepCompletionListener());
}
final GlobalizedMessage gzLabel;
if (labelKey != null) {
if (step.getLabelBundle() == null) {
gzLabel = gz(labelKey);
} else {
gzLabel = new GlobalizedMessage(labelKey,
step.getLabelBundle());
}
} else {
gzLabel = null;
}
if (gzLabel == null) {
labels.put(key, label);
} else {
labels.put(key, gzLabel);
}
}
final Class<? extends ContentItem> typeClass = typeInfo.
getContentItemClass();
final java.util.List<String> skipSteps = cmsConfig.getSkipAssetSteps();
if (LOGGER.isDebugEnabled()) {
for (final String step : skipSteps) {
LOGGER.debug("skip step \"{}\"...", step);
}
}
for (final AssetStepEntry data : ASSETS) {
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) {
panel.setNextStepKey(step);
}
panel = new StepComponent(step);
stepsContainer.add(panel);
Component comp = instantiateStep(step.getName());
if (comp instanceof AuthoringStepComponent) {
((AuthoringStepComponent) comp).addCompletionListener(
new StepCompletionListener());
}
panel.add(comp);
labels.put(step, label);
}
}
list.addChangeListener(new StepListener());
m_taskFinishForm = new TaskFinishForm(new TaskSelectionRequestLocal());
bodyPanel.add(m_taskFinishForm);
bodyPanel.connect(assignedTaskTable, 2, m_taskFinishForm);
bodyPanel.connect(m_taskFinishForm);
m_taskFinishForm.addProcessListener(new FormProcessListener() {
@Override
public final void process(final FormSectionEvent event)
throws FormProcessException {
final PageState state = event.getPageState();
assignedTaskTable.getRowSelectionModel().clearSelection(state);
}
});
}
private final class StepListener implements ChangeListener {
@Override
public final void stateChanged(final ChangeEvent event) {
final PageState state = event.getPageState();
final String key = list.getSelectedKey(state).toString();
final Iterator iter = stepsContainer.children();
while (iter.hasNext()) {
final StepComponent step = (StepComponent) iter.next();
if (step.getStepKey().toString().equals(key)) {
step.setVisible(state, true);
} else {
step.setVisible(state, false);
}
}
}
}
/**
*
*/
private final class StepCompletionListener implements ActionListener {
@Override
public final void actionPerformed(final ActionEvent event) {
final PageState state = event.getPageState();
if (ContentItemPage.isStreamlinedCreationActive(state)) {
final String key = list.getSelectedKey(state).toString();
final Iterator iter = stepsContainer.children();
while (iter.hasNext()) {
final StepComponent step = (StepComponent) iter.next();
if (step.getStepKey().toString().equals(key)) {
Object nextStep = step.getNextStepKey();
if (nextStep != null) {
list.getSelectionModel().setSelectedKey(
state, nextStep.toString());
}
}
}
}
}
}
@Override
public final void register(final Page page) {
super.register(page);
final Iterator iter = stepsContainer.children();
while (iter.hasNext()) {
final StepComponent child = (StepComponent) iter.next();
page.setVisibleDefault(child, false);
}
page.addActionListener(new ActionListener() {
@Override
public final void actionPerformed(final ActionEvent event) {
final PageState state = event.getPageState();
if (state.isVisibleOnPage(AuthoringKitWizard.this)) {
final SingleSelectionModel model = list.
getSelectionModel();
if (!model.isSelected(state)) {
model.setSelectedKey(state, defaultKey);
}
}
}
});
}
public static void registerAssetStep(final String baseObjectType,
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 String thisObjectType = data.getBaseDataObjectType();
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 The content type handled by this wizard
*/
public ContentTypeInfo getContentType() {
return typeInfo;
}
public List getList() {
return list;
}
/**
* @return The authoring kit which is represented by this wizard
*/
public AuthoringKitInfo getAuthoringKit() {
return kitInfo;
}
/**
* @return The ItemSelectionModel used by the steps in this wizard
*/
public ItemSelectionModel getItemSelectionModel() {
return selectionModel;
}
/**
* Instantiate the specified authoring kit step. Will throw a
* RuntimeException on failure.
*
* @param className The Java class name of the step
* @return The instance of the component.
*/
protected Component instantiateStep(final String className) {
LOGGER.debug("Instantiating kit wizard \"{}\" with arguments {}...",
className,
arguments);
Object[] vals;
try {
// Get the creation component
final Class createClass = Class.forName(className);
final Constructor constr = createClass.getConstructor(arguments);
final Component component = (Component) constr.newInstance(values);
return component;
} catch (ClassNotFoundException
| IllegalAccessException
| IllegalArgumentException
| InstantiationException
| InvocationTargetException
| NoSuchMethodException
| SecurityException ex) {
throw new UncheckedWrapperException(String.format(
"Failed to instantiate authoring kit component \"{}\".",
className),
ex);
}
}
/**
* Instantiate the specified authoring kit step for a user defined content
* type. Will throw a RuntimeException on failure.
*
* @param className The Java class name of the step
* @param originatingType
* @return
*/
protected Component instantiateUserDefinedStep(
final String className, final ContentTypeInfo originatingType) {
Object[] vals;
try {
// Get the creation component
final Class createClass = Class.forName(className);
final Constructor constr = createClass.getConstructor(
userDefinedArgs);
final Object[] userDefinedVals = new Object[]{selectionModel,
this,
originatingType};
final Component component = (Component) constr.newInstance(
userDefinedVals);
return component;
} catch (ClassNotFoundException | NoSuchMethodException
| InstantiationException | IllegalAccessException
| InvocationTargetException ex) {
throw new UncheckedWrapperException(ex);
}
}
/**
* Reset the state of this wizard
*/
@Override
public final void reset(final PageState state) {
list.setSelectedKey(state, defaultKey);
}
private final class StepComponent extends SimpleContainer {
private final Object key;
private Object nextKey;
public StepComponent(final Object key) {
this.key = key;
}
public Object getStepKey() {
return key;
}
public Object getNextStepKey() {
return nextKey;
}
public void setNextStepKey(final Object nextKey) {
this.nextKey = nextKey;
}
}
private final class TaskSelectionRequestLocal extends TaskRequestLocal {
@Override
protected final Object initialValue(final PageState state) {
final String key = assignedTaskTable
.getRowSelectionModel()
.getSelectedKey(state)
.toString();
return CmsTaskType.valueOf(key);
}
}
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

@ -0,0 +1,37 @@
/*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.authoring;
import com.arsdigita.bebop.event.ActionListener;
/**
* Interface which authoring step components should implement. It's
* currently an optional interface.
*
* @author Scott Seago (sseago@redhat.com)
* @version $Revision: #4 $ $DateTime: 2004/08/17 23:15:09 $
*/
public interface AuthoringStepComponent {
/**
* Add a completion listener to this component
*/
void addCompletionListener(ActionListener listener);
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.authoring;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.SingleSelect;
import com.arsdigita.bebop.parameters.ParameterModel;
import com.arsdigita.bebop.parameters.StringParameter;
import org.librecms.util.LanguageUtil;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.util.Pair;
import java.util.List;
import org.libreccm.cdi.utils.CdiUtil;
/**
* Language picker for the multilingual content items.
*/
public class LanguageWidget extends SingleSelect {
public LanguageWidget(String name) {
this(new StringParameter(name));
}
public LanguageWidget(ParameterModel model) {
super(model);
setupOptions();
}
/**
* Adds list of languages. Default version shows all supported languages for
* this CMS installation, as defined in the enterprise.init:
* com.arsdigita.cms.installer.Initializer: languages
*/
protected void setupOptions() {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final LanguageUtil languageUtil = cdiUtil.findBean(LanguageUtil.class);
final List<Pair> languages = languageUtil.convertToG11N(languageUtil.
getSupportedLanguages2LA());
for(final Pair pair : languages) {
final String langCode = (String) pair.getKey();
final GlobalizedMessage langName = (GlobalizedMessage) pair.getValue();
addOption(new Option(langCode, new Label(langName)));
}
}
}

View File

@ -57,7 +57,7 @@ import java.math.BigDecimal;
public class WizardSelector extends AuthoringKitSelector public class WizardSelector extends AuthoringKitSelector
implements Resettable { implements Resettable {
private ItemSelectionModel itemSelectionModel; private final ItemSelectionModel itemSelectionModel;
/** /**
* Construct a new WizardSelector. Load all the possible authoring kits from * Construct a new WizardSelector. Load all the possible authoring kits from

View File

@ -0,0 +1,203 @@
/*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.item;
import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.OptionGroup;
import com.arsdigita.bebop.form.Submit;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentType;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.ui.ContentItemPage;
import com.arsdigita.cms.ui.authoring.LanguageWidget;
import org.librecms.util.LanguageUtil;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.toolbox.ui.LayoutPanel;
import com.arsdigita.toolbox.ui.Section;
import com.arsdigita.util.Assert;
import com.arsdigita.util.Pair;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.web.RedirectSignal;
import com.arsdigita.web.URL;
import org.libreccm.workflow.Workflow;
import org.libreccm.workflow.WorkflowTemplate;
import org.apache.log4j.Logger;
import java.util.Collection;
import java.util.Iterator;
import java.util.TooManyListenersException;
/**
* Displays the "Language instances" pane, with all the language instances in
* the Bundle.
*
* @author Alan Pevec (apevec@redhat.com)
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ItemLanguages extends LayoutPanel {
private final ItemSelectionModel selectionModel;
private final LanguageWidget languageWidget;
private final Submit changeSubmit;
private final Submit createSubmit;
/**
* Constructs a new <code>ItemLanguages</code>.
*
* @param selectionModel the {@link ItemSelectionModel} which will supply the current
* item
*/
public ItemLanguages(final ItemSelectionModel selectionModel) {
this.selectionModel = selectionModel;
final Section section = new Section(gz("cms.ui.item.languages"));
setBody(section);
final ActionGroup group = new ActionGroup();
section.setBody(group);
group.setSubject(new ItemLanguagesTable(selectionModel));
final Form form = new Form("newLanguage", new BoxPanel(
BoxPanel.HORIZONTAL));
group.addAction(form);
form.setRedirecting(true);
languageWidget = new LanguageWidget(ContentItem.LANGUAGE) {
protected void setupOptions() {
// Don't do anything.
}
};
try {
languageWidget.addPrintListener(new OptionPrinter());
} catch (TooManyListenersException tmle) {
new UncheckedWrapperException(tmle);
}
form.add(languageWidget);
changeSubmit = new Submit("change", gz("cms.ui.item.language.change"));
form.add(changeSubmit);
createSubmit = new Submit("create", gz("cms.ui.item.language.add"));
form.add(createSubmit);
form.addProcessListener(new ProcessListener());
}
/**
* Offers only languages not yet present in the bundle.
*/
private class OptionPrinter implements PrintListener {
public final void prepare(final PrintEvent e) {
final PageState state = e.getPageState();
final OptionGroup optionGroup = (OptionGroup) e.getTarget();
final ContentPage item = (ContentPage) selectionModel.
getSelectedItem(state);
final Collection languages = LanguageUtil.convertToG11N(
LanguageUtil.getCreatableLanguages(item));
for (Iterator iter = languages.iterator(); iter.hasNext();) {
final Pair pair = (Pair) iter.next();
final String langCode = (String) pair.getKey();
final GlobalizedMessage langName
= (GlobalizedMessage) pair.getValue();
optionGroup.addOption(new Option(langCode, new Label(langName)));
}
}
}
/**
* Adds a new language instance to the bundle.
*/
private class ProcessListener implements FormProcessListener {
public final void process(final FormSectionEvent e)
throws FormProcessException {
PageState state = e.getPageState();
String lang = (String) languageWidget.getValue(state);
ContentPage item = (ContentPage) selectionModel.getSelectedItem(state);
ContentBundle bundle = item.getContentBundle();
String name = bundle.getName();
if (createSubmit.isSelected(state)) {
ContentSection section = item.getContentSection();
Assert.exists(section, ContentSection.class);
ContentType type = item.getContentType();
item = (ContentPage) item.copy(lang);
item.setLanguage(lang);
item.setName(name);
// Apply default workflow
WorkflowTemplate template
= ContentTypeWorkflowTemplate
.getWorkflowTemplate(section, type);
if (template != null) {
Workflow w = template.instantiateNewWorkflow();
w.setObjectID(item.getID());
w.start(Kernel.getContext().getUser());
w.save();
}
selectionModel.setSelectedObject(state, item);
// redirect to ContentItemPage.AUTHORING_TAB of the new instance
final String target = URL.getDispatcherPath() + ContentItemPage.
getItemURL(item,
ContentItemPage.AUTHORING_TAB);
throw new RedirectSignal(target, true);
} else if (changeSubmit.isSelected(state)) {
String oldLang = item.getLanguage();
item.setLanguage(lang);
// propagate language change to the Name attribute
item.setName(name);
item.save();
// if the item being changed is the default, update the bundle
// to keep this item as the default
if (bundle.getDefaultLanguage().equals(oldLang)) {
bundle.setDefaultLanguage(lang);
bundle.save();
}
}
}
}
protected static final GlobalizedMessage gz(final String key) {
return GlobalizationUtil.globalize(key);
}
protected static final String lz(final String key) {
return (String) gz(key).localize();
}
}

View File

@ -0,0 +1,255 @@
/*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.item;
import com.arsdigita.bebop.*;
import com.arsdigita.bebop.event.TableActionAdapter;
import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.table.TableCellRenderer;
import com.arsdigita.bebop.table.TableColumn;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.dispatcher.MultilingualItemResolver;
import com.arsdigita.cms.ui.ContentItemPage;
import org.librecms.util.LanguageUtil;
import com.arsdigita.toolbox.ui.DataTable;
import com.arsdigita.util.LockableImpl;
import com.arsdigita.web.RedirectSignal;
import com.arsdigita.web.URL;
import java.math.BigDecimal;
import org.apache.log4j.Logger;
/**
* Displays a list of all language instances of an item.
*
*/
public class ItemLanguagesTable extends DataTable {
private static final Logger LOGGER = Logger.getLogger(ItemLanguagesTable.class);
private final ItemSelectionModel m_model;
private final TableColumn m_deleteColumn;
/**
* Construct a new
* <code>ItemHistoryTable</code>
*
* @param model the ItemSelectionModel that supplies the current item
*/
public ItemLanguagesTable(ItemSelectionModel model) {
super(new LanguagesBuilder(model));
m_model = model;
addColumn("cms.ui.language.header",
ContentPage.LANGUAGE,
false,
new LanguageCellRenderer(m_model));
addColumn("cms.ui.title",
ContentPage.TITLE);
m_deleteColumn = addColumn("cms.ui.action", new ActionCellRenderer(
m_model));
setResourceBundle(GlobalizationUtil.getBundleName());
addTableActionListener(new InstanceDeleter(m_model));
}
/**
* Builds the query for all the language instances in the current Bundle
*/
private static class LanguagesBuilder extends LockableImpl
implements DataQueryBuilder {
ItemSelectionModel m_model;
public LanguagesBuilder(ItemSelectionModel model) {
super();
m_model = model;
}
public DataQuery makeDataQuery(DataTable t, PageState s) {
ContentPage multiLingual =
(ContentPage) m_model.getSelectedObject(s);
DataQuery q = SessionManager.getSession().retrieveQuery(
"com.arsdigita.cms.getBundledItems");
q.setParameter("bundleID", multiLingual.getContentBundle().getID());
return q;
}
public String getKeyColumn() {
return ContentPage.ID;
}
}
/**
* Renders the full language name.
*/
private static class LanguageCellRenderer implements TableCellRenderer {
private ItemSelectionModel m_model;
public LanguageCellRenderer(ItemSelectionModel model) {
m_model = model;
}
public Component getComponent(Table table, PageState state, Object value,
boolean isSelected, Object key,
int row, int column) {
BigDecimal id = (BigDecimal) key;
ContentPage cp;
try {
cp = new ContentPage(id);
} catch (DataObjectNotFoundException ex) {
// Content item was not found, return nothing
return new Label();
}
ContentBundle bundle = cp.getContentBundle();
if (bundle != null
&& !(cp instanceof LanguageInvariantContentItem
&& ((LanguageInvariantContentItem) cp).isLanguageInvariant())) {
StringBuilder fontWeight = new StringBuilder(2);
StringBuilder classes = new StringBuilder(20);
if (cp.isLive()) {
fontWeight.append(Label.BOLD);
classes.append("live ");
}
if (bundle.getPrimaryInstance().equals(cp)) {
fontWeight.append(Label.ITALIC);
classes.append("primaryInstance");
}
String target = ContentItemPage.getItemURL(cp, ContentItemPage.AUTHORING_TAB);
Label langLabel = new Label(LanguageUtil.getLangFull((String) value));
langLabel.setFontWeight(fontWeight.toString().trim());
langLabel.setClassAttr(classes.toString().trim());
if (m_model.getSelectedKey(state).equals(key)) {
// Current instance: no link
return langLabel;
} else {
return new Link(langLabel, target);
}
}
return new Label();
}
}
/**
* Delete language instance action link.
*/
private static class ActionCellRenderer implements TableCellRenderer {
private static final Logger logger =
Logger.getLogger(ActionCellRenderer.class);
private static final Label s_noAction;
private static final Label s_primary;
private static final ControlLink s_link;
static {
logger.debug("Static initializer is starting...");
s_noAction = new Label("&nbsp;", false);
s_noAction.lock();
s_primary = new Label(GlobalizationUtil.globalize(
"cms.ui.primary_instance"), false);
s_primary.lock();
s_link = new ControlLink(new Label(GlobalizationUtil.globalize(
"cms.ui.delete")));
s_link.setConfirmation(GlobalizationUtil.globalize(
"cms.ui.delete_confirmation"));
logger.debug("Static initalizer finished.");
}
private ItemSelectionModel m_model;
public ActionCellRenderer(ItemSelectionModel model) {
m_model = model;
}
public Component getComponent(Table table, PageState state, Object value,
boolean isSelected, Object key,
int row, int column) {
// check if primary instance
BigDecimal id = new BigDecimal(key.toString());
OID oid = new OID(ContentPage.BASE_DATA_OBJECT_TYPE, id);
try {
ContentPage item = (ContentPage) DomainObjectFactory.newInstance(oid);
if (item.getLanguage().equals(
item.getContentBundle().getDefaultLanguage())) {
return s_primary;
} else if (item.isLive()) {
return s_noAction;
}
} catch (DataObjectNotFoundException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not get item with id " + id);
}
return s_noAction;
}
return s_link;
}
}
// delete one language instance
private class InstanceDeleter extends TableActionAdapter {
private ItemSelectionModel m_model;
public InstanceDeleter(ItemSelectionModel model) {
m_model = model;
}
@Override
public void cellSelected(TableActionEvent e) {
int col = e.getColumn().intValue();
if (m_deleteColumn != getColumn(col)) {
return;
}
PageState s = e.getPageState();
BigDecimal id = new BigDecimal(e.getRowKey().toString());
OID oid = new OID(ContentPage.BASE_DATA_OBJECT_TYPE, id);
try {
ContentPage item =
(ContentPage) DomainObjectFactory.newInstance(oid);
ContentBundle bundle = item.getContentBundle();
bundle.removeInstance(item);
item.delete();
if (m_model.getSelectedKey(s).equals(id)) {
throw new RedirectSignal(
URL.there((new MultilingualItemResolver()
.generateItemURL(s,
bundle.getPrimaryInstance(),
bundle.getContentSection(),
ContentItem.DRAFT)),
null),
true);
}
} catch (com.arsdigita.domain.DataObjectNotFoundException ex) {
// Object not found is ok, it has probably been deleted already
}
((Table) e.getSource()).clearSelection(s);
}
}
}

View File

@ -134,6 +134,13 @@ public class ContentItemL10NManager {
return collectLanguages(item).contains(locale); return collectLanguages(item).contains(locale);
} }
@Transactional(Transactional.TxType.REQUIRED)
public Set<Locale> creatableLocales(final ContentItem item) {
return supportedLocales.stream()
.filter(locale -> hasLanguage(item, locale))
.collect(Collectors.toSet());
}
/** /**
* Adds a language to a content item. The method will retrieve all fields of * Adds a language to a content item. The method will retrieve all fields of