libreccm-legacy/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/ItemLifecycleItemPane.java

594 lines
22 KiB
Java
Executable File

/*
* 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.lifecycle;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.event.FormSectionEvent;
import java.text.DateFormat;
import org.apache.log4j.Logger;
import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormData;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.RequestLocal;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.FormInitListener;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.SingleSelect;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.cms.CMS;
import com.arsdigita.cms.CMSConfig;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.ContentSection;
import com.arsdigita.cms.SecurityManager;
import com.arsdigita.cms.dispatcher.Utilities;
import com.arsdigita.cms.lifecycle.Lifecycle;
import com.arsdigita.cms.ui.BaseItemPane;
import com.arsdigita.cms.ui.ContentItemPage;
import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.persistence.OID;
import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.toolbox.ui.PropertyList;
import com.arsdigita.toolbox.ui.Section;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.web.RedirectSignal;
import com.arsdigita.web.URL;
import com.arsdigita.web.Web;
import com.arsdigita.workflow.simple.TaskException;
import com.arsdigita.workflow.simple.Workflow;
import com.arsdigita.xml.Element;
/**
* This class contains the component which displays the information
* for a particular lifecycle, with the ability to edit and delete.
* This information also includes the associated phases for this
* lifecycle, also with the ability to add, edit, and delete.
*
* @author Michael Pih
* @author Jack Chung
* @author Xixi D'Moon <xdmoon@redhat.com>
* @author Justin Ross <jross@redhat.com>
* @author Jens Pelzetter jens@jp-digital.de
* @version $Id: ItemLifecycleItemPane.java 1942 2009-05-29 07:53:23Z terry $
*/
class ItemLifecycleItemPane extends BaseItemPane {
private static final Logger s_log = Logger.getLogger(
ItemLifecycleItemPane.class);
private final ContentItemRequestLocal m_item;
private final LifecycleRequestLocal m_lifecycle;
private final SimpleContainer m_detailPane;
public ItemLifecycleItemPane(final ContentItemRequestLocal item,
final LifecycleRequestLocal cycle) {
m_item = item;
m_lifecycle = cycle;
m_detailPane = new SimpleContainer();
add(m_detailPane);
setDefault(m_detailPane);
m_detailPane.add(new SummarySection());
m_detailPane.add(new PhaseSection());
}
private class SummarySection extends Section {
public SummarySection() {
setHeading(new Label(gz("cms.ui.lifecycle.details")));
final ActionGroup group = new ActionGroup();
setBody(group);
if (CMS.getConfig().getUseOldStyleItemLifecycleItemPane()) {
group.setSubject(new Properties());
group.addAction(new UnpublishLink());
group.addAction(new RepublishLink());
if (!ContentSection.getConfig().hideResetLifecycleLink()) {
group.addAction(new RepublishAndResetLink());
}
} else {
group.addAction(new ActionForm());
}
}
private class Properties extends PropertyList {
protected final java.util.List properties(final PageState state) {
final java.util.List props = super.properties(state);
final Lifecycle cycle = m_lifecycle.getLifecycle(state);
final DateFormat format =
DateFormat.getDateTimeInstance(DateFormat.FULL,
ContentSection.
getConfig().getHideTimezone() ? DateFormat.SHORT
: DateFormat.FULL);
props.add(new Property(gz("cms.ui.name"),
cycle.getLabel()));
props.add(new Property(gz("cms.ui.item.lifecycle.start_date"),
format.format(cycle.getStartDate())));
final java.util.Date endDate = cycle.getEndDate();
if (endDate == null) {
props.add(new Property(gz("cms.ui.item.lifecycle.end_date"),
lz("cms.ui.none")));
} else {
props.add(new Property(gz("cms.ui.item.lifecycle.end_date"),
format.format(endDate)));
}
return props;
}
}
}
private class PublishLink extends ActionLink {
private RequestLocal m_canPublish = new RequestLocal();
PublishLink(Component c) {
super(c);
}
public void generateXML(PageState ps, Element parent) {
Boolean canPublish = (Boolean) m_canPublish.get(ps);
if (null == canPublish) {
SecurityManager sm = Utilities.getSecurityManager(ps);
ContentItem item = m_item.getContentItem(ps);
if (sm.canAccess(ps.getRequest(),
SecurityManager.PUBLISH,
item)) {
canPublish = Boolean.TRUE;
} else {
canPublish = Boolean.FALSE;
}
m_canPublish.set(ps, canPublish);
}
if (canPublish.booleanValue()) {
if (s_log.isDebugEnabled()) {
ContentItem item = m_item.getContentItem(ps);
s_log.debug("User can publish " + item.getOID());
}
super.generateXML(ps, parent);
} else if (s_log.isDebugEnabled()) {
ContentItem item = m_item.getContentItem(ps);
s_log.debug("User cannot publish " + item.getOID());
}
}
}
private class UnpublishLink extends PublishLink {
UnpublishLink() {
super(new Label(gz("cms.ui.item.lifecycle.unpublish")));
addActionListener(new Listener());
}
private class Listener implements ActionListener {
public final void actionPerformed(final ActionEvent e) {
final PageState state = e.getPageState();
final ContentItem item = m_item.getContentItem(state);
item.unpublish();
final String target = URL.getDispatcherPath() + ContentItemPage.
getItemURL(item,
ContentItemPage.AUTHORING_TAB);
throw new RedirectSignal(target, true);
}
}
}
private static void republish(ContentItem item, boolean reset) {
item.republish(reset);
Workflow workflow = Workflow.getObjectWorkflow(item);
try {
ItemLifecycleSelectForm.finish(workflow, item, Web.getContext().
getUser());
} catch (TaskException te) {
throw new UncheckedWrapperException(te);
}
}
private class RepublishLink extends PublishLink {
RepublishLink() {
super(new Label(gz("cms.ui.item.lifecycle.republish")));
addActionListener(new Listener());
}
private class Listener implements ActionListener {
public final void actionPerformed(final ActionEvent e) {
final PageState state = e.getPageState();
final ContentItem item = m_item.getContentItem(state);
/*
* jensp 2011-12-14: Check is threaded publishing is active. If
* yes, execute publishing in a thread.
*/
if (CMSConfig.getInstance().getThreadedPublishing()) {
final Republisher republisher = new Republisher(item);
final Thread thread = new Thread(republisher);
thread.start();
throw new RedirectSignal(
URL.getDispatcherPath()
+ ContentItemPage.getItemURL(item,
ContentItemPage.PUBLISHING_TAB),
true);
/*
* jensp 2011-12-14 end
*/
} else {
republish(item, false);
if (ContentSection.getConfig().getUseStreamlinedCreation()) {
throw new RedirectSignal(
URL.there(state.getRequest(),
Utilities.getWorkspaceURL()), true);
}
}
}
}
/**
* @author Jens Pelzetter
*/
private class Republisher implements Runnable {
/**
* Saves OID of item as a string. This is necessary because it is
* not possible to access to same data object instance from
* multiple threads. So we have to create a new instance a the
* data object in the run method. To avoid any sort a problems,
* we store the OID as a string and convert it back to an OID in
* the run method.
*/
private final String itemOid;
private Republisher(final ContentItem item) {
itemOid = item.getOID().toString();
}
public void run() {
final ContentItem item = (ContentItem) DomainObjectFactory.
newInstance(OID.valueOf(itemOid));
PublishLock.getInstance().lock(item);
republish(item, false);
PublishLock.getInstance().unlock(item);
}
}
}
private class RepublishAndResetLink extends PublishLink {
RepublishAndResetLink() {
super(new Label(gz("cms.ui.item.lifecycle.republish_and_reset")));
addActionListener(new Listener());
// warning gets a bit annoying, and link should be descriptive
// enough that it is not required
// setConfirmation("This will reset all your publication dates, are
// you sure you want to continue?");
}
private class Listener implements ActionListener {
public final void actionPerformed(final ActionEvent e) {
final PageState state = e.getPageState();
final ContentItem item = m_item.getContentItem(state);
/**
* jensp 2011-12-14: Execute is a thread if
* threaded publishing is active.
*/
if (CMSConfig.getInstance().getThreadedPublishing()) {
final Republisher republisher = new Republisher(item);
final Thread thread = new Thread(republisher);
thread.start();
throw new RedirectSignal(
URL.getDispatcherPath()
+ ContentItemPage.getItemURL(item,
ContentItemPage.PUBLISHING_TAB),
true);
} else {
/**
* jensp 2011-12-14 end
*/
republish(item, true);
if (ContentSection.getConfig().getUseStreamlinedCreation()) {
throw new RedirectSignal(
URL.there(state.getRequest(),
Utilities.getWorkspaceURL()), true);
}
}
}
}
/**
* @author Jens Pelzetter
*/
private class Republisher implements Runnable {
/**
* Saves OID of item as a string. This is necessary because it is
* not possible to access to same data object instance from
* multiple threads. So we have to create a new instance a the
* data object in the run method. To avoid any sort a problems,
* we store the OID as a string and convert it back to an OID in
* the run method.
*/
private final String itemOid;
private Republisher(final ContentItem item) {
itemOid = item.getOID().toString();
}
public void run() {
final ContentItem item = (ContentItem) DomainObjectFactory.
newInstance(OID.valueOf(itemOid));
PublishLock.getInstance().lock(item);
republish(item, true);
PublishLock.getInstance().unlock(item);
}
}
}
private class PhaseSection extends Section {
PhaseSection() {
super(gz("cms.ui.lifecycle.phases"));
final ActionGroup group = new ActionGroup();
setBody(group);
group.setSubject(new PhaseTable());
}
}
private class PhaseTable extends Table {
PhaseTable() {
super(new ItemPhaseTableModelBuilder(m_lifecycle),
new String[]{
lz("cms.ui.name"),
lz("cms.ui.description"),
lz("cms.ui.item.lifecycle.start_date"),
lz("cms.ui.item.lifecycle.end_date")
});
}
}
/**
* New style pane. Uses a select box for the action to avoid wrong clicks
* on unpublish.
*
* @author Jens Pelzetter
*/
private class ActionForm
extends Form
implements FormProcessListener,
FormInitListener {
private static final String LIFECYCLE_ACTION =
"itemLifecycleItemPaneActionSelect";
private static final String REPUBLISH = "republish";
private static final String UNPUBLISH = "unpublish";
private static final String REPUBLISH_AND_RESET = "republishAndReset";
private final Submit submit;
private final Label notAuthorized;
public ActionForm() {
super("itemLifecycleItemPaneActionForm");
final BoxPanel actionPanel = new BoxPanel(BoxPanel.HORIZONTAL);
final SingleSelect actionSelect = new SingleSelect(
LIFECYCLE_ACTION);
actionSelect.addOption(new Option(REPUBLISH, (String) gz(
"cms.ui.item.lifecycle.republish").localize()));
if (!ContentSection.getConfig().hideResetLifecycleLink()) {
actionSelect.addOption(new Option(REPUBLISH_AND_RESET,
(String) gz(
"cms.ui.item.lifecycle.republish_and_reset").
localize()));
}
actionSelect.addOption(new Option(UNPUBLISH, (String) gz(
"cms.ui.item.lifecycle.unpublish").localize()));
submit = new Submit(gz("cms.ui.item.lifecycle.do"));
notAuthorized = new Label(gz(
"cms.ui.item.lifecycle.do.not_authorized"));
actionPanel.add(actionSelect);
actionPanel.add(submit);
actionPanel.add(notAuthorized);
add(actionPanel);
addInitListener(this);
addProcessListener(this);
}
public void init(FormSectionEvent fse) throws FormProcessException {
final PageState state = fse.getPageState();
final ContentItem item = m_item.getContentItem(state);
final SecurityManager sm = Utilities.getSecurityManager(state);
if (sm.canAccess(state.getRequest(),
SecurityManager.PUBLISH,
item)) {
submit.setVisible(state, true);
notAuthorized.setVisible(state, false);
} else {
submit.setVisible(state, false);
notAuthorized.setVisible(state, true);
}
}
public void process(final FormSectionEvent fse) throws
FormProcessException {
final PageState state = fse.getPageState();
final FormData data = fse.getFormData();
String selected = (String) data.get(LIFECYCLE_ACTION);
final ContentItem item = m_item.getContentItem(state);
/**
* Republish/Republish and Reset are executed in the thread
* if threaded publishing is active.
*/
if (REPUBLISH.equals(selected)) {
if (CMSConfig.getInstance().getThreadedPublishing()) {
final RepublishRunner runner = new RepublishRunner(item);
final Thread thread = new Thread(runner);
thread.start();
throw new RedirectSignal(
URL.getDispatcherPath()
+ ContentItemPage.getItemURL(item,
ContentItemPage.PUBLISHING_TAB),
true);
} else {
republish(item, false);
if (ContentSection.getConfig().getUseStreamlinedCreation()) {
throw new RedirectSignal(
URL.there(state.getRequest(),
Utilities.getWorkspaceURL()), true);
}
}
} else if (REPUBLISH_AND_RESET.equals(selected)) {
if (CMSConfig.getInstance().getThreadedPublishing()) {
final RepublishAndResetRunner runner =
new RepublishAndResetRunner(
item);
final Thread thread = new Thread(runner);
thread.start();
throw new RedirectSignal(
URL.getDispatcherPath()
+ ContentItemPage.getItemURL(item,
ContentItemPage.PUBLISHING_TAB),
true);
} else {
republish(item, true);
if (ContentSection.getConfig().getUseStreamlinedCreation()) {
throw new RedirectSignal(
URL.there(state.getRequest(),
Utilities.getWorkspaceURL()), true);
}
}
} else if (UNPUBLISH.equals(selected)) {
item.unpublish();
} else {
throw new IllegalArgumentException("Illegal selection");
}
}
private class RepublishRunner implements Runnable {
/**
* Saves OID of item as a string. This is necessary because it is
* not possible to access to same data object instance from
* multiple threads. So we have to create a new instance a the
* data object in the run method. To avoid any sort a problems,
* we store the OID as a string and convert it back to an OID in
* the run method.
*/
private final String itemOid;
private RepublishRunner(final ContentItem item) {
itemOid = item.getOID().toString();
}
private void doRepublish() {
final ContentItem item = (ContentItem) DomainObjectFactory.
newInstance(OID.valueOf(itemOid));
republish(item, false);
}
public void run() {
final ContentItem item = (ContentItem) DomainObjectFactory.
newInstance(OID.valueOf(itemOid));
PublishLock.getInstance().lock(item);
doRepublish();
PublishLock.getInstance().unlock(item);
}
}
private class RepublishAndResetRunner implements Runnable {
/**
* Saves OID of item as a string. This is necessary because it is
* not possible to access to same data object instance from
* multiple threads. So we have to create a new instance a the
* data object in the run method. To avoid any sort a problems,
* we store the OID as a string and convert it back to an OID in
* the run method.
*/
private final String itemOid;
private RepublishAndResetRunner(final ContentItem item) {
itemOid = item.getOID().toString();
}
private void doRepublishAndReset() {
final ContentItem item = (ContentItem) DomainObjectFactory.
newInstance(OID.valueOf(itemOid));
republish(item, true);
}
public void run() {
final ContentItem item = (ContentItem) DomainObjectFactory.
newInstance(OID.valueOf(itemOid));
PublishLock.getInstance().lock(item);
doRepublishAndReset();
PublishLock.getInstance().unlock(item);
}
}
}
}