From 24942b7a5c1253c5e8b71bc3aeed784ee268cf2d Mon Sep 17 00:00:00 2001 From: jensp Date: Fri, 13 Jan 2017 13:19:02 +0000 Subject: [PATCH] CCM NG: ContentItem Page ported git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4517 8810af33-2d31-482b-a856-94f89814c4df --- ...ava.todo => MultilingualItemResolver.java} | 0 ...lver.java.todo => SimpleItemResolver.java} | 0 ...r.java.todo => ContentItemContextBar.java} | 4 - ...temPage.java.todo => ContentItemPage.java} | 11 +- ...ava.todo => ContentSectionContextBar.java} | 0 ...Page.java.todo => ContentSectionPage.java} | 36 +- ...zard.java.todo => AuthoringKitWizard.java} | 0 ...Selector.java.todo => WizardSelector.java} | 0 ...k.java.todo => CustomizedPreviewLink.java} | 0 ...Languages.java.todo => ItemLanguages.java} | 0 ...able.java.todo => ItemLanguagesTable.java} | 0 ...java.todo => ItemLanguagesTableModel.java} | 0 ...do => ItemLanguagesTableModelBuilder.java} | 0 ....java.todo => ItemLifecycleAdminPane.java} | 0 ...e.java.todo => ItemLifecycleItemPane.java} | 529 ++++----- .../ui/lifecycle/ItemLifecycleSelectForm.java | 1058 +++++++++++++++++ .../ItemLifecycleSelectForm.java.todo | 1024 ---------------- .../lifecycle/ItemPhaseTableModelBuilder.java | 137 +++ ...Pane.java.todo => LifecycleAdminPane.java} | 0 ...mPane.java.todo => LifecycleItemPane.java} | 1 + .../ui/lifecycle/PhaseTableModelBuilder.java | 34 +- .../ui/revision/ItemRevisionAdminPane.java | 362 ++++++ .../revision/ItemRevisionAdminPane.java.todo | 316 ----- .../cms/ui/revision/RevisionRequestLocal.java | 33 + .../revision/RevisionTableModelBuilder.java | 164 +++ ...e.java.todo => ItemWorkflowAdminPane.java} | 0 ...ne.java.todo => ItemWorkflowItemPane.java} | 0 ...nishForm.java.todo => TaskFinishForm.java} | 0 .../AbstractAuditedEntityRepository.java | 31 +- .../java/org/libreccm/workflow/Workflow.java | 4 + .../libreccm/workflow/WorkflowRepository.java | 34 +- 31 files changed, 2093 insertions(+), 1685 deletions(-) rename ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/{MultilingualItemResolver.java.todo => MultilingualItemResolver.java} (100%) rename ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/{SimpleItemResolver.java.todo => SimpleItemResolver.java} (100%) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/{ContentItemContextBar.java.todo => ContentItemContextBar.java} (95%) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/{ContentItemPage.java.todo => ContentItemPage.java} (99%) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/{ContentSectionContextBar.java.todo => ContentSectionContextBar.java} (100%) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/{ContentSectionPage.java.todo => ContentSectionPage.java} (96%) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/{AuthoringKitWizard.java.todo => AuthoringKitWizard.java} (100%) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/{WizardSelector.java.todo => WizardSelector.java} (100%) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/item/{CustomizedPreviewLink.java.todo => CustomizedPreviewLink.java} (100%) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/item/{ItemLanguages.java.todo => ItemLanguages.java} (100%) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/item/{ItemLanguagesTable.java.todo => ItemLanguagesTable.java} (100%) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/item/{ItemLanguagesTableModel.java.todo => ItemLanguagesTableModel.java} (100%) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/item/{ItemLanguagesTableModelBuilder.java.todo => ItemLanguagesTableModelBuilder.java} (100%) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/{ItemLifecycleAdminPane.java.todo => ItemLifecycleAdminPane.java} (100%) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/{ItemLifecycleItemPane.java.todo => ItemLifecycleItemPane.java} (59%) create mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleSelectForm.java delete mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleSelectForm.java.todo create mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemPhaseTableModelBuilder.java rename ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/{LifecycleAdminPane.java.todo => LifecycleAdminPane.java} (100%) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/{LifecycleItemPane.java.todo => LifecycleItemPane.java} (99%) create mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/ItemRevisionAdminPane.java delete mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/ItemRevisionAdminPane.java.todo create mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/RevisionRequestLocal.java create mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/RevisionTableModelBuilder.java rename ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/{ItemWorkflowAdminPane.java.todo => ItemWorkflowAdminPane.java} (100%) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/{ItemWorkflowItemPane.java.todo => ItemWorkflowItemPane.java} (100%) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/{TaskFinishForm.java.todo => TaskFinishForm.java} (100%) diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/MultilingualItemResolver.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/MultilingualItemResolver.java similarity index 100% rename from ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/MultilingualItemResolver.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/MultilingualItemResolver.java diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/SimpleItemResolver.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/SimpleItemResolver.java similarity index 100% rename from ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/SimpleItemResolver.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/SimpleItemResolver.java diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemContextBar.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemContextBar.java similarity index 95% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemContextBar.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemContextBar.java index 3442ff5db..57aa93bca 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemContextBar.java.todo +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemContextBar.java @@ -23,16 +23,12 @@ import com.arsdigita.cms.CMS; import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentSection; -import org.librecms.contentsection.ContentType; import com.arsdigita.cms.ItemSelectionModel; import com.arsdigita.cms.PageLocations; import com.arsdigita.web.ParameterMap; import com.arsdigita.web.URL; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - import java.util.List; /** diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java similarity index 99% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java index 4fa2d0d52..5755de924 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java.todo +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java @@ -41,12 +41,12 @@ import com.arsdigita.bebop.parameters.StringParameter; import com.arsdigita.cms.CMS; import com.arsdigita.cms.ItemSelectionModel; import com.arsdigita.cms.PageLocations; -import com.arsdigita.cms.ui.item.CustomizedPreviewLink; import com.arsdigita.cms.dispatcher.CMSDispatcher; import com.arsdigita.cms.dispatcher.CMSPage; import com.arsdigita.cms.dispatcher.ItemResolver; import com.arsdigita.cms.ui.authoring.WizardSelector; import com.arsdigita.cms.ui.item.ContentItemRequestLocal; +import com.arsdigita.cms.ui.item.CustomizedPreviewLink; import com.arsdigita.cms.ui.item.ItemLanguages; import com.arsdigita.cms.ui.item.Summary; import com.arsdigita.cms.ui.lifecycle.ItemLifecycleAdminPane; @@ -60,9 +60,7 @@ import com.arsdigita.util.Assert; import com.arsdigita.util.UncheckedWrapperException; import com.arsdigita.xml.Document; import com.arsdigita.xml.Element; -import java.io.IOException; -import java.util.Optional; -import javax.servlet.http.HttpServletRequest; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.arsdigita.cms.CMSConfig; @@ -74,6 +72,11 @@ import org.librecms.contentsection.ContentItemVersion; import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentType; +import java.io.IOException; +import java.util.Optional; + +import javax.servlet.http.HttpServletRequest; + /** * Page for administering a content item. * diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionContextBar.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionContextBar.java similarity index 100% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionContextBar.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionContextBar.java diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionPage.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionPage.java similarity index 96% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionPage.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionPage.java index 03da35fcb..380ca212c 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionPage.java.todo +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionPage.java @@ -39,7 +39,7 @@ import com.arsdigita.cms.dispatcher.CMSPage; //ToDo NG import com.arsdigita.cms.ui.cse.ContentSoonExpiredPane; import com.arsdigita.cms.ui.folder.FolderAdminPane; import com.arsdigita.cms.ui.lifecycle.LifecycleAdminPane; -import com.arsdigita.cms.ui.role.RoleAdminPane; +//import com.arsdigita.cms.ui.role.RoleAdminPane; import com.arsdigita.cms.ui.type.ContentTypeAdminPane; import com.arsdigita.cms.ui.workflow.WorkflowAdminPane; import com.arsdigita.globalization.GlobalizedMessage; @@ -130,7 +130,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener { //ToDo NG private BrowsePane m_browsePane; //ToDo NG private ItemSearch m_searchPane; //ToDo NG private ImagesPane m_imagesPane; - private RoleAdminPane m_rolePane; +//ToDo NG private RoleAdminPane m_rolePane; private WorkflowAdminPane m_workflowPane; private LifecycleAdminPane m_lifecyclePane; //ToDo NG private CategoryAdminPane m_categoryPane; @@ -157,7 +157,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener { //ToDo NG m_browsePane = getBrowsePane(); //ToDo NG m_searchPane = getSearchPane(); //ToDo NG m_imagesPane = getImagesPane(); - m_rolePane = getRoleAdminPane(); +//ToDo NG m_rolePane = getRoleAdminPane(); m_workflowPane = getWorkflowAdminPane(); m_lifecyclePane = getLifecycleAdminPane(); //ToDo NG m_categoryPane = getCategoryAdminPane(); @@ -211,11 +211,12 @@ public class ContentSectionPage extends CMSPage implements ActionListener { m_typePane, permissionChecker.isPermitted( AdminPrivileges.ADMINISTER_CONTENT_TYPES)); - m_tabbedPane.setTabVisible( - state, - m_rolePane, - permissionChecker.isPermitted( - AdminPrivileges.ADMINISTER_ROLES)); +//ToDo NG +//m_tabbedPane.setTabVisible( +// state, +// m_rolePane, +// permissionChecker.isPermitted( +// AdminPrivileges.ADMINISTER_ROLES)); // csePane: should check permission m_tabbedPane.setTabVisible(state, m_csePane, true); // TODO Check for reportPane as well @@ -275,12 +276,13 @@ public class ContentSectionPage extends CMSPage implements ActionListener { // return m_imagesPane; // } - protected RoleAdminPane getRoleAdminPane() { - if (m_rolePane == null) { - m_rolePane = new RoleAdminPane(); - } - return m_rolePane; - } +// ToDo NG +// protected RoleAdminPane getRoleAdminPane() { +// if (m_rolePane == null) { +// m_rolePane = new RoleAdminPane(); +// } +// return m_rolePane; +// } /** * Creates, and then caches, the workflow administration pane. Overriding @@ -400,7 +402,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener { // ToDo NG tab(pane, "cms.ui.browse", getBrowsePane()); // ToDo NG tab(pane, "cms.ui.search", getSearchPane()); // ToDo NG tab(pane, "cms.ui.images", getImagesPane()); - tab(pane, "cms.ui.roles", getRoleAdminPane()); +// ToDo NG tab(pane, "cms.ui.roles", getRoleAdminPane()); tab(pane, "cms.ui.workflows", getWorkflowAdminPane()); tab(pane, "cms.ui.lifecycles", getLifecycleAdminPane()); // ToDo NG tab(pane, "cms.ui.categories", getCategoryAdminPane()); @@ -448,8 +450,8 @@ public class ContentSectionPage extends CMSPage implements ActionListener { m_folderPane.reset(state); //ToDo NG } else if (pane == m_browsePane) { // m_browsePane.reset(state); - } else if (pane == m_rolePane) { - m_rolePane.reset(state); +// } else if (pane == m_rolePane) { +// m_rolePane.reset(state); } else if (pane == m_workflowPane) { m_workflowPane.reset(state); } else if (pane == m_lifecyclePane) { diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitWizard.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitWizard.java similarity index 100% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitWizard.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitWizard.java diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/WizardSelector.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/WizardSelector.java similarity index 100% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/WizardSelector.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/WizardSelector.java diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/CustomizedPreviewLink.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/CustomizedPreviewLink.java similarity index 100% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/item/CustomizedPreviewLink.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/item/CustomizedPreviewLink.java diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguages.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguages.java similarity index 100% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguages.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguages.java diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguagesTable.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguagesTable.java similarity index 100% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguagesTable.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguagesTable.java diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguagesTableModel.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguagesTableModel.java similarity index 100% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguagesTableModel.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguagesTableModel.java diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguagesTableModelBuilder.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguagesTableModelBuilder.java similarity index 100% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguagesTableModelBuilder.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguagesTableModelBuilder.java diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleAdminPane.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleAdminPane.java similarity index 100% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleAdminPane.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleAdminPane.java diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleItemPane.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleItemPane.java similarity index 59% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleItemPane.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleItemPane.java index d138ecda6..f2d4a96d1 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleItemPane.java.todo +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleItemPane.java @@ -39,13 +39,11 @@ import com.arsdigita.bebop.event.PrintListener; 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.ContentCenter; -import com.arsdigita.cms.dispatcher.Utilities; import com.arsdigita.cms.ui.BaseItemPane; import com.arsdigita.cms.ui.ContentItemPage; import com.arsdigita.cms.ui.item.ContentItemRequestLocal; import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.mail.Mail; import com.arsdigita.toolbox.ui.ActionGroup; import com.arsdigita.toolbox.ui.Property; import com.arsdigita.toolbox.ui.PropertyList; @@ -53,7 +51,6 @@ 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.xml.Element; import org.apache.logging.log4j.LogManager; @@ -61,18 +58,15 @@ import org.apache.logging.log4j.Logger; import org.arsdigita.cms.CMSConfig; import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.l10n.GlobalizationHelper; -import org.libreccm.notification.Notification; -import org.libreccm.security.Party; import org.libreccm.security.PermissionChecker; +import org.libreccm.security.Shiro; import org.libreccm.security.User; -import org.libreccm.workflow.Workflow; +import org.libreccm.security.UserRepository; import org.libreccm.workflow.WorkflowManager; import org.librecms.CmsConstants; import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItemManager; import org.librecms.contentsection.ContentItemRepository; -import org.librecms.contentsection.ContentSection; -import org.librecms.contentsection.ContentSectionConfig; import org.librecms.contentsection.privileges.ItemPrivileges; import org.librecms.lifecycle.Lifecycle; @@ -85,6 +79,8 @@ import java.util.List; import java.util.Locale; import java.util.Optional; +import javax.mail.MessagingException; + /** * This class contains the component which displays the information for a * particular lifecycle, with the ability to edit and delete. This information @@ -304,7 +300,7 @@ class ItemLifecycleItemPane extends BaseItemPane { WorkflowManager.class); itemManager.publish(item); - + workflowManager.finish(item.getWorkflow()); } @@ -322,10 +318,13 @@ class ItemLifecycleItemPane extends BaseItemPane { public final void actionPerformed(final ActionEvent event) { final PageState state = event.getPageState(); final ContentItem item = selectedItem.getContentItem(state); - final User user = Web.getWebContext().getUser(); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final Shiro shiro = cdiUtil.findBean(Shiro.class); + final User user = shiro.getUser(); /* - * jensp 2011-12-14: Check is threaded publishing is active. If yes, execute publishing in a thread. + * jensp 2011-12-14: Check is threaded publishing is active. + * If yes, execute publishing in a thread. */ if (CMSConfig.getConfig().isThreadPublishing()) { final Republisher republisher = new Republisher(item, user); @@ -341,46 +340,30 @@ class ItemLifecycleItemPane extends BaseItemPane { = new PrintWriter(strWriter); ex.printStackTrace(writer); - PublishLock.getInstance().setError(item, strWriter - .toString()); +// PublishLock.getInstance().setError(item, strWriter +// .toString()); LOGGER.error(String.format( "An error occurred while " + "publishing the item '%s': ", - item.getOID().toString()), - ex); + item.getUuid()), ex); - if ((CMSConfig.getInstanceOf(). - getPublicationFailureSender() + if ((CMSConfig.getConfig() + .getPublishingFailureSender() == null) - && (CMSConfig.getInstanceOf(). - getPublicationFailureReceiver() + && (CMSConfig.getConfig() + .getPublishingFailureReceiver() == null)) { return; } - final PartyCollection receiverParties = Party - .retrieveAllParties(); - Party receiver = null; - receiverParties.addEqualsFilter("primaryEmail", - CMSConfig - .getInstanceOf() - .getPublicationFailureReceiver()); - if (receiverParties.next()) { - receiver = receiverParties.getParty(); - } - receiverParties.close(); - - final PartyCollection senderParties = Party - .retrieveAllParties(); - Party sender = null; - senderParties.addEqualsFilter("primaryEmail", - CMSConfig - .getInstanceOf(). - getPublicationFailureReceiver()); - if (senderParties.next()) { - sender = senderParties.getParty(); - } - senderParties.close(); + final UserRepository userRepo = cdiUtil.findBean( + UserRepository.class); + final User receiver = userRepo.findByEmailAddress( + CMSConfig.getConfig() + .getPublishingFailureReceiver()); + final User sender = userRepo.findByEmailAddress( + CMSConfig.getConfig() + .getPublishingFailureSender()); if ((sender != null) && (receiver != null)) { final Writer traceWriter = new StringWriter(); @@ -388,21 +371,25 @@ class ItemLifecycleItemPane extends BaseItemPane { traceWriter); ex.printStackTrace(printWriter); - final Notification notification - = new Notification( - sender, - receiver, - String.format( - "Failed to publish item '%s'", - item.getOID().toString()), - String.format( - "Publishing item '%s' failed " - + "with error message: %s.\n\n" - + "Stacktrace:\n%s", - item.getOID().toString(), - ex.getMessage(), - traceWriter.toString())); - notification.save(); + final Mail notification = new Mail( + receiver.getPrimaryEmailAddress() + .getAddress(), + sender.getPrimaryEmailAddress().getAddress(), + String.format( + "Failed to publish item '%s'", + item.getUuid())); + notification.setBody(String.format( + "Publishing item '%s' failed " + + "with error message: %s.\n\n" + + "Stacktrace:\n%s", + item.getUuid(), + ex.getMessage(), + traceWriter.toString())); + try { + notification.send(); + } catch (MessagingException msgex) { + throw new UncheckedWrapperException(msgex); + } } } @@ -420,10 +407,11 @@ class ItemLifecycleItemPane extends BaseItemPane { */ } else { republish(item, false, user); - if (ContentSection.getConfig().getUseStreamlinedCreation()) { + if (CMSConfig.getConfig().isUseStreamlinedCreation()) { throw new RedirectSignal( URL.there(state.getRequest(), - ContentCenter.getURL()), true); + CmsConstants.CONTENT_CENTER_URL), + true); } } } @@ -435,29 +423,24 @@ class ItemLifecycleItemPane extends BaseItemPane { */ 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 final String itemUuid; private final User user; private Republisher(final ContentItem item, User user) { - itemOid = item.getOID().toString(); + itemUuid = item.getUuid(); this.user = user; } @Override public void run() { - final ContentItem item = (ContentItem) DomainObjectFactory - .newInstance(OID.valueOf( - itemOid)); - PublishLock.getInstance().lock(item); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final ContentItemRepository itemRepo = cdiUtil.findBean( + ContentItemRepository.class); + final ContentItem item = itemRepo.findByUuid(itemUuid).get(); + +// PublishLock.getInstance().lock(item); republish(item, false, user); - PublishLock.getInstance().unlock(item); +// PublishLock.getInstance().unlock(item); } } @@ -482,13 +465,15 @@ class ItemLifecycleItemPane extends BaseItemPane { public final void actionPerformed(final ActionEvent e) { final PageState state = e.getPageState(); final ContentItem item = selectedItem.getContentItem(state); - final User user = Web.getWebContext().getUser(); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final Shiro shiro = cdiUtil.findBean(Shiro.class); + final User user = shiro.getUser(); /** * jensp 2011-12-14: Execute is a thread if threaded publishing * is active. */ - if (CMSConfig.getInstanceOf().getThreadedPublishing()) { + if (CMSConfig.getConfig().isThreadPublishing()) { final Republisher republisher = new Republisher(item, user); final Thread thread = new Thread(republisher); thread.setUncaughtExceptionHandler( @@ -502,46 +487,29 @@ class ItemLifecycleItemPane extends BaseItemPane { = new PrintWriter(strWriter); ex.printStackTrace(writer); - PublishLock.getInstance().setError(item, strWriter - .toString()); +// PublishLock.getInstance().setError(item, strWriter +// .toString()); LOGGER.error(String.format( "An error occurred while " + "publishing the item '%s': ", - item.getOID().toString()), - ex); + item.getUuid()), ex); - if ((CMSConfig.getInstanceOf(). - getPublicationFailureSender() - == null) - && (CMSConfig.getInstanceOf(). - getPublicationFailureReceiver() + if ((CMSConfig.getConfig(). + getPublishingFailureSender() == null) + && (CMSConfig.getConfig(). + getPublishingFailureReceiver() == null)) { return; } - final PartyCollection receiverParties = Party - .retrieveAllParties(); - Party receiver = null; - receiverParties.addEqualsFilter("primaryEmail", - CMSConfig - .getInstanceOf() - .getPublicationFailureReceiver()); - if (receiverParties.next()) { - receiver = receiverParties.getParty(); - } - receiverParties.close(); - - final PartyCollection senderParties = Party - .retrieveAllParties(); - Party sender = null; - senderParties.addEqualsFilter("primaryEmail", - CMSConfig - .getInstanceOf(). - getPublicationFailureReceiver()); - if (senderParties.next()) { - sender = senderParties.getParty(); - } - senderParties.close(); + final UserRepository userRepo = cdiUtil.findBean( + UserRepository.class); + final User receiver = userRepo.findByEmailAddress( + CMSConfig.getConfig() + .getPublishingFailureReceiver()); + final User sender = userRepo.findByEmailAddress( + CMSConfig.getConfig() + .getPublishingFailureSender()); if ((sender != null) && (receiver != null)) { final Writer traceWriter = new StringWriter(); @@ -549,21 +517,25 @@ class ItemLifecycleItemPane extends BaseItemPane { traceWriter); ex.printStackTrace(printWriter); - final Notification notification - = new Notification( - sender, - receiver, - String.format( - "Failed to publish item '%s'", - item.getOID().toString()), - String.format( - "Publishing item '%s' failed " - + "with error message: %s.\n\n" - + "Stacktrace:\n%s", - item.getOID().toString(), - ex.getMessage(), - traceWriter.toString())); - notification.save(); + final Mail notification = new Mail( + receiver.getPrimaryEmailAddress() + .getAddress(), + sender.getPrimaryEmailAddress().getAddress(), + String.format( + "Failed to publish item '%s'", + item.getUuid())); + notification.setBody(String.format( + "Publishing item '%s' failed " + + "with error message: %s.\n\n" + + "Stacktrace:\n%s", + item.getUuid(), + ex.getMessage(), + traceWriter.toString())); + try { + notification.send(); + } catch (MessagingException msgex) { + throw new UncheckedWrapperException(msgex); + } } } @@ -581,10 +553,11 @@ class ItemLifecycleItemPane extends BaseItemPane { * jensp 2011-12-14 end */ republish(item, true, user); - if (ContentSection.getConfig().getUseStreamlinedCreation()) { + if (CMSConfig.getConfig().isUseStreamlinedCreation()) { throw new RedirectSignal( URL.there(state.getRequest(), - ContentCenter.getURL()), true); + CmsConstants.CONTENT_CENTER_URL), + true); } } } @@ -596,29 +569,23 @@ class ItemLifecycleItemPane extends BaseItemPane { */ 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 final String itemUuid; private final User user; private Republisher(final ContentItem item, User user) { - itemOid = item.getOID().toString(); + itemUuid = item.getUuid(); this.user = user; } @Override public void run() { - final ContentItem item = (ContentItem) DomainObjectFactory - .newInstance(OID.valueOf( - itemOid)); - PublishLock.getInstance().lock(item); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final ContentItemRepository itemRepo = cdiUtil.findBean( + ContentItemRepository.class); + final ContentItem item = itemRepo.findByUuid(itemUuid).get(); +// PublishLock.getInstance().lock(item); republish(item, true, user); - PublishLock.getInstance().unlock(item); +// PublishLock.getInstance().unlock(item); } } @@ -678,18 +645,17 @@ class ItemLifecycleItemPane extends BaseItemPane { 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( + REPUBLISH, + new Label(gz("cms.ui.item.lifecycle.republish")))); + if (!CMSConfig.getConfig().isHideResetLifecycleLink()) { + actionSelect.addOption(new Option( + REPUBLISH_AND_RESET, + new Label(gz("cms.ui.item.lifecycle.republish_and_reset")))); } - actionSelect.addOption(new Option(UNPUBLISH, (String) gz( - "cms.ui.item.lifecycle.unpublish") - .localize())); + actionSelect.addOption(new Option( + UNPUBLISH, + new Label(gz("cms.ui.item.lifecycle.unpublish")))); submit = new Submit(gz("cms.ui.item.lifecycle.do")); notAuthorized = new Label(gz( @@ -705,15 +671,17 @@ class ItemLifecycleItemPane extends BaseItemPane { } @Override - public void init(FormSectionEvent fse) throws FormProcessException { - final PageState state = fse.getPageState(); + public void init(final FormSectionEvent event) + throws FormProcessException { + + final PageState state = event.getPageState(); final ContentItem item = selectedItem.getContentItem(state); - final SecurityManager sm = Utilities.getSecurityManager(state); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final PermissionChecker permissionChecker = cdiUtil.findBean( + PermissionChecker.class); - if (sm.canAccess(state.getRequest(), - SecurityManager.PUBLISH, - item)) { + if (permissionChecker.isPermitted(ItemPrivileges.PUBLISH, item)) { submit.setVisible(state, true); notAuthorized.setVisible(state, false); } else { @@ -723,11 +691,14 @@ class ItemLifecycleItemPane extends BaseItemPane { } @Override - public void process(final FormSectionEvent fse) throws - FormProcessException { - final PageState state = fse.getPageState(); - final FormData data = fse.getFormData(); - final User user = Web.getWebContext().getUser(); + public void process(final FormSectionEvent event) + throws FormProcessException { + + final PageState state = event.getPageState(); + final FormData data = event.getFormData(); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final Shiro shiro = cdiUtil.findBean(Shiro.class); + final User user = shiro.getUser(); String selected = (String) data.get(LIFECYCLE_ACTION); final ContentItem item = selectedItem.getContentItem(state); @@ -737,7 +708,7 @@ class ItemLifecycleItemPane extends BaseItemPane { * threaded publishing is active. */ if (REPUBLISH.equals(selected)) { - if (CMSConfig.getInstanceOf().getThreadedPublishing()) { + if (CMSConfig.getConfig().isThreadPublishing()) { final RepublishRunner runner = new RepublishRunner(item, user); final Thread thread = new Thread(runner); @@ -752,46 +723,30 @@ class ItemLifecycleItemPane extends BaseItemPane { = new PrintWriter(strWriter); ex.printStackTrace(writer); - PublishLock.getInstance().setError(item, strWriter - .toString()); +// PublishLock.getInstance().setError(item, strWriter +// .toString()); LOGGER.error(String.format( "An error occurred while " + "publishing the item '%s': ", - item.getOID().toString()), - ex); + item.getUuid()), ex); - if ((CMSConfig.getInstanceOf(). - getPublicationFailureSender() + if ((CMSConfig.getConfig() + .getPublishingFailureSender() == null) - && (CMSConfig.getInstanceOf(). - getPublicationFailureReceiver() + && (CMSConfig.getConfig() + .getPublishingFailureReceiver() == null)) { return; } - final PartyCollection receiverParties = Party - .retrieveAllParties(); - Party receiver = null; - receiverParties.addEqualsFilter("primaryEmail", - CMSConfig - .getInstanceOf() - .getPublicationFailureReceiver()); - if (receiverParties.next()) { - receiver = receiverParties.getParty(); - } - receiverParties.close(); - - final PartyCollection senderParties = Party - .retrieveAllParties(); - Party sender = null; - senderParties.addEqualsFilter("primaryEmail", - CMSConfig - .getInstanceOf(). - getPublicationFailureReceiver()); - if (senderParties.next()) { - sender = senderParties.getParty(); - } - senderParties.close(); + final UserRepository userRepo = cdiUtil.findBean( + UserRepository.class); + final User receiver = userRepo.findByEmailAddress( + CMSConfig.getConfig() + .getPublishingFailureReceiver()); + final User sender = userRepo.findByEmailAddress( + CMSConfig.getConfig() + .getPublishingFailureSender()); if ((sender != null) && (receiver != null)) { final Writer traceWriter = new StringWriter(); @@ -799,21 +754,25 @@ class ItemLifecycleItemPane extends BaseItemPane { traceWriter); ex.printStackTrace(printWriter); - final Notification notification - = new Notification( - sender, - receiver, - String.format( - "Failed to publish item '%s'", - item.getOID().toString()), - String.format( - "Publishing item '%s' failed " - + "with error message: %s.\n\n" - + "Stacktrace:\n%s", - item.getOID().toString(), - ex.getMessage(), - traceWriter.toString())); - notification.save(); + final Mail notification = new Mail( + receiver.getPrimaryEmailAddress() + .getAddress(), + sender.getPrimaryEmailAddress().getAddress(), + String.format( + "Failed to publish item '%s'", + item.getUuid())); + notification.setBody(String.format( + "Publishing item '%s' failed " + + "with error message: %s.\n\n" + + "Stacktrace:\n%s", + item.getUuid(), + ex.getMessage(), + traceWriter.toString())); + try { + notification.send(); + } catch (MessagingException msgex) { + throw new UncheckedWrapperException(msgex); + } } } @@ -829,14 +788,14 @@ class ItemLifecycleItemPane extends BaseItemPane { } else { republish(item, false, user); - if (ContentSection.getConfig().getUseStreamlinedCreation()) { + if (CMSConfig.getConfig().isUseStreamlinedCreation()) { throw new RedirectSignal( URL.there(state.getRequest(), - ContentCenter.getURL()), true); + CmsConstants.CONTENT_CENTER_URL), true); } } } else if (REPUBLISH_AND_RESET.equals(selected)) { - if (CMSConfig.getInstanceOf().getThreadedPublishing()) { + if (CMSConfig.getConfig().isThreadPublishing()) { final RepublishAndResetRunner runner = new RepublishAndResetRunner( item, user); @@ -852,46 +811,30 @@ class ItemLifecycleItemPane extends BaseItemPane { = new PrintWriter(strWriter); ex.printStackTrace(writer); - PublishLock.getInstance().setError(item, strWriter - .toString()); +// PublishLock.getInstance().setError(item, strWriter +// .toString()); LOGGER.error(String.format( "An error occurred while " + "publishing the item '%s': ", - item.getOID().toString()), - ex); + item.getUuid()), ex); - if ((CMSConfig.getInstanceOf(). - getPublicationFailureSender() + if ((CMSConfig.getConfig() + .getPublishingFailureSender() == null) - && (CMSConfig.getInstanceOf(). - getPublicationFailureReceiver() + && (CMSConfig.getConfig() + .getPublishingFailureReceiver() == null)) { return; } - final PartyCollection receiverParties = Party - .retrieveAllParties(); - Party receiver = null; - receiverParties.addEqualsFilter("primaryEmail", - CMSConfig - .getInstanceOf() - .getPublicationFailureReceiver()); - if (receiverParties.next()) { - receiver = receiverParties.getParty(); - } - receiverParties.close(); - - final PartyCollection senderParties = Party - .retrieveAllParties(); - Party sender = null; - senderParties.addEqualsFilter("primaryEmail", - CMSConfig - .getInstanceOf(). - getPublicationFailureReceiver()); - if (senderParties.next()) { - sender = senderParties.getParty(); - } - senderParties.close(); + final UserRepository userRepo = cdiUtil.findBean( + UserRepository.class); + final User receiver = userRepo.findByEmailAddress( + CMSConfig.getConfig() + .getPublishingFailureReceiver()); + final User sender = userRepo.findByEmailAddress( + CMSConfig.getConfig() + .getPublishingFailureSender()); if ((sender != null) && (receiver != null)) { final Writer traceWriter = new StringWriter(); @@ -899,21 +842,25 @@ class ItemLifecycleItemPane extends BaseItemPane { traceWriter); ex.printStackTrace(printWriter); - final Notification notification - = new Notification( - sender, - receiver, - String.format( - "Failed to publish item '%s'", - item.getOID().toString()), - String.format( - "Publishing item '%s' failed " - + "with error message: %s.\n\n" - + "Stacktrace:\n%s", - item.getOID().toString(), - ex.getMessage(), - traceWriter.toString())); - notification.save(); + final Mail notification = new Mail( + receiver.getPrimaryEmailAddress() + .getAddress(), + sender.getPrimaryEmailAddress().getAddress(), + String.format( + "Failed to publish item '%s'", + item.getUuid())); + notification.setBody(String.format( + "Publishing item '%s' failed " + + "with error message: %s.\n\n" + + "Stacktrace:\n%s", + item.getUuid(), + ex.getMessage(), + traceWriter.toString())); + try { + notification.send(); + } catch (MessagingException msgex) { + throw new UncheckedWrapperException(msgex); + } } } @@ -929,14 +876,16 @@ class ItemLifecycleItemPane extends BaseItemPane { } else { republish(item, true, user); - if (ContentSection.getConfig().getUseStreamlinedCreation()) { + if (CMSConfig.getConfig().isUseStreamlinedCreation()) { throw new RedirectSignal( URL.there(state.getRequest(), - ContentCenter.getURL()), true); + CmsConstants.CONTENT_CENTER_URL), true); } } } else if (UNPUBLISH.equals(selected)) { - item.unpublish(); + final ContentItemManager itemManager = cdiUtil.findBean( + ContentItemManager.class); + itemManager.unpublish(item); } else { throw new IllegalArgumentException("Illegal selection"); } @@ -944,72 +893,60 @@ class ItemLifecycleItemPane extends BaseItemPane { 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 final String itemUuid; private final User user; - private RepublishRunner(final ContentItem item, User user) { - itemOid = item.getOID().toString(); + private RepublishRunner(final ContentItem item, + final User user) { + itemUuid = item.getUuid(); this.user = user; } private void doRepublish() { - final ContentItem item = (ContentItem) DomainObjectFactory - .newInstance(OID.valueOf( - itemOid)); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final ContentItemRepository itemRepo = cdiUtil.findBean( + ContentItemRepository.class); + final ContentItem item = itemRepo.findByUuid(itemUuid).get(); republish(item, false, user); } @Override public void run() { - final ContentItem item = (ContentItem) DomainObjectFactory - .newInstance(OID.valueOf( - itemOid)); - PublishLock.getInstance().lock(item); +// PublishLock.getInstance().lock(item); doRepublish(); - PublishLock.getInstance().unlock(item); +// 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 final String itemUuid; private final User user; - private RepublishAndResetRunner(final ContentItem item, User user) { - itemOid = item.getOID().toString(); + private RepublishAndResetRunner(final ContentItem item, + final User user) { + itemUuid = item.getUuid(); this.user = user; } private void doRepublishAndReset() { - final ContentItem item = (ContentItem) DomainObjectFactory - .newInstance(OID.valueOf( - itemOid)); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final ContentItemRepository itemRepo = cdiUtil.findBean( + ContentItemRepository.class); + final ContentItem item = itemRepo.findByUuid(itemUuid).get(); republish(item, true, user); } @Override public void run() { - final ContentItem item = (ContentItem) DomainObjectFactory - .newInstance(OID.valueOf( - itemOid)); - PublishLock.getInstance().lock(item); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final ContentItemRepository itemRepo = cdiUtil.findBean( + ContentItemRepository.class); + final ContentItem item = itemRepo.findByUuid(itemUuid).get(); +// PublishLock.getInstance().lock(item); doRepublishAndReset(); - PublishLock.getInstance().unlock(item); +// PublishLock.getInstance().unlock(item); } } diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleSelectForm.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleSelectForm.java new file mode 100755 index 000000000..f700179fe --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleSelectForm.java @@ -0,0 +1,1058 @@ +/* + * 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.BoxPanel; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.Text; +import com.arsdigita.bebop.event.FormInitListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.FormValidationListener; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.form.Date; +import com.arsdigita.bebop.form.Option; +import com.arsdigita.bebop.form.SingleSelect; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.bebop.parameters.DateParameter; +import com.arsdigita.bebop.parameters.IntegerParameter; +import com.arsdigita.bebop.parameters.NumberInRangeValidationListener; +import com.arsdigita.cms.CMS; +import com.arsdigita.cms.ContentCenter; +import com.arsdigita.cms.ui.BaseForm; +import com.arsdigita.cms.ui.ContentItemPage; +import com.arsdigita.cms.ui.item.ContentItemRequestLocal; +import com.arsdigita.cms.ui.item.ItemWorkflowRequestLocal; +import com.arsdigita.cms.ui.workflow.WorkflowRequestLocal; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.mail.Mail; +import com.arsdigita.util.UncheckedWrapperException; +import com.arsdigita.web.RedirectSignal; +import com.arsdigita.web.URL; +import com.arsdigita.web.Web; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.arsdigita.cms.CMSConfig; +import org.libreccm.cdi.utils.CdiUtil; +import org.libreccm.l10n.GlobalizationHelper; +import org.libreccm.notification.Notification; +import org.libreccm.security.Party; +import org.libreccm.security.Shiro; +import org.libreccm.security.User; +import org.libreccm.security.UserRepository; +import org.libreccm.workflow.Task; +import org.libreccm.workflow.TaskManager; +import org.libreccm.workflow.Workflow; +import org.libreccm.workflow.WorkflowManager; +import org.libreccm.workflow.WorkflowRepository; +import org.libreccm.workflow.WorkflowTemplate; +import org.librecms.CmsConstants; +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentItemManager; +import org.librecms.contentsection.ContentItemRepository; +import org.librecms.contentsection.ContentSection; +import org.librecms.contentsection.ContentSectionConfig; +import org.librecms.contentsection.privileges.ItemPrivileges; +import org.librecms.lifecycle.Lifecycle; +import org.librecms.lifecycle.LifecycleDefinition; +import org.librecms.lifecycle.LifecycleDefinitionRepository; +import org.librecms.lifecycle.LifecycleManager; +import org.librecms.lifecycle.LifecycleRepository; +import org.librecms.lifecycle.Phase; +import org.librecms.lifecycle.PhaseDefinition; +import org.librecms.lifecycle.PhaseRepository; +import org.librecms.workflow.CmsTask; +import org.librecms.workflow.CmsTaskManager; +import org.librecms.workflow.CmsTaskType; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Calendar; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.TimeZone; +import java.util.TooManyListenersException; + +import javax.mail.MessagingException; +import javax.servlet.http.HttpServletRequest; + +/** + *

+ * A form to select and apply a lifecycle to a content item.

+ * + * @author Michael Pih + * @author Xixi D'moon <xdmoon@redhat.com> + * @author Justin Ross <jross@redhat.com> + * @author Jens Pelzetter + */ +class ItemLifecycleSelectForm extends BaseForm { + + private static final Logger LOGGER = LogManager.getLogger( + ItemLifecycleSelectForm.class); + + private final static String LIFECYCLE = "lifecycle"; + private final static String START_DATE = "start_date"; + private final static String END_DATE = "end_date"; + private final static String NOTIFICATION_DAYS = "notifyDays"; + private final static String NOTIFICATION_HOURS = "notifyHours"; + + private final ContentItemRequestLocal itemRequestLocal; + private final WorkflowRequestLocal workflowRequestLocal; + + // Form widgets + private final SingleSelect cycleSelect; + private final Date startDateField; + private final TextField startHourField; + private final TextField startMinuteField; + private final SingleSelect startAmpmSelect; + private final Date endDateField; + private final TextField endHourField; + private final TextField endMinuteField; + private final SingleSelect endAmpmSelect; + private final TextField notificationDaysField; + private final TextField notificationHoursField; + + public ItemLifecycleSelectForm(final ContentItemRequestLocal item) { + super("PublishItem", gz("cms.ui.item.lifecycle.apply")); + + this.itemRequestLocal = item; + workflowRequestLocal = new ItemWorkflowRequestLocal(); + + cycleSelect = new SingleSelect(new BigDecimalParameter(LIFECYCLE)); + try { + cycleSelect.addPrintListener(new OptionPrinter()); + } catch (TooManyListenersException tmle) { + throw new UncheckedWrapperException(tmle); + } + addField(gz("cms.ui.item.lifecycle"), cycleSelect); + + // Start date + startDateField = new Date(new DateParameter(START_DATE) { + + @Override + protected final Calendar getCalendar(final HttpServletRequest sreq) { + final Calendar cal = super.getCalendar(sreq); + + cal.setLenient(false); + + return cal; + } + + }); + addField(gz("cms.ui.item.lifecycle.start_date"), startDateField); + + // Start time + final BoxPanel startTime = new BoxPanel(BoxPanel.HORIZONTAL); + addField(gz("cms.ui.item.lifecycle.start_time"), startTime); + + // Hour + startHourField = new TextField(new IntegerParameter("start_hour")); + startTime.add(startHourField); + + startHourField.setSize(3); + startHourField.addValidationListener( + new NumberInRangeValidationListener(1, 12)); + + // Minute + startMinuteField = new TextField(new IntegerParameter("start_minute")); + startTime.add(startMinuteField); + + startMinuteField.setSize(3); + startMinuteField.addValidationListener( + new NumberInRangeValidationListener( + 0, 59)); + + // AM/PM + startAmpmSelect = new SingleSelect(new IntegerParameter("start_ampm")); + startTime.add(startAmpmSelect); + + startAmpmSelect.addOption(new Option("0", "am")); + startAmpmSelect.addOption(new Option("1", "pm")); + + // Time zone + startTime.add(new Label(new TimeZonePrinter())); + + // Expiration date + endDateField = new Date(new DateParameter(END_DATE) { + + @Override + protected final Calendar getCalendar(final HttpServletRequest sreq) { + final Calendar cal = super.getCalendar(sreq); + + cal.setLenient(false); + + return cal; + } + + }); + addField(gz("cms.ui.item.lifecycle.end_date"), endDateField); + + // End time + final BoxPanel endTime = new BoxPanel(BoxPanel.HORIZONTAL); + addField(gz("cms.ui.item.lifecycle.end_time"), endTime); + + // Hour + endHourField = new TextField(new IntegerParameter("end_hour")); + endTime.add(endHourField); + + endHourField.setSize(3); + endHourField.addValidationListener( + new NumberInRangeValidationListener(1, + 12)); + + // Minute + endMinuteField = new TextField(new IntegerParameter("end_minute")); + endTime.add(endMinuteField); + + endMinuteField.setSize(3); + endMinuteField.addValidationListener( + new NumberInRangeValidationListener(0, 59)); + + // AM/PM + endAmpmSelect = new SingleSelect(new IntegerParameter("end_ampm")); + endTime.add(endAmpmSelect); + + endAmpmSelect.addOption(new Option("0", "am")); + endAmpmSelect.addOption(new Option("1", "pm")); + + endTime.add(new Label(new TimeZonePrinter())); + + notificationDaysField = new TextField(new IntegerParameter( + NOTIFICATION_DAYS)); + notificationDaysField.setSize(4); + notificationHoursField = new TextField(new IntegerParameter( + NOTIFICATION_HOURS)); + notificationHoursField.setSize(4); + SimpleContainer cont = new SimpleContainer(); + cont.add(notificationDaysField); + cont.add(new Label(new GlobalizedMessage("cms.ui.item.days", + CmsConstants.CMS_BUNDLE), + false)); + cont.add(notificationHoursField); + cont.add(new Label(new GlobalizedMessage("cms.ui.item.hours", + CmsConstants.CMS_BUNDLE), + false)); + + addField(gz("cms.ui.item.notification_period"), cont); + + // A hidden field that checks to see if the user wants publish + // with a start time earlier than current time. + addAction(new Submit("finish", gz("cms.ui.item.lifecycle.publish"))); + + // Form listeners + addValidationListener(new ValidationListener()); + addSecurityListener(ItemPrivileges.PUBLISH, item); + addInitListener(new InitListener()); + addProcessListener(new ProcessListener()); + } + + private class OptionPrinter implements PrintListener { + + @Override + public final void prepare(final PrintEvent e) { + final ContentSection section = CMS.getContext().getContentSection(); + + final List definitions = section + .getLifecycleDefinitions(); + + final SingleSelect target = (SingleSelect) e.getTarget(); + target.clearOptions(); + + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final GlobalizationHelper globalizationHelper = cdiUtil.findBean( + GlobalizationHelper.class); + final Locale locale = globalizationHelper.getNegotiatedLocale(); + + for (final LifecycleDefinition definition : definitions) { + final List phaseDefinitions = definition + .getPhaseDefinitions(); + + if (!phaseDefinitions.isEmpty()) { + target.addOption(new Option( + Long.toString(definition.getDefinitionId()), + new Text(definition.getLabel().getValue(locale)))); + } + } + } + + } + + private class InitListener implements FormInitListener { + + @Override + public final void init(final FormSectionEvent event) { + final PageState state = event.getPageState(); + + final ContentItem item = itemRequestLocal.getContentItem(state); + + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final ContentItemManager itemManager = cdiUtil.findBean( + ContentItemManager.class); + + if (itemManager.isLive(item)) { + // If the item is published, select the currently + // associated lifecycle. + + final LifecycleDefinition definition = item.getLifecycle() + .getDefinition(); + cycleSelect.setValue(state, definition.getDefinitionId()); + } else { + // Set the default lifecycle (if it exists). + + final ContentSection section = CMS.getContext() + .getContentSection(); + final LifecycleDefinition definition = item.getContentType() + .getDefaultLifecycle(); + + if (definition != null) { + cycleSelect.setValue(state, definition.getDefinitionId()); + } + } + + // Set the default start date. + // XXX Isn't just new Date() sufficient? + final java.util.Date start = new java.util.Date(); + startDateField.setValue(state, start); + + final Calendar calendar = Calendar.getInstance(); + calendar.setTime(start); + + // If the hour is 12, then Calendar.get(Calendar.HOUR) + // returns 0 (from the 24 hour time - 12). We want it to + // return 12. + if (calendar.get(Calendar.HOUR) == 0) { + startHourField.setValue(state, 12); + } else { + startHourField.setValue(state, calendar.get(Calendar.HOUR)); + } + + final Integer min = calendar.get(Calendar.MINUTE); + + if (min < 10) { + startMinuteField.setValue(state, "0" + min.toString()); + } else { + startMinuteField.setValue(state, min.toString()); + } + + startAmpmSelect.setValue(state, calendar.get(Calendar.AM_PM)); + + final int defaultIime = CMSConfig.getConfig() + .getDefaultNotificationTime(); + final int defaultTimeDays = defaultIime / 24; + final int defaultTimeHours = defaultIime % 24; + + notificationDaysField.setValue(state, defaultTimeDays); + notificationHoursField.setValue(state, defaultTimeHours); + } + + } + + /** + * jensp 2011-12-14: Some larger changes to the behavior of the process + * listener. The real action has been moved to the + * @link{Publisher} class. If threaded publishing is active, the publish + * process runs in a separate thread (the item is locked before using + * {@link PublishLock}. If threaded publishing is not active, nothing has + * changed. + */ + private class ProcessListener implements FormProcessListener { + + @Override + public final void process(final FormSectionEvent event) + throws FormProcessException { + final PageState state = event.getPageState(); + final ContentItem item = itemRequestLocal.getContentItem(state); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + + final Publisher publisher = new Publisher(state); + if (CMSConfig.getConfig().isThreadPublishing()) { + final Runnable threadAction = new Runnable() { + + @Override + public void run() { +// PublishLock.getInstance().lock(item); + publisher.publish(); +// PublishLock.getInstance().unlock(item); + } + + }; + final Thread thread = new Thread(threadAction); + thread.setUncaughtExceptionHandler( + new Thread.UncaughtExceptionHandler() { + + @Override + public void uncaughtException(final Thread thread, + final Throwable ex) { + final StringWriter strWriter = new StringWriter(); + final PrintWriter writer = new PrintWriter(strWriter); + ex.printStackTrace(writer); + +// PublishLock.getInstance().setError(item, strWriter +// .toString()); + LOGGER.error(String.format( + "An error occurred while " + + "publishing the item '%s': ", + item.getUuid()), ex); + + if ((CMSConfig.getConfig() + .getPublishingFailureSender() == null) + && (CMSConfig.getConfig() + .getPublishingFailureReceiver() + == null)) { + return; + } + + final UserRepository userRepo = cdiUtil.findBean( + UserRepository.class); + final User receiver = userRepo.findByEmailAddress( + CMSConfig.getConfig() + .getPublishingFailureReceiver()); + final User sender = userRepo.findByEmailAddress( + CMSConfig.getConfig() + .getPublishingFailureSender()); + + if ((sender != null) && (receiver != null)) { + final Writer traceWriter = new StringWriter(); + final PrintWriter printWriter = new PrintWriter( + traceWriter); + ex.printStackTrace(printWriter); + + final Mail notification = new Mail( + receiver.getPrimaryEmailAddress() + .getAddress(), + sender.getPrimaryEmailAddress().getAddress(), + String.format( + "Failed to publish item '%s'", + item.getUuid())); + notification.setBody(String.format( + "Publishing item '%s' failed " + + "with error message: %s.\n\n" + + "Stacktrace:\n%s", + item.getUuid(), + ex.getMessage(), + traceWriter.toString())); + try { + notification.send(); + } catch (MessagingException msgex) { + throw new UncheckedWrapperException(msgex); + } + } + } + + }); + thread.start(); + } else { + publisher.publish(); + } + + if (CMSConfig.getConfig().isThreadPublishing()) { + throw new RedirectSignal( + URL.getDispatcherPath() + + ContentItemPage.getItemURL(item, + ContentItemPage.PUBLISHING_TAB), + true); + } else { + if (CMSConfig.getConfig().isUseStreamlinedCreation()) { + throw new RedirectSignal( + URL.there(state.getRequest(), + CmsConstants.CONTENT_CENTER_URL), true); + } + } + + /* + * final Integer startHour = (Integer) m_startHour.getValue(state); + * Integer startMinute = (Integer) m_startMinute.getValue(state); + * + * if (startMinute == null) { startMinute = new Integer(0); } + * + * final Integer startAmpm = (Integer) m_startAmpm.getValue(state); + * + * final Integer endHour = (Integer) m_endHour.getValue(state); + * Integer endMinute = (Integer) m_endMinute.getValue(state); + * + * if (endMinute == null) { endMinute = new Integer(0); } + * + * final Integer endAmpm = (Integer) m_endAmpm.getValue(state); + * + * // Instantiate the instance of the content type. final + * ContentItem item = m_item.getContentItem(state); + * + * final BigDecimal defID = (BigDecimal) + * m_cycleSelect.getValue(state); Assert.exists(defID); final + * LifecycleDefinition cycleDef = new LifecycleDefinition(defID); + * + * java.util.Date startDate = (java.util.Date) + * m_startDate.getValue(state); + * + * final Calendar start = Calendar.getInstanceOf(); + * start.setTime(startDate); start.set(Calendar.AM_PM, + * startAmpm.intValue()); start.set(Calendar.MINUTE, + * startMinute.intValue()); start.set(Calendar.AM_PM, + * startAmpm.intValue()); if (startHour.intValue() != 12) { + * start.set(Calendar.HOUR_OF_DAY, 12 * startAmpm.intValue() + + * startHour.intValue()); start.set(Calendar.HOUR, + * startHour.intValue()); } else { if (startAmpm.intValue() == 0) { + * start.set(Calendar.HOUR_OF_DAY, 0); start.set(Calendar.HOUR, 0); + * } else { start.set(Calendar.HOUR_OF_DAY, 12); + * start.set(Calendar.HOUR, 0); } } startDate = start.getTime(); + * + * java.util.Date endDate = (java.util.Date) + * m_endDate.getValue(state); + * + * if (endDate != null) { final Calendar end = + * Calendar.getInstanceOf(); + * + * end.setTime(endDate); end.set(Calendar.AM_PM, + * endAmpm.intValue()); end.set(Calendar.MINUTE, + * endMinute.intValue()); end.set(Calendar.AM_PM, + * endAmpm.intValue()); + * + * if (endHour.intValue() != 12) { end.set(Calendar.HOUR_OF_DAY, 12 + * * endAmpm.intValue() + endHour.intValue()); + * end.set(Calendar.HOUR, endHour.intValue()); } else { if + * (endAmpm.intValue() == 0) { end.set(Calendar.HOUR_OF_DAY, 0); + * end.set(Calendar.HOUR, 0); } else { end.set(Calendar.HOUR_OF_DAY, + * 12); end.set(Calendar.HOUR, 0); } } endDate = end.getTime(); } + * + * // If the item is already published, remove the current + * lifecycle. // Do not touch the live version. if + * (item.isPublished()) { item.removeLifecycle(item); item.save(); } + * + * // Apply the new lifecycle. ContentItem pending = + * item.publish(cycleDef, startDate); final Lifecycle lifecycle = + * pending.getLifecycle(); + * + * // XXX domlay Whoa. This must be broken for multiphase // + * lifecycles. + * + * if (endDate != null) { + * + * // update individual phases final PhaseCollection phases = + * lifecycle.getPhases(); + * + * while (phases.next()) { final Phase phase = phases.getPhase(); + * java.util.Date thisEnd = phase.getEndDate(); java.util.Date + * thisStart = phase.getStartDate(); if + * (thisStart.compareTo(endDate) > 0) { phase.setStartDate(endDate); + * phase.save(); } + * + * if (thisEnd == null || thisEnd.compareTo(endDate) > 0) { + * phase.setEndDate(endDate); phase.save(); } } } + * + * // endOfCycle may be the original date according to lifecycle + * phase definitions, or endDate if that was before // natural end + * of lifecycle java.util.Date endOfCycle = lifecycle.getEndDate(); + * if (endOfCycle != null) { + * + * // if advance notification is requested (!= 0) // add another + * phase at the start of which the user is notified Integer + * notificationDays = (Integer) m_notificationDays.getValue(state); + * Integer notificationHours = (Integer) + * m_notificationHours.getValue(state); java.util.Date + * notificationDate = null; + * + * int notificationPeriod = 0; if (notificationDays != null) { + * notificationPeriod += notificationDays.intValue() * 24; } if + * (notificationHours != null) { notificationPeriod += + * notificationHours.intValue(); } + * + * if (notificationPeriod > 0) { notificationDate = + * computeNotificationDate(endOfCycle, notificationPeriod); + * s_log.debug("adding custom phase"); Phase expirationImminentPhase + * = lifecycle.addCustomPhase("expirationImminent", new + * Long(notificationDate. getTime()), new + * Long(endOfCycle.getTime())); + * expirationImminentPhase.setListenerClassName( + * "org.librecms.lifecycle.NotifyLifecycleListener"); + * expirationImminentPhase.save(); } } + * + * // Force the lifecycle scheduler to run to avoid any // + * scheduler delay for items that should be published // + * immediately. pending.getLifecycle().start(); + * + * item.save(); + * + * final Workflow workflow = m_workflow.getWorkflow(state); try { + * finish(workflow, item, Web.getWebContext().getUser()); } catch + * (TaskException te) { throw new FormProcessException(te); } // + * redirect to /content-center if streamlined creation mode is + * active. if + * (ContentSection.getConfig().getUseStreamlinedCreation()) { throw + * new RedirectSignal(URL.there(state.getRequest(), + * Utilities.getWorkspaceURL()), true); } + */ + } + + } + + /** + * This class contains the real publish action. + */ + private class Publisher { + + private final Integer startHour; + private final Integer startMinute; + private final Integer startAmpm; + private final Integer endHour; + private final Integer endMinute; + private final Integer endAmpm; + private final String itemUuid; + private final Long defID; + private final java.util.Date startDate; + private final java.util.Date endDate; + private final Integer notificationDays; + private final Integer notificationHours; + private final String workflowUuid; + private final User user; + + /** + * The constructor collects all necessary data and stores them. + * + * @param state + */ + public Publisher(final PageState state) { + startHour = (Integer) startHourField.getValue(state); + if (startMinuteField.getValue(state) == null) { + startMinute = 0; + } else { + startMinute = (Integer) startMinuteField.getValue(state); + } + startAmpm = (Integer) startAmpmSelect.getValue(state); + + endHour = (Integer) endHourField.getValue(state); + if (endMinuteField.getValue(state) == null) { + endMinute = 0; + } else { + endMinute = (Integer) endMinuteField.getValue(state); + } + endAmpm = (Integer) endAmpmSelect.getValue(state); + + //item = m_item.getContentItem(state); + itemUuid = itemRequestLocal.getContentItem(state).getItemUuid(); + + defID = (Long) cycleSelect.getValue(state); + + final Calendar start = Calendar.getInstance(); + start.setTime((java.util.Date) startDateField.getValue(state)); + start.set(Calendar.AM_PM, startAmpm); + start.set(Calendar.MINUTE, startMinute); + start.set(Calendar.AM_PM, startAmpm); + if (startHour != 12) { + start.set(Calendar.HOUR_OF_DAY, + 12 * startAmpm + startHour); + start.set(Calendar.HOUR, startHour); + } else { + if (startAmpm == 0) { + start.set(Calendar.HOUR_OF_DAY, 0); + start.set(Calendar.HOUR, 0); + } else { + start.set(Calendar.HOUR_OF_DAY, 12); + start.set(Calendar.HOUR, 0); + } + } + startDate = start.getTime(); + + if (endDateField.getValue(state) == null) { + endDate = null; + } else { + final Calendar end = Calendar.getInstance(); + + end.setTime((java.util.Date) endDateField.getValue(state)); + end.set(Calendar.AM_PM, endAmpm); + end.set(Calendar.MINUTE, endMinute); + end.set(Calendar.AM_PM, endAmpm); + + if (endHour != 12) { + end.set(Calendar.HOUR_OF_DAY, + 12 * endAmpm + endHour); + end.set(Calendar.HOUR, endHour); + } else { + if (endAmpm == 0) { + end.set(Calendar.HOUR_OF_DAY, 0); + end.set(Calendar.HOUR, 0); + } else { + end.set(Calendar.HOUR_OF_DAY, 12); + end.set(Calendar.HOUR, 0); + } + } + endDate = end.getTime(); + } + + notificationDays = (Integer) notificationDaysField.getValue(state); + notificationHours = (Integer) notificationHoursField.getValue(state); + + if (workflowRequestLocal.getWorkflow(state) != null) { + workflowUuid = workflowRequestLocal.getWorkflow(state).getUuid(); + } else { + workflowUuid = null; + } + + user = CdiUtil.createCdiUtil().findBean(Shiro.class).getUser(); + } + + /** + * Published the item + */ + public void publish() { + + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final ContentItemRepository itemRepo = cdiUtil.findBean( + ContentItemRepository.class); + final ContentItemManager itemManager = cdiUtil.findBean( + ContentItemManager.class); + final PhaseRepository phaseRepo = cdiUtil.findBean( + PhaseRepository.class); + final LifecycleDefinitionRepository lifecycleDefRepo = cdiUtil + .findBean(LifecycleDefinitionRepository.class); + final LifecycleManager lifecycleManager = cdiUtil.findBean( + LifecycleManager.class); + + final ContentItem item = itemRepo.findByUuid(itemUuid).get(); + + // If the item is already published, remove the current lifecycle. + // Do not touch the live version. + if (itemManager.isLive(item)) { + item.setLifecycle(null); + itemRepo.save(item); + } + + ContentItem pending; + final LifecycleDefinition cycleDef; + final Lifecycle lifecycle; + // Apply the new lifecycle. + cycleDef = lifecycleDefRepo.findById(defID); + pending = itemManager.publish(item, cycleDef); + lifecycle = pending.getLifecycle(); + + if (endDate != null) { + + // update individual phases + final List phases = lifecycle.getPhases(); + + for (final Phase phase : phases) { + final java.util.Date thisEnd = phase.getEndDateTime(); + final java.util.Date thisStart = phase.getStartDateTime(); + if (thisStart.compareTo(endDate) > 0) { + phase.setStartDateTime(endDate); + phaseRepo.save(phase); + } + } + } + + // endOfCycle may be the original date according to lifecycle phase definitions, or endDate if that was before + // natural end of lifecycle + final java.util.Date endOfCycle = lifecycle.getEndDateTime(); + if (endOfCycle != null) { + + // if advance notification is requested (!= 0) + // add another phase at the start of which the user is notified + java.util.Date notificationDate; + + int notificationPeriod = 0; + if (notificationDays != null) { + notificationPeriod += notificationDays * 24; + } + if (notificationHours != null) { + notificationPeriod += notificationHours; + } + } + + // Force the lifecycle scheduler to run to avoid any + // scheduler delay for items that should be published + // immediately. + lifecycleManager.startLifecycle(pending.getLifecycle()); + + if (workflowUuid != null) { + final WorkflowRepository workflowRepo = cdiUtil.findBean( + WorkflowRepository.class); + final Workflow workflow = workflowRepo.findByUuid(workflowUuid) + .get(); + finish(workflow, item, user); + } + } + + } + + static void finish(final Workflow workflow, + final ContentItem item, + final User user) { + if ((workflow != null) && (user != null)) { + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final WorkflowRepository workflowRepo = cdiUtil.findBean( + WorkflowRepository.class); + final WorkflowManager workflowManager = cdiUtil.findBean( + WorkflowManager.class); + final TaskManager taskManager = cdiUtil.findBean(TaskManager.class); + final CmsTaskManager cmsTaskManager = cdiUtil.findBean( + CmsTaskManager.class); + + final List enabledTasks = workflowManager.findEnabledTasks( + workflow); + for (final Task task : enabledTasks) { + LOGGER.debug("Task is {}.", task.getUuid()); + if (task instanceof CmsTask) { + final CmsTask cmsTask = (CmsTask) task; + + if (cmsTask.getTaskType() == CmsTaskType.DEPLOY) { + LOGGER.debug("Found DEPLOY task."); + taskManager.finish(cmsTask); + } + } + } + + if (CMSConfig.getConfig().isDeleteWorkflowAfterPublication()) { + workflowRepo.delete(workflow); + } else { + // restart the workflow by recreating it + // from the same workflow template + final WorkflowTemplate template = workflow.getTemplate(); + workflowRepo.delete(workflow); + final Workflow restarted = workflowManager.createWorkflow( + template, item); + // Startring the workflow will probably do the wrong thing, because most of the time + // the current user would be a publisher, not an author + workflowRepo.save(restarted); + } + } + } + + private class ValidationListener implements FormValidationListener { + + @Override + public void validate(final FormSectionEvent event) throws + FormProcessException { + final PageState state = event.getPageState(); + + final Integer startHour = (Integer) startHourField.getValue(state); + if (startHour == null) { + throw new FormProcessException(new GlobalizedMessage( + "cms.ui.item.start_time_incomplete", + CmsConstants.CMS_BUNDLE)); + } + + final Integer startMinute; + if (startMinuteField.getValue(state) == null) { + startMinute = 0; + } else { + startMinute = (Integer) startMinuteField.getValue(state); + } + + final Integer startAmpm = (Integer) startAmpmSelect.getValue(state); + + java.util.Date startDate = (java.util.Date) startDateField.getValue( + state); + if (startDate == null) { + throw new FormProcessException(new GlobalizedMessage( + "cms.ui.item.lifecycle.start_date_invalid", + CmsConstants.CMS_BUNDLE)); + } + + final java.util.Date nowDate = new java.util.Date(); + + final Calendar cStart = Calendar.getInstance(); + final Calendar cNow = Calendar.getInstance(); + cStart.setTime(startDate); + cNow.setTime(nowDate); + + if (startHour != 12) { + cStart.set(Calendar.HOUR_OF_DAY, + 12 * startAmpm + startHour); + cStart.set(Calendar.HOUR, startHour); + } else { + if (startAmpm == 0) { + cStart.set(Calendar.HOUR_OF_DAY, 0); + cStart.set(Calendar.HOUR, 0); + } else { + cStart.set(Calendar.HOUR_OF_DAY, 12); + cStart.set(Calendar.HOUR, 0); + } + } + + // Give the user extra 5 minutes before form complains + // start time's in the past. + cStart.set(Calendar.MINUTE, startMinute + 5); + cStart.set(Calendar.AM_PM, startAmpm); + cStart.set(Calendar.SECOND, cNow.get(Calendar.SECOND)); + cStart.set(Calendar.MILLISECOND, cNow.get(Calendar.MILLISECOND)); + + if (cNow.after(cStart)) { + throw new FormProcessException(new GlobalizedMessage( + "cms.ui.item.lifecycle.start_date_in_past", + CmsConstants.CMS_BUNDLE)); + } + + final Integer endHour = (Integer) endHourField.getValue(state); + final Integer endMinuteTmp = (Integer) endMinuteField + .getValue(state); + final java.util.Date endDate = (java.util.Date) endDateField + .getValue(state); + + if (endHour == null && (endMinuteTmp != null || endDate != null)) { + throw new FormProcessException(new GlobalizedMessage( + "cms.ui.item.lifecycle.end_time_incomplete", + CmsConstants.CMS_BUNDLE)); + } + + final Integer endMinute; + if (endMinuteTmp == null && endHour != null) { + endMinute = 0; + } else { + endMinute = endMinuteTmp; + } + + boolean timeBlank = (endHour == null) && (endMinute == null); + + final Integer endAmpm = (Integer) endAmpmSelect.getValue(state); + + if (endDate == null && !timeBlank) { + throw new FormProcessException(new GlobalizedMessage( + "cms.ui.item.lifecycle.end_date_invalid", + CmsConstants.CMS_BUNDLE)); + } + + if (endDate != null) { + final Calendar cEnd = Calendar.getInstance(); + cEnd.setTime(endDate); + + if (endHour != 12) { + cEnd.set(Calendar.HOUR_OF_DAY, + 12 * endAmpm + endHour); + cEnd.set(Calendar.HOUR, endHour); + } else { + if (endAmpm == 0) { + cEnd.set(Calendar.HOUR_OF_DAY, 0); + cEnd.set(Calendar.HOUR, 0); + } else { + cEnd.set(Calendar.HOUR_OF_DAY, 12); + cEnd.set(Calendar.HOUR, 0); + } + } + + // Give the user extra 5 minutes before form complains + // end time's in the past. + cEnd.set(Calendar.MINUTE, endMinute + 5); + cEnd.set(Calendar.AM_PM, endAmpm); + cEnd.set(Calendar.SECOND, cNow.get(Calendar.SECOND)); + cEnd.set(Calendar.MILLISECOND, cNow.get(Calendar.MILLISECOND)); + + //check if the end date is prior to the start date + if (cStart.after(cEnd)) { + throw new FormProcessException(new GlobalizedMessage( + "cms.ui.item.lifecycle.end_date_before_start_date", + CmsConstants.CMS_BUNDLE)); + } + + final Integer notificationDays = (Integer) notificationDaysField + .getValue(state); + final Integer notificationHours + = (Integer) notificationHoursField + .getValue(state); + + int notificationPeriod = 0; + if (notificationDays != null) { + notificationPeriod += notificationDays * 24; + } + if (notificationHours != null) { + notificationPeriod += notificationHours; + } + + if (notificationPeriod > 0) { + // point in time for notification == end date - notificationPeriod + final java.util.Date notificationDate + = computeNotificationDate( + cEnd.getTime(), + notificationPeriod); + LOGGER.debug("cStart (Date): {}", cStart.getTime()); + LOGGER.debug("notificationDate: {}", notificationDate); + // complain if date for notification is before the start date + if (notificationDate.before(cStart.getTime())) { + LOGGER.debug("notification date is before start date!"); + + throw new FormProcessException(new GlobalizedMessage( + "cms.ui.item.notification_period_before_start", + CmsConstants.CMS_BUNDLE)); + } else { + LOGGER.debug( + "notification date is after start date, OK"); + } + } + } + } + + } + + public class TimeZonePrinter implements PrintListener { + + @Override + public void prepare(final PrintEvent event) { + final Label target = (Label) event.getTarget(); + if (CMSConfig.getConfig().isHideTimezone()) { + target.setLabel(""); + } else { + final PageState state = event.getPageState(); + final Calendar mStart = Calendar.getInstance(); + final java.util.Date startDate = (java.util.Date) startDateField + .getValue(state); + + if (startDate != null) { + mStart.setTime((java.util.Date) startDateField.getValue( + state)); + } + + final String zone = mStart.getTimeZone().getDisplayName(true, + TimeZone.SHORT); + + target.setLabel(zone); + } + } + + } + + /** + * Find out at which date a notification (about an item that is about to + * expire) should be sent, based on the endDate (== date at which the item + * is unpublished) and the notification period. + * + * @param endDate the endDate of the lifecycle, i.e. the date when the + * item is going to be unpublished + * @param notification how many hours the users shouls be notified in + * advance + */ + private java.util.Date computeNotificationDate(final java.util.Date endDate, + final int notificationPeriod) { + if (endDate == null) { + return null; + } + + return new java.util.Date( + endDate.getTime() - notificationPeriod * 3600000L); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleSelectForm.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleSelectForm.java.todo deleted file mode 100755 index c6bbaf010..000000000 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemLifecycleSelectForm.java.todo +++ /dev/null @@ -1,1024 +0,0 @@ -/* - * 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.BoxPanel; -import com.arsdigita.bebop.FormProcessException; -import com.arsdigita.bebop.Label; -import com.arsdigita.bebop.PageState; -import com.arsdigita.bebop.SimpleContainer; -import com.arsdigita.bebop.event.FormInitListener; -import com.arsdigita.bebop.event.FormProcessListener; -import com.arsdigita.bebop.event.FormSectionEvent; -import com.arsdigita.bebop.event.FormValidationListener; -import com.arsdigita.bebop.event.PrintEvent; -import com.arsdigita.bebop.event.PrintListener; -import com.arsdigita.bebop.form.Date; -import com.arsdigita.bebop.form.Option; -import com.arsdigita.bebop.form.SingleSelect; -import com.arsdigita.bebop.form.Submit; -import com.arsdigita.bebop.form.TextField; -import com.arsdigita.bebop.parameters.BigDecimalParameter; -import com.arsdigita.bebop.parameters.DateParameter; -import com.arsdigita.bebop.parameters.IntegerParameter; -import com.arsdigita.bebop.parameters.NumberInRangeValidationListener; -import com.arsdigita.cms.CMS; -import com.arsdigita.cms.CMSConfig; -import com.arsdigita.cms.ContentItem; -import com.arsdigita.cms.ContentSection; -import com.arsdigita.cms.ContentTypeLifecycleDefinition; -import com.arsdigita.cms.ContentCenter; -import com.arsdigita.cms.lifecycle.Lifecycle; -import com.arsdigita.cms.lifecycle.LifecycleDefinition; -import com.arsdigita.cms.lifecycle.LifecycleDefinitionCollection; -import com.arsdigita.cms.lifecycle.Phase; -import com.arsdigita.cms.lifecycle.PhaseCollection; -import com.arsdigita.cms.lifecycle.PhaseDefinitionCollection; -import com.arsdigita.cms.ui.BaseForm; -import com.arsdigita.cms.ui.ContentItemPage; -import com.arsdigita.cms.ui.item.ContentItemRequestLocal; -import com.arsdigita.cms.ui.item.ItemWorkflowRequestLocal; -import com.arsdigita.cms.ui.workflow.WorkflowRequestLocal; -import com.arsdigita.cms.util.GlobalizationUtil; -import com.arsdigita.cms.workflow.CMSEngine; -import com.arsdigita.cms.workflow.CMSTask; -import com.arsdigita.cms.workflow.CMSTaskType; -import com.arsdigita.domain.DomainObjectFactory; -import com.arsdigita.kernel.Party; -import com.arsdigita.kernel.PartyCollection; -import com.arsdigita.kernel.User; -import com.arsdigita.notification.Notification; -import com.arsdigita.persistence.OID; -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.Engine; -import com.arsdigita.workflow.simple.TaskException; -import com.arsdigita.workflow.simple.Workflow; -import com.arsdigita.workflow.simple.WorkflowTemplate; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.Writer; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Calendar; -import java.util.Iterator; -import java.util.TimeZone; -import java.util.TooManyListenersException; -import javax.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; - -/** - *

- * A form to select and apply a lifecycle to a content item.

- * - * @author Michael Pih - * @author Xixi D'moon <xdmoon@redhat.com> - * @author Justin Ross <jross@redhat.com> - * @author Jens Pelzetter jens@jp-digital.de - * @version $Id: ItemLifecycleSelectForm.java 2267 2012-01-09 16:50:14Z pboy $ - */ -class ItemLifecycleSelectForm extends BaseForm { - - private static final Logger s_log - = Logger.getLogger(ItemLifecycleSelectForm.class); - private final static String LIFECYCLE = "lifecycle"; - private final static String START_DATE = "start_date"; - private final static String END_DATE = "end_date"; - private final static String NOTIFICATION_DAYS = "notifyDays"; - private final static String NOTIFICATION_HOURS = "notifyHours"; - private final ContentItemRequestLocal m_item; - private final WorkflowRequestLocal m_workflow; - // Form widgets - private final SingleSelect m_cycleSelect; - private final Date m_startDate; - private final TextField m_startHour; - private final TextField m_startMinute; - private final SingleSelect m_startAmpm; - private final Date m_endDate; - private final TextField m_endHour; - private final TextField m_endMinute; - private final SingleSelect m_endAmpm; - private TextField m_notificationDays; - private TextField m_notificationHours; - - public ItemLifecycleSelectForm(final ContentItemRequestLocal item) { - super("PublishItem", gz("cms.ui.item.lifecycle.apply")); - - m_item = item; - m_workflow = new ItemWorkflowRequestLocal(); - - m_cycleSelect = new SingleSelect(new BigDecimalParameter(LIFECYCLE)); - try { - m_cycleSelect.addPrintListener(new OptionPrinter()); - } catch (TooManyListenersException tmle) { - throw new UncheckedWrapperException(tmle); - } - addField(gz("cms.ui.item.lifecycle"), m_cycleSelect); - - // Start date - m_startDate = new Date(new DateParameter(START_DATE) { - - @Override - protected final Calendar getCalendar(final HttpServletRequest sreq) { - final Calendar cal = super.getCalendar(sreq); - - cal.setLenient(false); - - return cal; - } - - }); - addField(gz("cms.ui.item.lifecycle.start_date"), m_startDate); - - // Start time - final BoxPanel startTime = new BoxPanel(BoxPanel.HORIZONTAL); - addField(gz("cms.ui.item.lifecycle.start_time"), startTime); - - // Hour - m_startHour = new TextField(new IntegerParameter("start_hour")); - startTime.add(m_startHour); - - m_startHour.setSize(3); - m_startHour.addValidationListener( - new NumberInRangeValidationListener(1, 12)); - - // Minute - m_startMinute = new TextField(new IntegerParameter("start_minute")); - startTime.add(m_startMinute); - - m_startMinute.setSize(3); - m_startMinute.addValidationListener(new NumberInRangeValidationListener( - 0, 59)); - - // AM/PM - m_startAmpm = new SingleSelect(new IntegerParameter("start_ampm")); - startTime.add(m_startAmpm); - - m_startAmpm.addOption(new Option("0", "am")); - m_startAmpm.addOption(new Option("1", "pm")); - - // Time zone - startTime.add(new Label(new TimeZonePrinter())); - - // Expiration date - m_endDate = new Date(new DateParameter(END_DATE) { - - @Override - protected final Calendar getCalendar(final HttpServletRequest sreq) { - final Calendar cal = super.getCalendar(sreq); - - cal.setLenient(false); - - return cal; - } - - }); - addField(gz("cms.ui.item.lifecycle.end_date"), m_endDate); - - // End time - final BoxPanel endTime = new BoxPanel(BoxPanel.HORIZONTAL); - addField(gz("cms.ui.item.lifecycle.end_time"), endTime); - - // Hour - m_endHour = new TextField(new IntegerParameter("end_hour")); - endTime.add(m_endHour); - - m_endHour.setSize(3); - m_endHour.addValidationListener(new NumberInRangeValidationListener(1, - 12)); - - // Minute - m_endMinute = new TextField(new IntegerParameter("end_minute")); - endTime.add(m_endMinute); - - m_endMinute.setSize(3); - m_endMinute.addValidationListener( - new NumberInRangeValidationListener(0, 59)); - - // AM/PM - m_endAmpm = new SingleSelect(new IntegerParameter("end_ampm")); - endTime.add(m_endAmpm); - - m_endAmpm.addOption(new Option("0", "am")); - m_endAmpm.addOption(new Option("1", "pm")); - - endTime.add(new Label(new TimeZonePrinter())); - - m_notificationDays = new TextField(new IntegerParameter(NOTIFICATION_DAYS)); - m_notificationDays.setSize(4); - m_notificationHours = new TextField(new IntegerParameter(NOTIFICATION_HOURS)); - m_notificationHours.setSize(4); - SimpleContainer cont = new SimpleContainer(); - cont.add(m_notificationDays); - cont.add(new Label(GlobalizationUtil.globalize("cms.ui.item.days"), - false)); - cont.add(m_notificationHours); - cont.add(new Label(GlobalizationUtil.globalize("cms.ui.item.hours"), - false)); - - addField(gz("cms.ui.item.notification_period"), cont); - - // A hidden field that checks to see if the user wants publish - // with a start time earlier than current time. - addAction(new Submit("finish", gz("cms.ui.item.lifecycle.publish"))); - - // Form listeners - addValidationListener(new ValidationListener()); - addSecurityListener(PUBLISH, m_item); - addInitListener(new InitListener()); - addProcessListener(new ProcessListener()); - } - - private class OptionPrinter implements PrintListener { - - @Override - public final void prepare(final PrintEvent e) { - final ContentSection section = CMS.getContext().getContentSection(); - - final LifecycleDefinitionCollection ldc = section.getLifecycleDefinitions(); - ldc.addOrder("label"); - - final SingleSelect target = (SingleSelect) e.getTarget(); - target.clearOptions(); - - while (ldc.next()) { - final LifecycleDefinition ld = ldc.getLifecycleDefinition(); - final PhaseDefinitionCollection pdc = ld.getPhaseDefinitions(); - - // XXX domlay this seems a little weak. perhaps - // there's a better way to determine if a lifecycle is - // ready to be applied to an item. - if (!pdc.isEmpty()) { - target.addOption(new Option(ld.getID().toString(), - ld.getLabel())); - } - - pdc.close(); - } - - ldc.close(); - } - - } - - private class InitListener implements FormInitListener { - - @Override - public final void init(final FormSectionEvent e) { - final PageState state = e.getPageState(); - - final ContentItem item = m_item.getContentItem(state); - - if (item.isPublished()) { - // If the item is published, select the currently - // associated lifecycle. - - final LifecycleDefinition ld = item.getLifecycle(). - getLifecycleDefinition(); - m_cycleSelect.setValue(state, ld.getID()); - } else { - // Set the default lifecycle (if it exists). - - final ContentSection section = CMS.getContext().getContentSection(); - final LifecycleDefinition ld = ContentTypeLifecycleDefinition. - getLifecycleDefinition(section, item.getContentType()); - - if (ld != null) { - m_cycleSelect.setValue(state, ld.getID()); - } - } - - // Set the default start date. - // XXX Isn't just new Date() sufficient? - final java.util.Date start = new java.util.Date(System. - currentTimeMillis()); - m_startDate.setValue(state, start); - - final Calendar calendar = Calendar.getInstance(); - calendar.setTime(start); - - // If the hour is 12, then Calendar.get(Calendar.HOUR) - // returns 0 (from the 24 hour time - 12). We want it to - // return 12. - if (calendar.get(Calendar.HOUR) == 0) { - m_startHour.setValue(state, new Integer(12)); - } else { - m_startHour.setValue(state, new Integer(calendar.get( - Calendar.HOUR))); - } - - final Integer min = new Integer(calendar.get(Calendar.MINUTE)); - - if (min.intValue() < 10) { - m_startMinute.setValue(state, "0" + min.toString()); - } else { - m_startMinute.setValue(state, min.toString()); - } - - m_startAmpm.setValue(state, - new Integer(calendar.get(Calendar.AM_PM))); - - BigInteger[] defaultTime = BigInteger.valueOf(ContentSection.getConfig(). - getDefaultNotificationTime()). - divideAndRemainder(BigInteger.valueOf(24)); - - m_notificationDays.setValue(state, new Integer(defaultTime[0]. - intValue())); - m_notificationHours.setValue(state, new Integer(defaultTime[1]. - intValue())); - } - - } - - /** - * jensp 2011-12-14: Some larger changes to the behavior of the process - * listener. The real action has been moved to the - * @link{Publisher} class. If threaded publishing is active, the publish - * process runs in a separate thread (the item is locked before using - * {@link PublishLock}. If threaded publishing is not active, nothing has - * changed. - */ - private class ProcessListener implements FormProcessListener { - - @Override - public final void process(final FormSectionEvent e) - throws FormProcessException { - final PageState state = e.getPageState(); - final ContentItem item = m_item.getContentItem(state); - - final Publisher publisher = new Publisher(state); - if (CMSConfig.getInstanceOf().getThreadedPublishing()) { - final Runnable threadAction = new Runnable() { - - @Override - public void run() { - PublishLock.getInstance().lock(item); - publisher.publish(); - PublishLock.getInstance().unlock(item); - } - - }; - final Thread thread = new Thread(threadAction); - thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { - - @Override - public void uncaughtException(final Thread thread, - final Throwable ex) { - final StringWriter strWriter = new StringWriter(); - final PrintWriter writer = new PrintWriter(strWriter); - ex.printStackTrace(writer); - - PublishLock.getInstance().setError(item, strWriter.toString()); - s_log.error(String.format( - "An error occurred while " - + "publishing the item '%s': ", - item.getOID().toString()), - ex); - - if ((CMSConfig.getInstanceOf().getPublicationFailureSender() - == null) - && (CMSConfig.getInstanceOf(). - getPublicationFailureReceiver() == null)) { - return; - } - - final PartyCollection receiverParties = Party. - retrieveAllParties(); - Party receiver = null; - receiverParties.addEqualsFilter("primaryEmail", - CMSConfig.getInstanceOf(). - getPublicationFailureReceiver()); - if (receiverParties.next()) { - receiver = receiverParties.getParty(); - } - receiverParties.close(); - - final PartyCollection senderParties = Party. - retrieveAllParties(); - Party sender = null; - senderParties.addEqualsFilter("primaryEmail", CMSConfig. - getInstanceOf().getPublicationFailureReceiver()); - if (senderParties.next()) { - sender = senderParties.getParty(); - } - senderParties.close(); - - if ((sender != null) && (receiver != null)) { - final Writer traceWriter = new StringWriter(); - final PrintWriter printWriter = new PrintWriter( - traceWriter); - ex.printStackTrace(printWriter); - - final Notification notification = new Notification( - sender, - receiver, - String.format("Failed to publish item '%s'", - item.getOID().toString()), - String.format("Publishing item '%s' failed " - + "with error message: %s.\n\n" - + "Stacktrace:\n%s", - item.getOID().toString(), - ex.getMessage(), - traceWriter.toString())); - notification.save(); - } - } - - }); - thread.start(); - } else { - publisher.publish(); - } - - if (CMSConfig.getInstanceOf().getThreadedPublishing()) { - throw new RedirectSignal( - URL.getDispatcherPath() - + ContentItemPage.getItemURL(item, - ContentItemPage.PUBLISHING_TAB), - true); - } else { - if (ContentSection.getConfig().getUseStreamlinedCreation()) { - throw new RedirectSignal( - URL.there(state.getRequest(), - ContentCenter.getURL()), - true); - } - } - - /* - * final Integer startHour = (Integer) m_startHour.getValue(state); - * Integer startMinute = (Integer) m_startMinute.getValue(state); - * - * if (startMinute == null) { startMinute = new Integer(0); } - * - * final Integer startAmpm = (Integer) m_startAmpm.getValue(state); - * - * final Integer endHour = (Integer) m_endHour.getValue(state); - * Integer endMinute = (Integer) m_endMinute.getValue(state); - * - * if (endMinute == null) { endMinute = new Integer(0); } - * - * final Integer endAmpm = (Integer) m_endAmpm.getValue(state); - * - * // Instantiate the instance of the content type. final - * ContentItem item = m_item.getContentItem(state); - * - * final BigDecimal defID = (BigDecimal) - * m_cycleSelect.getValue(state); Assert.exists(defID); final - * LifecycleDefinition cycleDef = new LifecycleDefinition(defID); - * - * java.util.Date startDate = (java.util.Date) - * m_startDate.getValue(state); - * - * final Calendar start = Calendar.getInstanceOf(); - * start.setTime(startDate); start.set(Calendar.AM_PM, - * startAmpm.intValue()); start.set(Calendar.MINUTE, - * startMinute.intValue()); start.set(Calendar.AM_PM, - * startAmpm.intValue()); if (startHour.intValue() != 12) { - * start.set(Calendar.HOUR_OF_DAY, 12 * startAmpm.intValue() + - * startHour.intValue()); start.set(Calendar.HOUR, - * startHour.intValue()); } else { if (startAmpm.intValue() == 0) { - * start.set(Calendar.HOUR_OF_DAY, 0); start.set(Calendar.HOUR, 0); - * } else { start.set(Calendar.HOUR_OF_DAY, 12); - * start.set(Calendar.HOUR, 0); } } startDate = start.getTime(); - * - * java.util.Date endDate = (java.util.Date) - * m_endDate.getValue(state); - * - * if (endDate != null) { final Calendar end = - * Calendar.getInstanceOf(); - * - * end.setTime(endDate); end.set(Calendar.AM_PM, - * endAmpm.intValue()); end.set(Calendar.MINUTE, - * endMinute.intValue()); end.set(Calendar.AM_PM, - * endAmpm.intValue()); - * - * if (endHour.intValue() != 12) { end.set(Calendar.HOUR_OF_DAY, 12 - * * endAmpm.intValue() + endHour.intValue()); - * end.set(Calendar.HOUR, endHour.intValue()); } else { if - * (endAmpm.intValue() == 0) { end.set(Calendar.HOUR_OF_DAY, 0); - * end.set(Calendar.HOUR, 0); } else { end.set(Calendar.HOUR_OF_DAY, - * 12); end.set(Calendar.HOUR, 0); } } endDate = end.getTime(); } - * - * // If the item is already published, remove the current - * lifecycle. // Do not touch the live version. if - * (item.isPublished()) { item.removeLifecycle(item); item.save(); } - * - * // Apply the new lifecycle. ContentItem pending = - * item.publish(cycleDef, startDate); final Lifecycle lifecycle = - * pending.getLifecycle(); - * - * // XXX domlay Whoa. This must be broken for multiphase // - * lifecycles. - * - * if (endDate != null) { - * - * // update individual phases final PhaseCollection phases = - * lifecycle.getPhases(); - * - * while (phases.next()) { final Phase phase = phases.getPhase(); - * java.util.Date thisEnd = phase.getEndDate(); java.util.Date - * thisStart = phase.getStartDate(); if - * (thisStart.compareTo(endDate) > 0) { phase.setStartDate(endDate); - * phase.save(); } - * - * if (thisEnd == null || thisEnd.compareTo(endDate) > 0) { - * phase.setEndDate(endDate); phase.save(); } } } - * - * // endOfCycle may be the original date according to lifecycle - * phase definitions, or endDate if that was before // natural end - * of lifecycle java.util.Date endOfCycle = lifecycle.getEndDate(); - * if (endOfCycle != null) { - * - * // if advance notification is requested (!= 0) // add another - * phase at the start of which the user is notified Integer - * notificationDays = (Integer) m_notificationDays.getValue(state); - * Integer notificationHours = (Integer) - * m_notificationHours.getValue(state); java.util.Date - * notificationDate = null; - * - * int notificationPeriod = 0; if (notificationDays != null) { - * notificationPeriod += notificationDays.intValue() * 24; } if - * (notificationHours != null) { notificationPeriod += - * notificationHours.intValue(); } - * - * if (notificationPeriod > 0) { notificationDate = - * computeNotificationDate(endOfCycle, notificationPeriod); - * s_log.debug("adding custom phase"); Phase expirationImminentPhase - * = lifecycle.addCustomPhase("expirationImminent", new - * Long(notificationDate. getTime()), new - * Long(endOfCycle.getTime())); - * expirationImminentPhase.setListenerClassName( - * "com.arsdigita.cms.lifecycle.NotifyLifecycleListener"); - * expirationImminentPhase.save(); } } - * - * // Force the lifecycle scheduler to run to avoid any // - * scheduler delay for items that should be published // - * immediately. pending.getLifecycle().start(); - * - * item.save(); - * - * final Workflow workflow = m_workflow.getWorkflow(state); try { - * finish(workflow, item, Web.getWebContext().getUser()); } catch - * (TaskException te) { throw new FormProcessException(te); } // - * redirect to /content-center if streamlined creation mode is - * active. if - * (ContentSection.getConfig().getUseStreamlinedCreation()) { throw - * new RedirectSignal(URL.there(state.getRequest(), - * Utilities.getWorkspaceURL()), true); } - */ - } - - } - - /** - * This class contains the real publish action. - */ - private class Publisher { - - private final Integer startHour; - private final Integer startMinute; - private final Integer startAmpm; - private final Integer endHour; - private final Integer endMinute; - private final Integer endAmpm; - private final String oidStr; - private final BigDecimal defID; - private final java.util.Date startDate; - private final java.util.Date endDate; - private final Integer notificationDays; - private final Integer notificationHours; - private final String workflowOid; - private final User user; - - /** - * The constructor collects all necessary data and stores them. - * - * @param state - */ - public Publisher(final PageState state) { - startHour = (Integer) m_startHour.getValue(state); - if (m_startMinute.getValue(state) == null) { - startMinute = new Integer(0); - } else { - startMinute = (Integer) m_startMinute.getValue(state); - } - startAmpm = (Integer) m_startAmpm.getValue(state); - - endHour = (Integer) m_endHour.getValue(state); - if (m_endMinute.getValue(state) == null) { - endMinute = new Integer(0); - } else { - endMinute = (Integer) m_endMinute.getValue(state); - } - endAmpm = (Integer) m_endAmpm.getValue(state); - - //item = m_item.getContentItem(state); - oidStr = m_item.getContentItem(state).getOID().toString(); - - defID = (BigDecimal) m_cycleSelect.getValue(state); - - final Calendar start = Calendar.getInstance(); - start.setTime((java.util.Date) m_startDate.getValue(state)); - start.set(Calendar.AM_PM, startAmpm.intValue()); - start.set(Calendar.MINUTE, startMinute.intValue()); - start.set(Calendar.AM_PM, startAmpm.intValue()); - if (startHour.intValue() != 12) { - start.set(Calendar.HOUR_OF_DAY, - 12 * startAmpm.intValue() + startHour.intValue()); - start.set(Calendar.HOUR, startHour.intValue()); - } else { - if (startAmpm.intValue() == 0) { - start.set(Calendar.HOUR_OF_DAY, 0); - start.set(Calendar.HOUR, 0); - } else { - start.set(Calendar.HOUR_OF_DAY, 12); - start.set(Calendar.HOUR, 0); - } - } - startDate = start.getTime(); - - if (m_endDate.getValue(state) == null) { - endDate = null; - } else { - final Calendar end = Calendar.getInstance(); - - end.setTime((java.util.Date) m_endDate.getValue(state)); - end.set(Calendar.AM_PM, endAmpm.intValue()); - end.set(Calendar.MINUTE, endMinute.intValue()); - end.set(Calendar.AM_PM, endAmpm.intValue()); - - if (endHour.intValue() != 12) { - end.set(Calendar.HOUR_OF_DAY, - 12 * endAmpm.intValue() + endHour.intValue()); - end.set(Calendar.HOUR, endHour.intValue()); - } else { - if (endAmpm.intValue() == 0) { - end.set(Calendar.HOUR_OF_DAY, 0); - end.set(Calendar.HOUR, 0); - } else { - end.set(Calendar.HOUR_OF_DAY, 12); - end.set(Calendar.HOUR, 0); - } - } - endDate = end.getTime(); - } - - notificationDays = (Integer) m_notificationDays.getValue(state); - notificationHours = (Integer) m_notificationHours.getValue(state); - - if (m_workflow.getWorkflow(state) != null) { - workflowOid = m_workflow.getWorkflow(state).getOID().toString(); - } else { - workflowOid = null; - } - - user = Web.getWebContext().getUser(); - } - - /** - * Published the item - */ - public void publish() { - - /** - * We have to create a new instance here since it is not possible to - * access the same data object from multiple threads. - */ - final OID oid = OID.valueOf(oidStr); - final ContentItem item = (ContentItem) DomainObjectFactory. - newInstance(oid); - - // If the item is already published, remove the current lifecycle. - // Do not touch the live version. - if (item.isPublished()) { - item.removeLifecycle(item); - item.save(); - } - - ContentItem pending; - final LifecycleDefinition cycleDef; - final Lifecycle lifecycle; - // Apply the new lifecycle. - cycleDef = new LifecycleDefinition(defID); - pending = item.publish(cycleDef, startDate); - lifecycle = pending.getLifecycle(); - - // XXX domlay Whoa. This must be broken for multiphase - // lifecycles. - if (endDate != null) { - - // update individual phases - final PhaseCollection phases = lifecycle.getPhases(); - - while (phases.next()) { - final Phase phase = phases.getPhase(); - java.util.Date thisEnd = phase.getEndDate(); - java.util.Date thisStart = phase.getStartDate(); - if (thisStart.compareTo(endDate) > 0) { - phase.setStartDate(endDate); - phase.save(); - } - - if (thisEnd == null || thisEnd.compareTo(endDate) > 0) { - phase.setEndDate(endDate); - phase.save(); - } - } - } - - // endOfCycle may be the original date according to lifecycle phase definitions, or endDate if that was before - // natural end of lifecycle - java.util.Date endOfCycle = lifecycle.getEndDate(); - if (endOfCycle != null) { - - // if advance notification is requested (!= 0) - // add another phase at the start of which the user is notified - java.util.Date notificationDate = null; - - int notificationPeriod = 0; - if (notificationDays != null) { - notificationPeriod += notificationDays.intValue() * 24; - } - if (notificationHours != null) { - notificationPeriod += notificationHours.intValue(); - } - - if (notificationPeriod > 0) { - notificationDate = computeNotificationDate(endOfCycle, notificationPeriod); - s_log.debug("adding custom phase"); - Phase expirationImminentPhase = lifecycle.addCustomPhase("expirationImminent", - new Long( - notificationDate. - getTime()), - new Long(endOfCycle. - getTime())); - expirationImminentPhase.setListenerClassName( - "com.arsdigita.cms.lifecycle.NotifyLifecycleListener"); - expirationImminentPhase.save(); - } - } - - // Force the lifecycle scheduler to run to avoid any - // scheduler delay for items that should be published - // immediately. - pending.getLifecycle().start(); - - item.save(); - - if (workflowOid != null) { - final Workflow workflow = (Workflow) DomainObjectFactory.newInstance(OID. - valueOf(workflowOid)); - try { - finish(workflow, item, user); - } catch (TaskException ex) { - throw new UncheckedWrapperException(ex); - } - } - } - - } - - static void finish(Workflow workflow, ContentItem item, User user) throws - TaskException { - if ((workflow != null) && (user != null)) { - final Engine engine = Engine.getInstance(CMSEngine.CMS_ENGINE_TYPE); - // ; - - final Iterator iter = engine.getEnabledTasks(user, workflow.getID()). - iterator(); - - while (iter.hasNext()) { - final CMSTask task = (CMSTask) iter.next(); - if (s_log.isDebugEnabled()) { - s_log.debug("Task is " + task.getOID().toString()); - } - if (task.getTaskType().getID().equals(CMSTaskType.DEPLOY)) { - s_log.debug("Found DEPLOY task, ID=" + CMSTaskType.DEPLOY); - task.finish(user); - } - } - if (ContentSection.getConfig().getDeleteWorkflowAfterPublication()) { - workflow.delete(); - } else { - // restart the workflow by recreating it - // from the same workflow template - WorkflowTemplate t = workflow.getWorkflowTemplate(); - workflow.delete(); - workflow = t.instantiateNewWorkflow(); - workflow.setObject(item); - /* Startring the workflow will probably do the wrong thing, because most of the time - * the current user would be a publisher, not an author */ -// workflow.start(user); - workflow.save(); - } - } - } - - private class ValidationListener implements FormValidationListener { - - @Override - public void validate(FormSectionEvent e) throws FormProcessException { - final PageState state = e.getPageState(); - - final Integer startHour = (Integer) m_startHour.getValue(state); - if (startHour == null) { - throw new FormProcessException(GlobalizationUtil.globalize( - "cms.ui.item.start_time_incomplete")); - } - - Integer startMinute = (Integer) m_startMinute.getValue(state); - if (startMinute == null) { - startMinute = new Integer(0); - } - - Integer startAmpm = (Integer) m_startAmpm.getValue(state); - - java.util.Date startDate = (java.util.Date) m_startDate.getValue( - state); - if (startDate == null) { - throw new FormProcessException(GlobalizationUtil.globalize( - "cms.ui.item.lifecycle.start_date_invalid")); - } - - java.util.Date nowDate = new java.util.Date(System.currentTimeMillis()); - - Calendar cStart = Calendar.getInstance(); - Calendar cNow = Calendar.getInstance(); - cStart.setTime(startDate); - cNow.setTime(nowDate); - - if (startHour.intValue() != 12) { - cStart.set(Calendar.HOUR_OF_DAY, - 12 * startAmpm.intValue() + startHour.intValue()); - cStart.set(Calendar.HOUR, startHour.intValue()); - } else { - if (startAmpm.intValue() == 0) { - cStart.set(Calendar.HOUR_OF_DAY, 0); - cStart.set(Calendar.HOUR, 0); - } else { - cStart.set(Calendar.HOUR_OF_DAY, 12); - cStart.set(Calendar.HOUR, 0); - } - } - - // Give the user extra 5 minutes before form complains - // start time's in the past. - cStart.set(Calendar.MINUTE, startMinute.intValue() + 5); - cStart.set(Calendar.AM_PM, startAmpm.intValue()); - cStart.set(Calendar.SECOND, cNow.get(Calendar.SECOND)); - cStart.set(Calendar.MILLISECOND, cNow.get(Calendar.MILLISECOND)); - - if (cNow.after(cStart)) { - throw new FormProcessException(GlobalizationUtil.globalize( - "cms.ui.item.lifecycle.start_date_in_past")); - } - - Integer endHour = (Integer) m_endHour.getValue(state); - Integer endMinute = (Integer) m_endMinute.getValue(state); - java.util.Date endDate = (java.util.Date) m_endDate.getValue(state); - - if (endHour == null && (endMinute != null || endDate != null)) { - throw new FormProcessException(GlobalizationUtil.globalize( - "cms.ui.item.lifecycle.end_time_incomplete")); - } - - if (endMinute == null && endHour != null) { - endMinute = new Integer(0); - } - - boolean timeBlank = (endHour == null) && (endMinute == null); - - Integer endAmpm = (Integer) m_endAmpm.getValue(state); - - if (endDate == null && !timeBlank) { - throw new FormProcessException(GlobalizationUtil.globalize( - "cms.ui.item.lifecycle.end_date_invalid")); - } - - if (endDate != null) { - Calendar cEnd = Calendar.getInstance(); - cEnd.setTime(endDate); - - if (endHour.intValue() != 12) { - cEnd.set(Calendar.HOUR_OF_DAY, - 12 * endAmpm.intValue() + endHour.intValue()); - cEnd.set(Calendar.HOUR, endHour.intValue()); - } else { - if (endAmpm.intValue() == 0) { - cEnd.set(Calendar.HOUR_OF_DAY, 0); - cEnd.set(Calendar.HOUR, 0); - } else { - cEnd.set(Calendar.HOUR_OF_DAY, 12); - cEnd.set(Calendar.HOUR, 0); - } - } - - // Give the user extra 5 minutes before form complains - // end time's in the past. - cEnd.set(Calendar.MINUTE, endMinute.intValue() + 5); - cEnd.set(Calendar.AM_PM, endAmpm.intValue()); - cEnd.set(Calendar.SECOND, cNow.get(Calendar.SECOND)); - cEnd.set(Calendar.MILLISECOND, cNow.get(Calendar.MILLISECOND)); - - //check if the end date is prior to the start date - if (cStart.after(cEnd)) { - throw new FormProcessException(GlobalizationUtil.globalize( - "cms.ui.item.lifecycle.end_date_before_start_date")); - } - - Integer notificationDays = (Integer) m_notificationDays.getValue(state); - Integer notificationHours = (Integer) m_notificationHours.getValue(state); - - int notificationPeriod = 0; - if (notificationDays != null) { - notificationPeriod += notificationDays.intValue() * 24; - } - if (notificationHours != null) { - notificationPeriod += notificationHours.intValue(); - } - - if (notificationPeriod > 0) { - // point in time for notification == end date - notificationPeriod - java.util.Date notificationDate = computeNotificationDate(cEnd.getTime(), - notificationPeriod); - s_log.debug("cStart (Date): " + cStart.getTime()); - s_log.debug("notificationDate: " + notificationDate); - // complain if date for notification is before the start date - if (notificationDate.before(cStart.getTime())) { - s_log.debug("notification date is before start date!"); - - throw new FormProcessException(GlobalizationUtil.globalize("cms.ui.item.notification_period_before_start")); - } else { - s_log.debug("notification date is after start date, OK"); - } - } - } - } - - } - - public class TimeZonePrinter implements PrintListener { - - @Override - public void prepare(PrintEvent e) { - final Label target = (Label) e.getTarget(); - if (ContentSection.getConfig().getHideTimezone()) { - target.setLabel(""); - } else { - final PageState state = e.getPageState(); - final Calendar mStart = Calendar.getInstance(); - java.util.Date st = (java.util.Date) m_startDate.getValue(state); - - if (st != null) { - mStart.setTime((java.util.Date) m_startDate.getValue(state)); - } - - final String zone = mStart.getTimeZone().getDisplayName(true, - TimeZone.SHORT); - - target.setLabel(zone); - } - } - - } - - /** - * Find out at which date a notification (about an item that is about to - * expire) should be sent, based on the endDate (== date at which the item - * is unpublished) and the notification period. - * - * @param endDate the endDate of the lifecycle, i.e. the date when the item - * is going to be unpublished - * @param notification how many hours the users shouls be notified in - * advance - */ - private java.util.Date computeNotificationDate(java.util.Date endDate, - int notificationPeriod) { - if (endDate == null) { - return null; - } - - return new java.util.Date(endDate.getTime() - (long) notificationPeriod - * 3600000L); - } - -} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemPhaseTableModelBuilder.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemPhaseTableModelBuilder.java new file mode 100755 index 000000000..69292517a --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/ItemPhaseTableModelBuilder.java @@ -0,0 +1,137 @@ +/* + * 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.PageState; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.table.AbstractTableModelBuilder; +import com.arsdigita.bebop.table.TableModel; +import com.arsdigita.globalization.GlobalizedMessage; + +import org.arsdigita.cms.CMSConfig; +import org.libreccm.cdi.utils.CdiUtil; +import org.libreccm.l10n.GlobalizationHelper; +import org.librecms.CmsConstants; +import org.librecms.contentsection.ContentSection; +import org.librecms.contentsection.ContentSectionConfig; +import org.librecms.lifecycle.Phase; + +import java.text.DateFormat; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +/** + * @author Xixi D'Moon <xdmoon@arsdigita.com> + * @author Michael Pih + * @author Justin Ross <jross@redhat.com> + * @author Jens Pelzetter + */ +class ItemPhaseTableModelBuilder extends AbstractTableModelBuilder { + + private final LifecycleRequestLocal lifecycle; + + public ItemPhaseTableModelBuilder(final LifecycleRequestLocal lifecycle) { + this.lifecycle = lifecycle; + } + + @Override + public final TableModel makeModel(final Table table, + final PageState state) { + return new Model(lifecycle.getLifecycle(state).getPhases()); + } + + private static class Model implements TableModel { + + private final List phases; + private int index = -1; + private Phase phase; + + public Model(final List phases) { + this.phases = phases; + } + + @Override + public final int getColumnCount() { + return 4; + } + + @Override + public final boolean nextRow() { + index++; + if (index < phases.size()) { + phase = phases.get(index); + + return true; + } else { + return false; + } + } + + @Override + public final Object getElementAt(final int column) { + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final GlobalizationHelper globalizationHelper = cdiUtil + .findBean(GlobalizationHelper.class); + final Locale locale = globalizationHelper.getNegotiatedLocale(); + final DateFormat format; + if (CMSConfig.getConfig().isHideTimezone()) { + format = DateFormat.getDateTimeInstance( + DateFormat.FULL, DateFormat.SHORT, locale); + } else { + format = DateFormat.getDateTimeInstance( + DateFormat.FULL, DateFormat.FULL, locale); + } + + switch (column) { + case 0: + return phase.getDefinition().getLabel().getValue(locale); + case 1: + return phase.getDefinition().getDescription().getValue( + locale); + case 2: + final Date startDate = phase.getStartDateTime(); + return format.format(startDate); + case 3: + final Date endDate = phase.getEndDateTime(); + + if (endDate == null) { + return lz("cms.ui.lifecycle.forever"); + } else { + return format.format(endDate); + } + default: + throw new IllegalArgumentException(); + } + } + + @Override + public final Object getKeyAt(final int column) { + return phase.getDefinition().getDefinitionId(); + } + + } + + protected final static String lz(final String key) { + final GlobalizedMessage message = new GlobalizedMessage(key, + CmsConstants.CMS_BUNDLE); + return (String) message.localize(); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/LifecycleAdminPane.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/LifecycleAdminPane.java similarity index 100% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/LifecycleAdminPane.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/LifecycleAdminPane.java diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/LifecycleItemPane.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/LifecycleItemPane.java similarity index 99% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/LifecycleItemPane.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/LifecycleItemPane.java index 353b5560c..0386089e6 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/LifecycleItemPane.java.todo +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/LifecycleItemPane.java @@ -36,6 +36,7 @@ import org.librecms.lifecycle.PhaseDefinition; import com.arsdigita.cms.ui.BaseItemPane; import com.arsdigita.kernel.KernelConfig; import com.arsdigita.toolbox.ui.ActionGroup; +import com.arsdigita.toolbox.ui.Property; import com.arsdigita.toolbox.ui.PropertyList; import com.arsdigita.toolbox.ui.Section; diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/PhaseTableModelBuilder.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/PhaseTableModelBuilder.java index a745fc3d3..c899f6230 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/PhaseTableModelBuilder.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/PhaseTableModelBuilder.java @@ -38,26 +38,27 @@ import java.util.List; class PhaseTableModelBuilder extends LockableImpl implements TableModelBuilder { - private final LifecycleDefinitionRequestLocal m_cycle; + private final LifecycleDefinitionRequestLocal cycle; public PhaseTableModelBuilder (final LifecycleDefinitionRequestLocal cycle) { - m_cycle = cycle; + this.cycle = cycle; } + @Override public final TableModel makeModel(final Table table, final PageState state) { - return new PhaseTableModel(m_cycle.getLifecycleDefinition(state)); + return new PhaseTableModel(cycle.getLifecycleDefinition(state)); } private static class PhaseTableModel implements TableModel { - private PhaseDefinition m_phase; - private final List m_phases; + + private final List phases; private int index = -1; + private PhaseDefinition phase; public PhaseTableModel(final LifecycleDefinition cycle) { - m_phases = cycle.getPhaseDefinitions(); - m_phase = null; + phases = cycle.getPhaseDefinitions(); } @Override @@ -68,8 +69,8 @@ class PhaseTableModelBuilder extends LockableImpl @Override public final boolean nextRow() { index++; - if (index < m_phases.size()) { - m_phase = m_phases.get(index); + if (index < phases.size()) { + phase = phases.get(index); return true; } else { @@ -79,17 +80,17 @@ class PhaseTableModelBuilder extends LockableImpl @Override public final Object getElementAt(final int column) { - Assert.exists(m_phase, "PhaseDefinition m_phase"); + Assert.exists(phase, "PhaseDefinition m_phase"); switch (column) { case 0: - return m_phase.getLabel(); + return phase.getLabel(); case 1: - return m_phase.getDescription(); + return phase.getDescription(); case 2: - return Duration.formatDuration(m_phase.getDefaultDelay()); + return Duration.formatDuration(phase.getDefaultDelay()); case 3: - final Long duration = m_phase.getDefaultDuration(); + final Long duration = phase.getDefaultDuration(); if (duration == null) { return lz("cms.ui.lifecycle.forever"); @@ -105,11 +106,12 @@ class PhaseTableModelBuilder extends LockableImpl } } + @Override public Object getKeyAt(int columnIndex) { - if (m_phase == null) { + if (phase == null) { throw new IllegalStateException(); } else { - return m_phase.getDefinitionId(); + return phase.getDefinitionId(); } } } diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/ItemRevisionAdminPane.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/ItemRevisionAdminPane.java new file mode 100755 index 000000000..60319cac8 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/ItemRevisionAdminPane.java @@ -0,0 +1,362 @@ +/* + * 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.revision; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.GridPanel; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.Text; +import com.arsdigita.bebop.event.TableActionAdapter; +import com.arsdigita.bebop.event.TableActionEvent; +import com.arsdigita.bebop.form.Option; +import com.arsdigita.bebop.form.RadioGroup; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.table.DefaultTableCellRenderer; +import com.arsdigita.bebop.table.DefaultTableColumnModel; +import com.arsdigita.bebop.table.TableCellRenderer; +import com.arsdigita.bebop.table.TableColumn; +import com.arsdigita.bebop.table.TableColumnModel; + +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentSection; + +import com.arsdigita.cms.dispatcher.CMSDispatcher; +import com.arsdigita.cms.dispatcher.ItemResolver; +import com.arsdigita.cms.ui.BaseItemPane; +import com.arsdigita.cms.ui.item.ContentItemRequestLocal; +import com.arsdigita.toolbox.ui.ActionGroup; +import com.arsdigita.toolbox.ui.LayoutPanel; +import com.arsdigita.toolbox.ui.NullComponent; +import com.arsdigita.toolbox.ui.Section; + +import org.libreccm.cdi.utils.CdiUtil; +import org.librecms.contentsection.ContentItemManager; +import org.librecms.contentsection.ContentItemRepository; +import org.librecms.contentsection.ContentSectionManager; + +import java.math.BigInteger; + +/** + * Displays the revision history of a {@link ContentItem} + * + * @author unknown + * @author Jens Pelzetter + * + */ +public final class ItemRevisionAdminPane extends BaseItemPane { + + private final ContentItemRequestLocal itemRequestLocal; + + private final RevisionTable revisionsTable; + + private final RevisionRequestLocal fromRequestLocal; + private final RevisionRequestLocal toRequestLocal; + + private final LayoutPanel selectPane; + //ToDo + //private final DifferencePane diffPane; + + public ItemRevisionAdminPane(final ContentItemRequestLocal itemRequestLocal) { + this.itemRequestLocal = itemRequestLocal; + + final RadioGroup fromSelect = new RadioGroup("from"); + final RadioGroup toSelect = new RadioGroup("to"); + + fromRequestLocal = new SelectionRequestLocal(fromSelect); + toRequestLocal = new SelectionRequestLocal(toSelect); + + revisionsTable = new RevisionTable(fromSelect, toSelect); + + final RevisionForm form = new RevisionForm(fromSelect, toSelect, + revisionsTable); + + selectPane = new LayoutPanel(); + add(selectPane); + setDefault(selectPane); + + selectPane.setBody(new Section(gz("cms.ui.item.revisions"), form)); + + final ActionLink returnLink = new ActionLink(new Label(gz( + "cms.ui.item.revision.return"))); + +// Todo +// diffPane = new DifferencePane(itemRequestLocal, +// fromRequestLocal, +// toRequestLocal, +// returnLink); +// add(diffPane); +// +// connect(form, diffPane); + connect(returnLink, selectPane); + } + + private class SelectionRequestLocal extends RevisionRequestLocal { + + private final RadioGroup group; + + SelectionRequestLocal(final RadioGroup group) { + this.group = group; + } + + @Override + protected final Object initialValue(final PageState state) { + final Object selected = group.getValue(state); + + if (selected == null || selected.toString().equals("")) { + return null; + } else { + final long revisionNumber = Long.parseLong(selected.toString()); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final ContentItemRepository itemRepository = cdiUtil.findBean( + ContentItemRepository.class); + return itemRepository.retrieveRevision(revisionNumber); + } + } + + } + + private class RevisionForm extends Form { + + RevisionForm(final RadioGroup fromSelect, + final RadioGroup toSelect, + final RevisionTable revisions) { + super("revisions", new GridPanel(1)); + + setMethod("get"); + + add(fromSelect); + add(toSelect); + + // Sets the 'to' revision to the dummy current revision + // and the 'from' revision to the dummy root revision. + fromSelect.setOptionSelected(""); + toSelect.setOptionSelected(""); + + final ActionGroup group = new ActionGroup(); + add(group); + + group.setSubject(revisions); + + group.addAction(new Submit("diff", + gz("cms.ui.item.revision.difference.show"))); + } + + } + + private class RevisionTable extends Table { + // XXX Need to fix the static l18n stuff + + private final TableColumn fromCol = new TableColumn( + RevisionTableModelBuilder.FROM, lz("cms.ui.item.revision.from")); + private final TableColumn toCol = new TableColumn( + RevisionTableModelBuilder.TO, + lz("cms.ui.item.revision.to")); + private final TableColumn timestampCol = new TableColumn( + RevisionTableModelBuilder.TIMESTAMP, lz("cms.ui.item.revision")); + private final TableColumn userCol = new TableColumn( + RevisionTableModelBuilder.USER, lz("cms.ui.user")); + private final TableColumn descriptionCol = new TableColumn( + RevisionTableModelBuilder.DESCRIPTION, lz("cms.ui.description")); + private final TableColumn previewCol = new TableColumn( + RevisionTableModelBuilder.PREVIEW, lz("cms.ui.item.revision.view")); + private final TableColumn rollbackCol = new TableColumn( + RevisionTableModelBuilder.ROLLBACK, + lz("cms.ui.item.revision.rollback")); + + public RevisionTable(final RadioGroup fromSelect, + final RadioGroup toSelect) { + super(new RevisionTableModelBuilder(itemRequestLocal), + new DefaultTableColumnModel()); + + final TableColumnModel columns = getColumnModel(); + columns.add(fromCol); + columns.add(toCol); + columns.add(timestampCol); + columns.add(userCol); + columns.add(descriptionCol); + columns.add(previewCol); + columns.add(rollbackCol); + + fromCol.setCellRenderer(new RadioCellRenderer(fromSelect)); + toCol.setCellRenderer(new RadioCellRenderer(toSelect)); + timestampCol.setCellRenderer(new DefaultTableCellRenderer(false)); + userCol.setCellRenderer(new DefaultTableCellRenderer(false)); + descriptionCol.setCellRenderer(new DefaultTableCellRenderer(false)); + previewCol.setCellRenderer(new ViewCellRenderer()); + rollbackCol.setCellRenderer(new RollbackCellRenderer()); + + setEmptyView(new Label(gz("cms.ui.item.revision.none"))); + + addTableActionListener(new RollbackActionListener()); + } + + class RadioCellRenderer implements TableCellRenderer { + + private final RadioGroup group; + + RadioCellRenderer(final RadioGroup group) { + this.group = group; + } + + @Override + public Component getComponent(final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int column) { + switch (key.toString()) { + case "first": + if (column == RevisionTableModelBuilder.FROM) { + return new NullComponent(); + } else { + final Option option = new Option("", new Text("")); + + option.setGroup(group); + + return option; + } + case "last": + if (column == RevisionTableModelBuilder.FROM) { + final Option option = new Option("", ""); + + option.setGroup(group); + + return option; + } else { + return new NullComponent(); + } + default: + final Option option = new Option(key.toString(), + new Text("")); + + option.setGroup(group); + + return option; + } + } + + } + + class ViewCellRenderer implements TableCellRenderer { + + @Override + public Component getComponent(final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int column) { + if (key instanceof String) { + return new NullComponent(); + } else { + final BigInteger transID = (BigInteger) key; + final ContentItem item = itemRequestLocal.getContentItem( + state); + final ContentSection section = item.getContentType() + .getContentSection(); + + final ContentSectionManager sectionManager = CdiUtil + .createCdiUtil().findBean(ContentSectionManager.class); + final ItemResolver itemResolver = sectionManager + .getItemResolver(section); + + final StringBuffer url = new StringBuffer(itemResolver + .generateItemURL(state, item, section, + CMSDispatcher.PREVIEW)); + + // Cheesy code should be fixed + final String sep; + if (url.toString().indexOf('?') == -1) { + sep = "?"; + } else { + sep = "&"; + } + + // TODO: fix this + //url.append(sep).append + // (HistoryCollection.TRANS_ID).append("="); + url.append(sep).append("transID").append("="); + url.append(transID.toString()); + + final Link link = new Link(new Label(gz( + "cms.ui.item.revision.view")), + url.toString()); + + link.setTargetFrame(lz("cms.ui.item.revision.view")); + + return link; + } + } + + } + + class RollbackActionListener extends TableActionAdapter { + + @Override + public final void cellSelected(final TableActionEvent event) { + final PageState state = event.getPageState(); + + if (event.getColumn() == RevisionTableModelBuilder.ROLLBACK) { + final ContentItem item = itemRequestLocal.getContentItem( + state); + + //Rollback not supported yet + +// Versions.rollback(item.getOID(), +// new BigInteger(event.getRowKey() +// .toString())); +// +// item.applyTag(lz("cms.ui.item.revision.rolled_back")); + } + } + + } + + class RollbackCellRenderer implements TableCellRenderer { + + @Override + public Component getComponent(final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int column) { + if (key instanceof String) { + return new NullComponent(); + } else { + return new ControlLink(new Label(gz( + "cms.ui.item.revision.rollback"))); + } + } + + } + + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/ItemRevisionAdminPane.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/ItemRevisionAdminPane.java.todo deleted file mode 100755 index b965e1a0a..000000000 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/ItemRevisionAdminPane.java.todo +++ /dev/null @@ -1,316 +0,0 @@ -/* - * 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.revision; - -import com.arsdigita.bebop.ActionLink; -import com.arsdigita.bebop.Component; -import com.arsdigita.bebop.ControlLink; -import com.arsdigita.bebop.Form; -import com.arsdigita.bebop.GridPanel; -import com.arsdigita.bebop.Label; -import com.arsdigita.bebop.Link; -import com.arsdigita.bebop.PageState; -import com.arsdigita.bebop.Table; -import com.arsdigita.bebop.event.TableActionAdapter; -import com.arsdigita.bebop.event.TableActionEvent; -import com.arsdigita.bebop.form.Option; -import com.arsdigita.bebop.form.RadioGroup; -import com.arsdigita.bebop.form.Submit; -import com.arsdigita.bebop.table.DefaultTableCellRenderer; -import com.arsdigita.bebop.table.DefaultTableColumnModel; -import com.arsdigita.bebop.table.TableCellRenderer; -import com.arsdigita.bebop.table.TableColumn; -import com.arsdigita.bebop.table.TableColumnModel; -import com.arsdigita.cms.ContentItem; -import com.arsdigita.cms.ContentSection; -import com.arsdigita.cms.dispatcher.CMSDispatcher; -import com.arsdigita.cms.dispatcher.ItemResolver; -import com.arsdigita.cms.ui.BaseItemPane; -import com.arsdigita.cms.ui.item.ContentItemRequestLocal; -import com.arsdigita.toolbox.ui.ActionGroup; -import com.arsdigita.toolbox.ui.LayoutPanel; -import com.arsdigita.toolbox.ui.NullComponent; -import com.arsdigita.toolbox.ui.Section; -import com.arsdigita.versioning.Transaction; -import com.arsdigita.versioning.Versions; - -import java.math.BigInteger; - -/** - * - * @version $Id: ItemRevisionAdminPane.java 287 2005-02-22 00:29:02Z sskracic $ - */ -public final class ItemRevisionAdminPane extends BaseItemPane { - - private final ContentItemRequestLocal m_item; - - private final RevisionTable m_revisions; - - private final TransactionRequestLocal m_from; - private final TransactionRequestLocal m_to; - - private final LayoutPanel m_selectPane; - private final DifferencePane m_diffPane; - - public ItemRevisionAdminPane(final ContentItemRequestLocal item) { - m_item = item; - - final RadioGroup fromSelect = new RadioGroup("from"); - final RadioGroup toSelect = new RadioGroup("to"); - - m_from = new SelectionRequestLocal(fromSelect); - m_to = new SelectionRequestLocal(toSelect); - - m_revisions = new RevisionTable(fromSelect, toSelect); - - final RevisionForm form = new RevisionForm - (fromSelect, toSelect, m_revisions); - - m_selectPane = new LayoutPanel(); - add(m_selectPane); - setDefault(m_selectPane); - - m_selectPane.setBody - (new Section(gz("cms.ui.item.revisions"), form)); - - final ActionLink returnLink = new ActionLink - (new Label(gz("cms.ui.item.revision.return"))); - - m_diffPane = new DifferencePane(m_item, m_from, m_to, returnLink); - add(m_diffPane); - - connect(form, m_diffPane); - connect(returnLink, m_selectPane); - } - - private class SelectionRequestLocal extends TransactionRequestLocal { - private final RadioGroup m_group; - - SelectionRequestLocal(final RadioGroup group) { - m_group = group; - } - - protected final Object initialValue(final PageState state) { - final Object id = m_group.getValue(state); - - if (id == null || id.toString().equals("")) { - return null; - } else { - return Transaction.retrieve(new BigInteger(id.toString())); - } - } - } - - private class RevisionForm extends Form { - RevisionForm(final RadioGroup fromSelect, - final RadioGroup toSelect, - final RevisionTable revisions) { - super("revisions", new GridPanel(1)); - - setMethod("get"); - - add(fromSelect); - add(toSelect); - - // Sets the 'to' revision to the dummy current revision - // and the 'from' revision to the dummy root revision. - fromSelect.setOptionSelected(""); - toSelect.setOptionSelected(""); - - final ActionGroup group = new ActionGroup(); - add(group); - - group.setSubject(revisions); - - group.addAction - (new Submit("diff", - gz("cms.ui.item.revision.difference.show"))); - } - } - - private class RevisionTable extends Table { - // XXX Need to fix the static l18n stuff - - private TableColumn m_from = new TableColumn - (RevisionTableModelBuilder.FROM, lz("cms.ui.item.revision.from")); - private TableColumn m_to = new TableColumn - (RevisionTableModelBuilder.TO, lz("cms.ui.item.revision.to")); - private TableColumn m_timestamp = new TableColumn - (RevisionTableModelBuilder.TIMESTAMP, lz("cms.ui.item.revision")); - private TableColumn m_user = new TableColumn - (RevisionTableModelBuilder.USER, lz("cms.ui.user")); - private TableColumn m_description = new TableColumn - (RevisionTableModelBuilder.DESCRIPTION, lz("cms.ui.description")); - private TableColumn m_preview = new TableColumn - (RevisionTableModelBuilder.PREVIEW, lz("cms.ui.item.revision.view")); - private TableColumn m_rollback = new TableColumn - (RevisionTableModelBuilder.ROLLBACK, - lz("cms.ui.item.revision.rollback")); - - public RevisionTable(final RadioGroup fromSelect, - final RadioGroup toSelect) { - super(new RevisionTableModelBuilder(m_item), - new DefaultTableColumnModel()); - - final TableColumnModel columns = getColumnModel(); - columns.add(m_from); - columns.add(m_to); - columns.add(m_timestamp); - columns.add(m_user); - columns.add(m_description); - columns.add(m_preview); - columns.add(m_rollback); - - m_from.setCellRenderer(new RadioCellRenderer(fromSelect)); - m_to.setCellRenderer(new RadioCellRenderer(toSelect)); - m_timestamp.setCellRenderer(new DefaultTableCellRenderer(false)); - m_user.setCellRenderer(new DefaultTableCellRenderer(false)); - m_description.setCellRenderer(new DefaultTableCellRenderer(false)); - m_preview.setCellRenderer(new ViewCellRenderer()); - m_rollback.setCellRenderer(new RollbackCellRenderer()); - - setEmptyView(new Label(gz("cms.ui.item.revision.none"))); - - addTableActionListener(new RollbackActionListener()); - } - - class RadioCellRenderer implements TableCellRenderer { - private final RadioGroup m_group; - - RadioCellRenderer(final RadioGroup group) { - m_group = group; - } - - public Component getComponent(final Table table, - final PageState state, - final Object value, - final boolean isSelected, - final Object key, - final int row, final int column) { - if (key.toString().equals("first")) { - if (column == RevisionTableModelBuilder.FROM) { - return new NullComponent(); - } else { - final Option option = new Option("", ""); - - option.setGroup(m_group); - - return option; - } - } else if (key.toString().equals("last")) { - if (column == RevisionTableModelBuilder.FROM) { - final Option option = new Option("", ""); - - option.setGroup(m_group); - - return option; - } else { - return new NullComponent(); - } - } else { - final Option option = new Option(key.toString(), ""); - - option.setGroup(m_group); - - return option; - } - } - } - - class ViewCellRenderer implements TableCellRenderer { - public Component getComponent(final Table table, - final PageState state, - final Object value, - final boolean isSelected, - final Object key, - final int row, final int column) { - if (key instanceof String) { - return new NullComponent(); - } else { - final BigInteger transID = (BigInteger) key; - final ContentItem item = m_item.getContentItem(state); - final ContentSection section = item.getContentSection(); - - final ItemResolver itemResolver = - section.getItemResolver(); - - final StringBuffer url = new StringBuffer - (itemResolver.generateItemURL - (state, item, section, CMSDispatcher.PREVIEW)); - - // Cheesy code should be fixed - - final String sep; - if (url.toString().indexOf('?') == -1) { - sep = "?"; - } else { - sep = "&"; - } - - // TODO: fix this - //url.append(sep).append - // (HistoryCollection.TRANS_ID).append("="); - url.append(sep).append("transID").append("="); - url.append(transID.toString()); - - final Link link = new Link - (new Label(gz("cms.ui.item.revision.view")), - url.toString()); - - link.setTargetFrame(lz("cms.ui.item.revision.view")); - - return link; - } - } - } - - class RollbackActionListener extends TableActionAdapter { - public final void cellSelected(final TableActionEvent e) { - final PageState state = e.getPageState(); - - if (e.getColumn().intValue() - == RevisionTableModelBuilder.ROLLBACK) { - final ContentItem item = m_item.getContentItem(state); - - Versions.rollback - (item.getOID(), - new BigInteger(e.getRowKey().toString())); - - item.applyTag(lz("cms.ui.item.revision.rolled_back")); - } - } - } - - class RollbackCellRenderer implements TableCellRenderer { - public Component getComponent(final Table table, - final PageState state, - final Object value, - final boolean isSelected, - final Object key, - final int row, final int column) { - if (key instanceof String) { - return new NullComponent(); - } else { - return new ControlLink - (new Label(gz("cms.ui.item.revision.rollback"))); - } - } - } - } -} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/RevisionRequestLocal.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/RevisionRequestLocal.java new file mode 100755 index 000000000..e5806e310 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/RevisionRequestLocal.java @@ -0,0 +1,33 @@ +/* + * 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.revision; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; + +import org.libreccm.auditing.CcmRevision; + +public abstract class RevisionRequestLocal extends RequestLocal { + + public final CcmRevision getRevision(final PageState state) { + final CcmRevision revision = (CcmRevision) get(state); + + return revision; + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/RevisionTableModelBuilder.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/RevisionTableModelBuilder.java new file mode 100755 index 000000000..e0df62508 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/RevisionTableModelBuilder.java @@ -0,0 +1,164 @@ +/* + * 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.revision; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.table.AbstractTableModelBuilder; +import com.arsdigita.bebop.table.TableModel; +import com.arsdigita.cms.ui.item.ContentItemRequestLocal; +import com.arsdigita.globalization.GlobalizedMessage; + +import org.libreccm.security.User; + +import com.arsdigita.toolbox.ui.FormatStandards; + +import org.libreccm.auditing.CcmRevision; +import org.libreccm.cdi.utils.CdiUtil; +import org.librecms.CmsConstants; +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentItemRepository; + +import java.util.List; + +/** + * @author Stanislav Freidin <sfreidin@redhat.com> + * @author Justin Ross <jross@redhat.com> + * @version $Id: RevisionTableModelBuilder.java 1942 2009-05-29 07:53:23Z terry + * $ + */ +class RevisionTableModelBuilder extends AbstractTableModelBuilder { + + static final int FROM = 0; + static final int TO = 1; + static final int TIMESTAMP = 2; + static final int USER = 3; + static final int DESCRIPTION = 4; + static final int PREVIEW = 5; + static final int ROLLBACK = 6; + + static final int COLUMNS = 7; + + private final ContentItemRequestLocal itemRequestLocal; + + RevisionTableModelBuilder(final ContentItemRequestLocal itemRequestLocal) { + this.itemRequestLocal = itemRequestLocal; + } + + @Override + public final TableModel makeModel(final Table table, + final PageState state) { + return new Model(itemRequestLocal.getContentItem(state)); + } + + private static class Model implements TableModel { + + private final List revisions; + private CcmRevision currentRevision; + private long count = 0; + private long last = 2; + private int index = -1; + + public Model(final ContentItem item) { + final ContentItemRepository itemRepository = CdiUtil + .createCdiUtil() + .findBean(ContentItemRepository.class); + revisions = itemRepository.retrieveRevisions(item, + item.getObjectId()); + + last = revisions.size() + 2; + } + + @Override + public final int getColumnCount() { + return COLUMNS; + } + + @Override + public final boolean nextRow() { + count++; + index++; + + if (count == 1) { + return true; + } else if (count == last) { + return true; + } else if (revisions.size() < index) { + currentRevision = revisions.get(index); + + return true; + } else { + return false; + } + } + + @Override + public final Object getElementAt(final int column) { + if (count == 1) { + switch (column) { + case TIMESTAMP: + return lz("cms.ui.item.revision.current"); + default: + return ""; + } + } else if (count == last) { + switch (column) { + case TIMESTAMP: + return lz("cms.ui.item.revision.first"); + default: + return ""; + } + } else { + switch (column) { + case TIMESTAMP: + return FormatStandards.formatDateTime( + currentRevision.getRevisionDate()); + case USER: + + return currentRevision.getUserName(); + case DESCRIPTION: + return ""; + default: + return ""; + } + } + } + + @Override + public final Object getKeyAt(final int column) { + if (count == 1) { + return "first"; + } else if (count == last) { + return "last"; + } else { + return currentRevision.getId(); + } + } + + } + + private static GlobalizedMessage gz(final String key) { + return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE); + } + + private static String lz(final String key) { + return (String) gz(key).localize(); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/ItemWorkflowAdminPane.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/ItemWorkflowAdminPane.java similarity index 100% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/ItemWorkflowAdminPane.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/ItemWorkflowAdminPane.java diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/ItemWorkflowItemPane.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/ItemWorkflowItemPane.java similarity index 100% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/ItemWorkflowItemPane.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/ItemWorkflowItemPane.java diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/TaskFinishForm.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/TaskFinishForm.java similarity index 100% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/TaskFinishForm.java.todo rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/TaskFinishForm.java diff --git a/ccm-core/src/main/java/org/libreccm/auditing/AbstractAuditedEntityRepository.java b/ccm-core/src/main/java/org/libreccm/auditing/AbstractAuditedEntityRepository.java index 1710d2afa..2dd9b842f 100644 --- a/ccm-core/src/main/java/org/libreccm/auditing/AbstractAuditedEntityRepository.java +++ b/ccm-core/src/main/java/org/libreccm/auditing/AbstractAuditedEntityRepository.java @@ -44,8 +44,17 @@ public abstract class AbstractAuditedEntityRepository public abstract K getEntityId(final T entity); + /** + * Retrieves an entity at specific revision. The entity will be in the state + * as it was when the revision was created. + * + * @param entity + * @param revision + * + * @return + */ @SuppressWarnings("unchecked") - public T retrieveRevisionOfEntity(final T entity, final Number revision) { + public T retrieveEntityAtRevision(final T entity, final Number revision) { final AuditQuery query = auditReader.createQuery() .forEntitiesAtRevision(getEntityClass(), revision); query.add(AuditEntity.id().eq(getEntityId(entity))); @@ -104,7 +113,7 @@ public abstract class AbstractAuditedEntityRepository * Retrieves all revisions of the given entity. The list of revisions is * ordered from the oldest revision to the newest revision. * - * @param entity The entity. + * @param entity The entity. * @param objectId The primary key of the entity. * * @return A list of all revisions of the provided entity. @@ -122,9 +131,10 @@ public abstract class AbstractAuditedEntityRepository /** * Retrieves the current revision of an entity. - * - * @param entity The entity. + * + * @param entity The entity. * @param objectId the primary key the entity. + * * @return The most current revision of the entity. */ public CcmRevision retrieveCurrentRevision(final T entity, @@ -136,4 +146,17 @@ public abstract class AbstractAuditedEntityRepository return auditReader.findRevision(CcmRevision.class, lastRevision); } + /** + * Retrieves a specific revision object. + * + * @param entity + * @param objectId + * @param revision + * + * @return + */ + public CcmRevision retrieveRevision(final Number revision) { + return auditReader.findRevision(CcmRevision.class, revision); + } + } diff --git a/ccm-core/src/main/java/org/libreccm/workflow/Workflow.java b/ccm-core/src/main/java/org/libreccm/workflow/Workflow.java index 5366cda86..6749796b0 100644 --- a/ccm-core/src/main/java/org/libreccm/workflow/Workflow.java +++ b/ccm-core/src/main/java/org/libreccm/workflow/Workflow.java @@ -64,6 +64,10 @@ import org.libreccm.portation.Portable; @Table(name = "WORKFLOWS", schema = DB_SCHEMA) @Inheritance(strategy = InheritanceType.JOINED) @NamedQueries({ + @NamedQuery( + name = "Workflow.findByUuid", + query = "SELECT W FROM Workflow w WHERE w.uuid = :uuid") + , @NamedQuery( name = "Workflow.findForObject", query = "SELECT w FROM Workflow w " diff --git a/ccm-core/src/main/java/org/libreccm/workflow/WorkflowRepository.java b/ccm-core/src/main/java/org/libreccm/workflow/WorkflowRepository.java index e7ba9ea42..afc89e1b6 100644 --- a/ccm-core/src/main/java/org/libreccm/workflow/WorkflowRepository.java +++ b/ccm-core/src/main/java/org/libreccm/workflow/WorkflowRepository.java @@ -52,22 +52,48 @@ public class WorkflowRepository extends AbstractEntityRepository workflow.setUuid(UUID.randomUUID().toString()); } + /** + * Find a {@link Workflow} by its UUID. + * + * @param uuid The UUID of the {@link Workflow} to find. + * + * @return An {@link Optional} containing the {@link Workflow} identified by + * the provided UUID. + */ + public Optional findByUuid(final String uuid) { + if (uuid == null || uuid.trim().isEmpty()) { + throw new IllegalArgumentException( + "The UUID of the Workflow to retrieve can't be null or empty."); + } + + final TypedQuery query = getEntityManager().createNamedQuery( + "Workflow.findByUuid", Workflow.class); + query.setParameter("uuid", uuid); + + try { + return Optional.of(query.getSingleResult()); + } catch(NoResultException ex) { + return Optional.empty(); + } + } + /** * Finds the workflow for an given object if the object has workflow. * * @param object The object + * * @return An {@link Optional} containing the workflow assigned to the - * {@code object} if the object has a workflow. Otherwise an empty - * {@link Optional} is returned. + * {@code object} if the object has a workflow. Otherwise an empty + * {@link Optional} is returned. */ public Optional findWorkflowForObject(final CcmObject object) { if (object == null) { throw new IllegalArgumentException( - "Can't find a workflow for object null."); + "Can't find a workflow for object null."); } final TypedQuery query = getEntityManager().createNamedQuery( - "Workflow.findForObject", Workflow.class); + "Workflow.findForObject", Workflow.class); query.setParameter("object", object); try {