CCM NG: Migrated several classes from ccm-core to CCM NG. No finished, none finished classes as *.todo to avoid compilation failures.

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4457 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2016-11-25 16:32:50 +00:00
parent 45c8296282
commit f63434ae80
27 changed files with 3917 additions and 509 deletions

View File

@ -23,7 +23,6 @@ import com.arsdigita.bebop.SingleSelectionModel;
import com.arsdigita.bebop.parameters.LongParameter; import com.arsdigita.bebop.parameters.LongParameter;
import com.arsdigita.ui.CcmObjectSelectionModel; import com.arsdigita.ui.CcmObjectSelectionModel;
import org.apache.log4j.Logger;
import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.cdi.utils.CdiUtil;
import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentType; import org.librecms.contentsection.ContentType;
@ -53,6 +52,14 @@ public class ItemSelectionModel extends CcmObjectSelectionModel<ContentItem> {
private Long typeId; private Long typeId;
public ItemSelectionModel(final LongParameter parameter) {
super(parameter);
}
public ItemSelectionModel(final String parameterName) {
super(parameterName);
}
/** /**
* Construct a new <code>ItemSelectionModel</code> * Construct a new <code>ItemSelectionModel</code>
* *

View File

@ -55,7 +55,8 @@ public class CMSForm extends Form implements Cancellable {
* @param state The page state * @param state The page state
* @return true if the form is cancelled, false otherwise * @return true if the form is cancelled, false otherwise
*/ */
public boolean isCancelled(PageState state) { @Override
public boolean isCancelled(final PageState state) {
return false; return false;
} }
} }

View File

@ -0,0 +1,98 @@
/*
* 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;
import com.arsdigita.bebop.PageState;
import com.arsdigita.cms.CMS;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.ContentSection;
import com.arsdigita.cms.ContentType;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.Template;
import com.arsdigita.cms.PageLocations;
import com.arsdigita.web.ParameterMap;
import com.arsdigita.web.URL;
import org.apache.log4j.Logger;
import java.util.List;
/**
* <p>The context bar of the content section UI.</p>
*
* @author Justin Ross &lt;jross@redhat.com&gt;
* @version $Id: ContentItemContextBar.java 287 2005-02-22 00:29:02Z sskracic $
*/
class ContentItemContextBar extends ContentSectionContextBar {
private static final Logger s_log = Logger.getLogger
(ContentItemContextBar.class);
private final ItemSelectionModel m_item;
ContentItemContextBar(final ItemSelectionModel item) {
super();
m_item = item;
}
@Override
protected final List entries(final PageState state) {
final List entries = super.entries(state);
final ContentItem item = (ContentItem) m_item.getSelectedObject(state);
final ContentSection section = CMS.getContext().getContentSection();
boolean isTemplate =
item.getContentType().equals(ContentType.findByAssociatedObjectType(Template.BASE_DATA_OBJECT_TYPE));
final URL url = URL.there
(state.getRequest(),
section.getPath() + "/" + PageLocations.ITEM_PAGE,
params(item));
StringBuffer title = new StringBuffer();
if (isTemplate) {
title.append(localize("cms.ui.template"));
} else {
title.append(localize("cms.ui.content_item"));
}
title.append(": ")
.append(item.getDisplayName());
String language = item.getLanguage();
if (language != null) {
title.append(" (")
.append(language)
.append(")");
}
entries.add(new Entry(title.toString(), url));
return entries;
}
private static ParameterMap params(final ContentItem item) {
final ParameterMap params = new ParameterMap();
params.setParameter(ContentItemPage.ITEM_ID, item.getID());
return params;
}
private static String localize(final String key) {
return (String) ContentSectionPage.globalize(key).localize();
}
}

View File

@ -24,8 +24,10 @@ import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label; import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Link; import com.arsdigita.bebop.Link;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.ParameterSingleSelectionModel;
import com.arsdigita.bebop.Resettable; import com.arsdigita.bebop.Resettable;
import com.arsdigita.bebop.SimpleContainer; import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.SingleSelectionModel;
import com.arsdigita.bebop.TabbedPane; import com.arsdigita.bebop.TabbedPane;
import com.arsdigita.bebop.event.ActionEvent; import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener; import com.arsdigita.bebop.event.ActionListener;
@ -33,9 +35,12 @@ import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.FormValidationListener; import com.arsdigita.bebop.event.FormValidationListener;
import com.arsdigita.bebop.event.PrintEvent; import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener; import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.parameters.BigDecimalParameter; import com.arsdigita.bebop.parameters.LongParameter;
import com.arsdigita.bebop.parameters.NotNullValidationListener; import com.arsdigita.bebop.parameters.NotNullValidationListener;
import com.arsdigita.bebop.parameters.StringParameter; 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.ui.item.CustomizedPreviewLink;
import com.arsdigita.cms.dispatcher.CMSDispatcher; import com.arsdigita.cms.dispatcher.CMSDispatcher;
import com.arsdigita.cms.dispatcher.CMSPage; import com.arsdigita.cms.dispatcher.CMSPage;
@ -49,31 +54,43 @@ import com.arsdigita.cms.ui.revision.ItemRevisionAdminPane;
import com.arsdigita.cms.ui.templates.ItemTemplates; import com.arsdigita.cms.ui.templates.ItemTemplates;
import com.arsdigita.cms.ui.workflow.ItemWorkflowAdminPane; import com.arsdigita.cms.ui.workflow.ItemWorkflowAdminPane;
import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.kernel.KernelConfig;
import com.arsdigita.kernel.ui.ACSObjectSelectionModel; import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
import com.arsdigita.util.Assert; import com.arsdigita.util.Assert;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.xml.Document; import com.arsdigita.xml.Document;
import com.arsdigita.xml.Element; import com.arsdigita.xml.Element;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.util.Optional;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger; 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.librecms.CmsConstants;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentItemVersion;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentType;
/** /**
* Page for administering a content item. * Page for administering a content item.
* *
* @author Michael Pih * @author Michael Pih
* @author Stanislav Freidin &lt;sfreidin@redhat.com&gt; * @author <a href="mailto:sfreidin@redhat.com">Stanislav Freidin</a>
* @author Jack Chung * @author Jack Chung
* @author Sören Bernstein <quasi@quasiweb.de> * @author <a href="mailto:quasi@quasiweb.de">Sören Bernstein</a>
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
* *
* @version $Id: ContentItemPage.java 2245 2011-11-15 08:03:57Z pboy $
*/ */
public class ContentItemPage extends CMSPage implements ActionListener { public class ContentItemPage extends CMSPage implements ActionListener {
/** /**
* Private Logger instance for debugging purpose. * Private Logger instance for debugging purpose.
*/ */
private static final Logger s_log = Logger.getLogger(ContentItemPage.class); private static final Logger LOGGER = LogManager.getLogger(
ContentItemPage.class);
/** /**
* The URL parameter that must be passed in in order to set the current tab. * The URL parameter that must be passed in in order to set the current tab.
* This is a KLUDGE right now because the TabbedDialog's current tab is * This is a KLUDGE right now because the TabbedDialog's current tab is
@ -81,11 +98,15 @@ public class ContentItemPage extends CMSPage implements ActionListener {
*/ */
public static final String SET_TAB = "set_tab"; public static final String SET_TAB = "set_tab";
/** /**
* The name of the global state parameter that holds the item id * The name of the global state parameter that holds the item id.
*/ */
public static final String ITEM_ID = "item_id"; public static final String ITEM_ID = "item_id";
/** /**
* The name of the global state parameter which holds the return URL * The name of th global state parameter that holds the selected language.
*/
public static final String SELECTED_LANGUAGE = "selected_language";
/**
* The name of the global state parameter which holds the return URL.
*/ */
public static final String RETURN_URL = "return_url"; public static final String RETURN_URL = "return_url";
/** /**
@ -96,43 +117,47 @@ public class ContentItemPage extends CMSPage implements ActionListener {
public static final String STREAMLINED_CREATION = "streamlined_creation"; public static final String STREAMLINED_CREATION = "streamlined_creation";
public static final String STREAMLINED_CREATION_ACTIVE = "active"; public static final String STREAMLINED_CREATION_ACTIVE = "active";
public static final String STREAMLINED_CREATION_INACTIVE = "active"; public static final String STREAMLINED_CREATION_INACTIVE = "active";
private static int s_tabOrder = 0;
/** /**
* Index of the summary tab * Index of the summary tab
*/ */
public static final int SUMMARY_TAB = s_tabOrder++; public static final int SUMMARY_TAB = 0;
/** /**
* <p>The name of the state parameter which indicates the content type of * <p>
* the item the user wishes to create. or edit.</p> * The name of the state parameter which indicates the content type of the
* item the user wishes to create. or edit.</p>
* *
* <p>The parameter must be a BigDecimalParameter which encodes the id of * <p>
* the content type.</p> * The parameter must be a BigDecimalParameter which encodes the id of the
* content type.</p>
*/ */
public static final String CONTENT_TYPE = "content_type"; public static final String CONTENT_TYPE = "content_type";
public static final int AUTHORING_TAB = s_tabOrder++; public static final int AUTHORING_TAB = 1;
public static final int LANGUAGE_TAB = s_tabOrder++; public static final int LANGUAGE_TAB = 2;
public static final int WORKFLOW_TAB = s_tabOrder++; public static final int WORKFLOW_TAB = 3;
public static final int PUBLISHING_TAB = s_tabOrder++; public static final int PUBLISHING_TAB = 4;
public static final int HISTORY_TAB = s_tabOrder++; public static final int HISTORY_TAB = 5;
public static final int TEMPLATES_TAB = s_tabOrder++; public static final int TEMPLATES_TAB = 6;
private final TabbedPane m_tabbedPane;
private StringParameter m_returnURL; private final TabbedPane tabbedPane;
private ItemSelectionModel m_itemModel; private final StringParameter returnUrlParameter;
private ACSObjectSelectionModel m_typeModel; private final ItemSelectionModel itemModel;
private ContentItemRequestLocal m_item; private final SingleSelectionModel<String> selectedLanguageModel;
private Summary m_summaryPane; private final ACSObjectSelectionModel typeModel;
private ItemWorkflowAdminPane m_workflowPane; private final ContentItemRequestLocal itemRequestLocal;
private ItemLifecycleAdminPane m_lifecyclePane; private final Summary summaryPane;
private WizardSelector m_wizardPane; private final ItemWorkflowAdminPane workflowPane;
private ItemLanguages m_languagesPane; private final ItemLifecycleAdminPane lifecyclePane;
private ItemRevisionAdminPane m_revisionsPane; private final WizardSelector wizardPane;
private ItemTemplates m_templatesPane; private final ItemLanguages languagesPane;
private Link m_previewLink; private final ItemRevisionAdminPane revisionsPane;
private GlobalNavigation m_globalNavigation; private final ItemTemplates templatesPane;
private ContentItemContextBar m_contextBar; private final Link m_previewLink;
private final GlobalNavigation m_globalNavigation;
private final ContentItemContextBar m_contextBar;
private class ItemRequestLocal extends ContentItemRequestLocal { private class ItemRequestLocal extends ContentItemRequestLocal {
@Override
protected final Object initialValue(final PageState state) { protected final Object initialValue(final PageState state) {
return CMS.getContext().getContentItem(); return CMS.getContext().getContentItem();
} }
@ -140,9 +165,11 @@ public class ContentItemPage extends CMSPage implements ActionListener {
private class TitlePrinter implements PrintListener { private class TitlePrinter implements PrintListener {
public final void prepare(final PrintEvent e) { @Override
final Label label = (Label) e.getTarget(); public final void prepare(final PrintEvent event) {
final ContentItem item = m_item.getContentItem(e.getPageState()); final Label label = (Label) event.getTarget();
final ContentItem item = itemRequestLocal.getContentItem(event.
getPageState());
label.setLabel(item.getDisplayName()); label.setLabel(item.getDisplayName());
} }
@ -154,80 +181,88 @@ public class ContentItemPage extends CMSPage implements ActionListener {
public ContentItemPage() { public ContentItemPage() {
super("", new SimpleContainer()); super("", new SimpleContainer());
m_item = new ItemRequestLocal(); itemRequestLocal = new ItemRequestLocal();
setClassAttr("cms-admin"); setClassAttr("cms-admin");
setTitle(new Label(new TitlePrinter())); setTitle(new Label(new TitlePrinter()));
// Add the item id global state parameter // Add the item id global state parameter
BigDecimalParameter itemId = new BigDecimalParameter(ITEM_ID); final LongParameter itemId = new LongParameter(ITEM_ID);
itemId.addParameterListener(new NotNullValidationListener(ITEM_ID)); itemId.addParameterListener(new NotNullValidationListener(ITEM_ID));
addGlobalStateParam(itemId); addGlobalStateParam(itemId);
m_itemModel = new ItemSelectionModel(itemId); itemModel = new ItemSelectionModel(itemId);
// Add the selected item language as parameter
final StringParameter selectedLanguage = new StringParameter(
SELECTED_LANGUAGE);
selectedLanguage.addParameterListener(new NotNullValidationListener(
SELECTED_LANGUAGE));
addGlobalStateParam(selectedLanguage);
selectedLanguageModel = new ParameterSingleSelectionModel<>(
selectedLanguage);
// Add the content type global state parameter // Add the content type global state parameter
BigDecimalParameter contentType = new BigDecimalParameter(CONTENT_TYPE); final LongParameter contentType = new LongParameter(CONTENT_TYPE);
addGlobalStateParam(contentType); addGlobalStateParam(contentType);
// Add the streamlined creation global state parameter // Add the streamlined creation global state parameter
StringParameter streamlinedCreation = new StringParameter( final StringParameter streamlinedCreation = new StringParameter(
STREAMLINED_CREATION); STREAMLINED_CREATION);
addGlobalStateParam(streamlinedCreation); addGlobalStateParam(streamlinedCreation);
m_typeModel = new ACSObjectSelectionModel(ContentType.class.getName(), typeModel = new ACSObjectSelectionModel(ContentType.class.getName(),
ContentType.BASE_DATA_OBJECT_TYPE, ContentType.class.getName(),
contentType); contentType);
// Validate the item ID parameter (caches the validation). // Validate the item ID parameter (caches the validation).
getStateModel().addValidationListener(new FormValidationListener() { getStateModel().addValidationListener(
public void validate(FormSectionEvent event) event -> validateItemID(event.getPageState()));
throws FormProcessException {
validateItemID(event.getPageState());
}
});
// Add the return url global state parameter // Add the return url global state parameter
m_returnURL = new StringParameter(RETURN_URL); returnUrlParameter = new StringParameter(RETURN_URL);
addGlobalStateParam(m_returnURL); addGlobalStateParam(returnUrlParameter);
m_globalNavigation = new GlobalNavigation(); m_globalNavigation = new GlobalNavigation();
add(m_globalNavigation); add(m_globalNavigation);
m_contextBar = new ContentItemContextBar(m_itemModel); m_contextBar = new ContentItemContextBar(itemModel);
add(m_contextBar); add(m_contextBar);
// Create panels. // Create panels.
m_summaryPane = new Summary(m_itemModel); summaryPane = new Summary(itemModel);
m_wizardPane = new WizardSelector(m_itemModel, m_typeModel); wizardPane = new WizardSelector(itemModel, typeModel);
m_languagesPane = new ItemLanguages(m_itemModel); languagesPane = new ItemLanguages(itemModel, selectedLanguageModel);
m_workflowPane = new ItemWorkflowAdminPane(itemId); // Make this use m_item XXX workflowPane = new ItemWorkflowAdminPane(itemId); // Make this use m_item XXX
m_lifecyclePane = new ItemLifecycleAdminPane(m_item); lifecyclePane = new ItemLifecycleAdminPane(itemRequestLocal);
m_revisionsPane = new ItemRevisionAdminPane(m_item); revisionsPane = new ItemRevisionAdminPane(itemRequestLocal);
m_templatesPane = new ItemTemplates(m_itemModel); templatesPane = new ItemTemplates(itemModel);
// Create tabbed pane. // Create tabbed pane.
m_tabbedPane = new TabbedPane(); tabbedPane = new TabbedPane();
add(m_tabbedPane); add(tabbedPane);
m_tabbedPane.setIdAttr("page-body"); tabbedPane.setIdAttr("page-body");
m_tabbedPane.addTab(new Label(gz("cms.ui.item.summary")), m_summaryPane); tabbedPane.addTab(new Label(gz("cms.ui.item.summary")), summaryPane);
m_tabbedPane.addTab(new Label(gz("cms.ui.item.authoring")), m_wizardPane); tabbedPane.
m_tabbedPane.addTab(new Label(gz("cms.ui.item.languages")), addTab(new Label(gz("cms.ui.item.authoring")), wizardPane);
m_languagesPane); tabbedPane.addTab(new Label(gz("cms.ui.item.languages")),
m_tabbedPane.addTab(new Label(gz("cms.ui.item.workflow")), languagesPane);
m_workflowPane); tabbedPane.addTab(new Label(gz("cms.ui.item.workflow")),
m_tabbedPane.addTab(new Label(gz("cms.ui.item.lifecycles")), workflowPane);
m_lifecyclePane); tabbedPane.addTab(new Label(gz("cms.ui.item.lifecycles")),
m_tabbedPane.addTab(new Label(gz("cms.ui.item.history")), lifecyclePane);
m_revisionsPane); tabbedPane.addTab(new Label(gz("cms.ui.item.history")),
m_tabbedPane.addTab(new Label(gz("cms.ui.item.templates")), revisionsPane);
m_templatesPane); tabbedPane.addTab(new Label(gz("cms.ui.item.templates")),
templatesPane);
m_tabbedPane.addActionListener(new ActionListener() { tabbedPane.addActionListener(new ActionListener() {
public final void actionPerformed(final ActionEvent e) { @Override
final PageState state = e.getPageState(); public final void actionPerformed(final ActionEvent event) {
final Component pane = m_tabbedPane.getCurrentPane(state);
final PageState state = event.getPageState();
final Component pane = tabbedPane.getCurrentPane(state);
if (pane instanceof Resettable) { if (pane instanceof Resettable) {
((Resettable) pane).reset(state); ((Resettable) pane).reset(state);
@ -237,13 +272,15 @@ public class ContentItemPage extends CMSPage implements ActionListener {
// Build the preview link. // Build the preview link.
m_previewLink = new Link(new Label(gz("cms.ui.preview")), m_previewLink = new Link(new Label(gz("cms.ui.preview")),
new PrintListener() { new PrintListener() {
public final void prepare(final PrintEvent e) { @Override
final Link link = (Link) e.getTarget(); public final void prepare(final PrintEvent event) {
link.setTarget(getPreviewURL(e.getPageState())); final Link link = (Link) event.getTarget();
link.setTargetFrame(Link.NEW_FRAME); link.setTarget(getPreviewURL(event.
} getPageState()));
}); link.setTargetFrame(Link.NEW_FRAME);
}
});
m_previewLink.setIdAttr("preview_link"); m_previewLink.setIdAttr("preview_link");
add(m_previewLink); add(m_previewLink);
@ -251,21 +288,25 @@ public class ContentItemPage extends CMSPage implements ActionListener {
// Add validation to make sure we are not attempting to edit a live item // Add validation to make sure we are not attempting to edit a live item
getStateModel().addValidationListener(new FormValidationListener() { getStateModel().addValidationListener(new FormValidationListener() {
public void validate(FormSectionEvent e) throws FormProcessException {
PageState s = e.getPageState(); @Override
FormData data = e.getFormData(); public void validate(final FormSectionEvent event)
final ContentItem item = m_item.getContentItem(s); throws FormProcessException {
if (item != null && ContentItem.LIVE.equals(item.getVersion())) {
s_log.error(String.format( PageState s = event.getPageState();
"The item %d is live and cannot be edited.", item.getID())); FormData data = event.getFormData();
// data.addError(err); final ContentItem item = itemRequestLocal.getContentItem(s);
throw new FormProcessException(GlobalizationUtil.globalize( if (item != null
"cms.ui.live_item_not_editable")); && ContentItemVersion.LIVE == item.getVersion()) {
LOGGER.error(String.format(
"The item %d is live and cannot be edited.", item.
getObjectId()));
throw new FormProcessException(new GlobalizedMessage(
"cms.ui.live_item_not_editable",
CmsConstants.CMS_BUNDLE));
} }
} }
}); });
add(new DebugPanel());
} }
/** /**
@ -276,12 +317,13 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* @pre state != null * @pre state != null
* @exception FormProcessException if the item_id is not valid * @exception FormProcessException if the item_id is not valid
*/ */
protected void validateItemID(PageState state) throws FormProcessException { protected void validateItemID(final PageState state) throws
final ContentItem item = m_item.getContentItem(state); FormProcessException {
final ContentItem item = itemRequestLocal.getContentItem(state);
if (item == null) { if (item == null) {
throw new FormProcessException(GlobalizationUtil.globalize( throw new FormProcessException(new GlobalizedMessage(
"cms.ui.invalid_item_id")); "cms.ui.invalid_item_id", CmsConstants.CMS_BUNDLE));
} }
} }
@ -294,7 +336,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* @return The current content section * @return The current content section
*/ */
@Override @Override
public ContentSection getContentSection(HttpServletRequest request) { public ContentSection getContentSection(final HttpServletRequest request) {
// Resets all content sections associations. // Resets all content sections associations.
ContentSection section = super.getContentSection(request); ContentSection section = super.getContentSection(request);
Assert.exists(section); Assert.exists(section);
@ -310,54 +352,49 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* @return The current content item, null if there is none * @return The current content item, null if there is none
*/ */
@Override @Override
public ContentItem getContentItem(PageState state) { public ContentItem getContentItem(final PageState state) {
return (ContentItem) m_itemModel.getSelectedObject(state); return (ContentItem) itemModel.getSelectedObject(state);
} }
/** /**
* Set the current tab, if necessary * Set the current tab, if necessary
* @param event
*/ */
public void actionPerformed(ActionEvent event) { @Override
public void actionPerformed(final ActionEvent event) {
final PageState state = event.getPageState(); final PageState state = event.getPageState();
final String setTab = state.getRequest().getParameter(SET_TAB); final String setTab = state.getRequest().getParameter(SET_TAB);
// Hide the templates tab, the workflow tab, and the preview // Hide the templates tab, the workflow tab, and the preview
// link if the current item is a template. // link if the current item is a template.
final ContentItem item = m_item.getContentItem(state); final ContentItem item = itemRequestLocal.getContentItem(state);
if (item instanceof Template) {
m_tabbedPane.setTabVisible(state, m_templatesPane, false);
m_tabbedPane.setTabVisible(state, m_workflowPane, false);
m_tabbedPane.setTabVisible(state, m_languagesPane, false);
m_previewLink.setVisible(state, false);
} else {
m_tabbedPane.setTabVisible(state, m_templatesPane, !ContentSection.
getConfig().getHideTemplatesTab());
}
// Added by: Sören Bernstein <quasi@quasiweb.de>
// If the content item is a language invariant content item, don't show
// the language pane
if (item instanceof LanguageInvariantContentItem) {
LanguageInvariantContentItem li_item = (LanguageInvariantContentItem) item;
if (li_item.isLanguageInvariant()) {
m_tabbedPane.setTabVisible(state, m_languagesPane, false);
}
}
// ToDo: Reable when Templates have been ported. Not clear yet if
// Templates will be ContentItems in LibreCMS...
// if (item instanceof Template) {
// tabbedPane.setTabVisible(state, templatesPane, false);
// tabbedPane.setTabVisible(state, workflowPane, false);
// tabbedPane.setTabVisible(state, languagesPane, false);
// m_previewLink.setVisible(state, false);
// } else {
// tabbedPane.setTabVisible(state,
// templatesPane,
// !ContentSectionConfig.getConfig().getHideTemplatesTab());
// }
// Set the current tab based on parameters // Set the current tab based on parameters
if (setTab != null) { if (setTab != null) {
Integer tab = null; Integer tab;
try { try {
tab = Integer.valueOf(setTab); tab = Integer.valueOf(setTab);
} catch (NumberFormatException e) { } catch (NumberFormatException ex) {
// Stop processing set_tab parameter. // Stop processing set_tab parameter.
LOGGER.warn("Stopping processing of set_tab parameter.", ex);
return; return;
} }
if (tab.intValue() < m_tabbedPane.size()) { if (tab < tabbedPane.size()) {
m_tabbedPane.setSelectedIndex(state, tab.intValue()); tabbedPane.setSelectedIndex(state, tab);
} }
} }
} }
@ -368,10 +405,11 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* @param nodeURL The URL where this page is mounted * @param nodeURL The URL where this page is mounted
* @param itemId The id of the item to display * @param itemId The id of the item to display
* @param tab The index of the tab to display * @param tab The index of the tab to display
* @return
*/ */
public static String getItemURL(String nodeURL, public static String getItemURL(final String nodeURL,
BigDecimal itemId, final Long itemId,
int tab) { final int tab) {
return getItemURL(nodeURL, itemId, tab, false); return getItemURL(nodeURL, itemId, tab, false);
} }
@ -382,33 +420,58 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* @param itemId The id of the item to display * @param itemId The id of the item to display
* @param tab The index of the tab to display * @param tab The index of the tab to display
* @param streamlinedCreation Whether to activate Streamlined item authoring * @param streamlinedCreation Whether to activate Streamlined item authoring
* @return
*/ */
public static String getItemURL(String nodeURL, public static String getItemURL(final String nodeURL,
BigDecimal itemId, final Long itemId,
int tab, final int tab,
boolean streamlinedCreation) { final boolean streamlinedCreation) {
StringBuffer url = new StringBuffer(); final StringBuilder urlBuilder = new StringBuilder();
url.append(nodeURL).append(PageLocations.ITEM_PAGE).append("?").append( urlBuilder
ITEM_ID).append("=").append(itemId.toString()).append("&"). .append(nodeURL)
append(SET_TAB).append("=").append(tab); .append(PageLocations.ITEM_PAGE)
.append("?")
.append(ITEM_ID)
.append("=")
.append(itemId.toString())
.append("&")
.append(SET_TAB)
.append("=")
.append(tab);
if (streamlinedCreation && ContentSection.getConfig(). if (streamlinedCreation
getUseStreamlinedCreation()) { && CMSConfig.getConfig().isUseStreamlinedCreation()) {
url.append("&").append(STREAMLINED_CREATION).append("=").append(
STREAMLINED_CREATION_ACTIVE); urlBuilder
.append("&")
.append(STREAMLINED_CREATION)
.append("=")
.append(STREAMLINED_CREATION_ACTIVE);
} }
return url.toString(); return urlBuilder.toString();
} }
/** /**
* @param itemId
* @param tab
* @return
* @deprecated Use getItemURL instead * @deprecated Use getItemURL instead
*/ */
public static String getRelativeItemURL(BigDecimal itemId, int tab) { public static String getRelativeItemURL(final Long itemId, final int tab) {
StringBuffer url = new StringBuffer(); final StringBuilder url = new StringBuilder();
url.append(PageLocations.ITEM_PAGE).append("?").append(ITEM_ID).append("=").append(itemId. url
toString()).append("&").append(SET_TAB).append("=").append(tab); .append(PageLocations.ITEM_PAGE)
.append("?")
.append(ITEM_ID)
.append("=")
.append(itemId.toString())
.append("&")
.append(SET_TAB)
.append("=")
.append(tab);
return url.toString(); return url.toString();
} }
@ -417,16 +480,18 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* *
* @param item the ContentItem object to display * @param item the ContentItem object to display
* @param tab The index of the tab to display * @param tab The index of the tab to display
* @return
*/ */
public static String getItemURL(ContentItem item, int tab) { public static String getItemURL(final ContentItem item,
final ContentSection section = item.getContentSection(); final int tab) {
final ContentSection section = item.getContentType().getContentSection();
if (section == null) { if (section == null) {
return null; return null;
} else { } else {
final String nodeURL = section.getPath() + "/"; final String nodeURL = section.getPrimaryUrl() + "/";
return getItemURL(nodeURL, item.getID(), tab); return getItemURL(nodeURL, item.getObjectId(), tab);
} }
} }
@ -435,16 +500,20 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* *
* @param itemId the id of the ContentItem object to display * @param itemId the id of the ContentItem object to display
* @param tab The index of the tab to display * @param tab The index of the tab to display
* @return
*/ */
public static String getItemURL(long itemId, int tab) { public static String getItemURL(final long itemId,
final ContentItem item = final int tab) {
(ContentItem) DomainObjectFactory.newInstance(new OID( final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
ContentItem.BASE_DATA_OBJECT_TYPE, itemId)); final ContentItemRepository itemRepo = cdiUtil.findBean(
ContentItemRepository.class);
if (item == null) { final Optional<ContentItem> item = itemRepo.findById(itemId);
return null;
if (item.isPresent()) {
return getItemURL(item.get(), tab);
} else { } else {
return getItemURL(item, tab); return null;
} }
} }
@ -454,12 +523,12 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* *
* @param state The current page state * @param state The current page state
*/ */
public void redirectBack(PageState state) { public void redirectBack(final PageState state) {
try { try {
String returnURL = (String) state.getValue(m_returnURL); final String returnUrl = (String) state.getValue(returnUrlParameter);
state.getResponse().sendRedirect(returnURL); state.getResponse().sendRedirect(returnUrl);
} catch (IOException e) { } catch (IOException ex) {
s_log.error("IO Error redirecting back", e); LOGGER.error("IO Error redirecting back", ex);
// do nothing // do nothing
} }
} }
@ -467,13 +536,13 @@ public class ContentItemPage extends CMSPage implements ActionListener {
/** /**
* Fetch the preview URL. * Fetch the preview URL.
*/ */
private String getPreviewURL(PageState state) { private String getPreviewURL(final PageState state) {
final ContentItem item = m_item.getContentItem(state); final ContentItem item = itemRequestLocal.getContentItem(state);
if (item instanceof CustomizedPreviewLink) { if (item instanceof CustomizedPreviewLink) {
final String previewLink = ((CustomizedPreviewLink) item). final String previewLink = ((CustomizedPreviewLink) item).
getPreviewUrl( getPreviewUrl(
state); state);
if ((previewLink == null) || previewLink.isEmpty()) { if ((previewLink == null) || previewLink.isEmpty()) {
return getDefaultPreviewLink(state, item); return getDefaultPreviewLink(state, item);
} else { } else {
@ -491,49 +560,66 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* @return * @return
*/ */
private String getDefaultPreviewLink(final PageState state, private String getDefaultPreviewLink(final PageState state,
final ContentItem item) { final ContentItem item) {
final ContentSection section = CMS.getContext().getContentSection(); final ContentSection section = CMS.getContext().getContentSection();
//ContentSection section = getContentSection(state); final ItemResolver itemResolver;
final ItemResolver itemResolver = section.getItemResolver(); try {
final Class<?> itemResolverClass = Class.forName(section.
getItemResolverClass());
itemResolver = (ItemResolver) itemResolverClass.newInstance();
} catch (ClassNotFoundException
| IllegalAccessException
| InstantiationException ex) {
throw new UncheckedWrapperException(ex);
}
// Pass in the "Live" context since we need it for the preview // Pass in the "Live" context since we need it for the preview
return itemResolver.generateItemURL(state, item, section, return itemResolver.generateItemURL(state,
CMSDispatcher.PREVIEW); item,
section,
CMSDispatcher.PREVIEW);
} }
protected final static GlobalizedMessage gz(final String key) { protected final static GlobalizedMessage gz(final String key) {
return GlobalizationUtil.globalize(key); return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE);
} }
protected final static String lz(final String key) { protected final static String lz(final String key) {
return (String) gz(key).localize(); return (String) gz(key).localize();
} }
public static boolean isStreamlinedCreationActive(PageState state) { public static boolean isStreamlinedCreationActive(final PageState state) {
return ContentSection.getConfig().getUseStreamlinedCreation() return CMSConfig.getConfig().isUseStreamlinedCreation()
&& STREAMLINED_CREATION_ACTIVE.equals(state.getRequest(). && STREAMLINED_CREATION_ACTIVE.equals(state.getRequest().
getParameter(STREAMLINED_CREATION)); getParameter(STREAMLINED_CREATION));
} }
protected TabbedPane getTabbedPane() { protected TabbedPane getTabbedPane() {
return m_tabbedPane; return tabbedPane;
} }
protected WizardSelector getWizardPane() { protected WizardSelector getWizardPane() {
return m_wizardPane; return wizardPane;
} }
/** /**
* Adds the content type to the output. * Adds the content type to the output.
* *
* @param state PageState * @param state PageState
* @param parent Parent document * @param parent Parent document
* @return page * @return page
*/ */
protected Element generateXMLHelper(PageState state, Document parent) { @Override
Element page = super.generateXMLHelper(state, parent); protected Element generateXMLHelper(final PageState state,
Element contenttype = page.newChildElement("bebop:contentType", BEBOP_XML_NS); final Document parent) {
contenttype.setText(m_item.getContentItem(state).getContentType().getName()); final Element page = super.generateXMLHelper(state, parent);
final Element contenttype = page.newChildElement("bebop:contentType",
BEBOP_XML_NS);
contenttype.setText(itemRequestLocal
.getContentItem(state)
.getContentType()
.getLabel().getValue(KernelConfig.getConfig().getDefaultLocale()));
return page; return page;
} }

View File

@ -0,0 +1,394 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.FormSection;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.PropertyEditor;
import com.arsdigita.bebop.PropertyEditorModel;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.FormSubmissionListener;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.cms.dispatcher.Utilities;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.toolbox.ui.ComponentAccess;
import com.arsdigita.util.Assert;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.security.PermissionChecker;
import org.librecms.CmsConstants;
/**
* Extends {@link com.arsdigita.bebop.PropertyEditor} to provide access control
* features. Each link may be associated with a {@link
* com.arsdigita.toolbox.ui.ComponentAccess} object; if the current does not
* have sufficient privileges, the link will be hidden.
* <p>
* The simple use pattern for this component is as follows:
*
* <blockquote><pre><code>
* SecurityPropertyEditor editor = new SecurityPropertyEditor();
* editor.setDisplayComponent(new FooComponent());
* NameEditForm n = new NameEditForm();
* ComponentAccess ca1 = new ComponentAccess(n);
* ca1.addAccessCheck(WORKFLOW_ADMIN);
* ca1.addAccessCheck(CATEGORY_ADMIN);
* editor.add("name", "Edit Name", ca, n.getCancelButton());
* AddressEditForm a = new AddressEditForm();
* ComponentAccess ca2 = new ComponentAccess(a);
* editor.add("address", "Edit Address", ca2, a.getCancelButton());
* </code></pre></blockquote>
*
* @author Michael Pih (pihman@arsdigita.com)
* @author Stanislav Freidin (sfreidin@arsdigita.com)
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class SecurityPropertyEditor extends PropertyEditor {
private final Map<String, ComponentAccess> accessChecks;
/**
* Construct a new, empty <code>PropertyEditor</code>. The {@link
* #setDisplayComponent(Component)} method must be called before this
* component is locked.
*/
public SecurityPropertyEditor() {
this(null);
}
/**
* Construct a new, <code>PropertyEditor</code> with the given display
* component
*
* @param display The display component
*/
public SecurityPropertyEditor(final Component display) {
super(display);
accessChecks = new HashMap<>();
setModelBuilder(new AccessListModelBuilder());
}
/**
* Add a component to the property editor. The component will be completely
* invisible; it is up to the user to call {@link #showComponent(PageState,
* String)} to display the component, and to call {@link
* #showDisplayPane(PageState)} when the component needs to be hidden.
*
* @param key The symbolic key for the component; must be unique for this
* <code>PropertyEditor</code>
* @param componentAccess The {@link ComponentAccess} object which contains
* the child component, along with security restrictions
*/
public void addComponent(final String key,
final ComponentAccess componentAccess) {
super.addComponent(key, componentAccess.getComponent());
accessChecks.put(key, componentAccess);
}
/**
* Add a component to the list of links. It is up to the component to
* correctly call showDisplayPane when it's done.
*
* @param key The symbolic key for the component; must be unique for this
* <code>PropertyEditor</code>
* @param label The label for the link
* @param componentAccess The component access
* @deprecated use addComponent(String,GlobalizedMessage,ComponentAccess)
* instead.
*/
public void addComponent(final String key,
final String label,
final ComponentAccess componentAccess) {
addComponent(key, componentAccess);
getLabelsMap().put(key, label);
}
/**
* Add a component to the list of links. It is up to the component to
* correctly call showDisplayPane when it's done.
*
* @param key The symbolic key for the component; must be unique for this
* <code>PropertyEditor</code>
* @param label The label for the link
* @param componentAccess The component access
*/
public void addComponent(final String key,
final GlobalizedMessage label,
final ComponentAccess componentAccess) {
addComponent(key, componentAccess);
getLabelsMap().put(key, label);
}
/**
* Specify a new {@link ComponentAccess} for a component which has already
* been added to the <code>SecurityPropertyEditor</code>.
*
* @param key the key under which the component was added
* @param componentAccess the <code>ComponentAccess</code> instance that
* will determine when the link for the specified component should be
* visible
* @pre access.getComponent() == m_forms.get(key)
*/
public void setComponentAccess(final String key,
final ComponentAccess componentAccess) {
Assert.isUnlocked(this);
final Component component = getComponent(key);
Assert.exists(component, "the specified component");
Assert.isTrue(componentAccess.getComponent().equals(component),
"The specified component does not match the component that"
+ " id already in the PropertyEditor");
accessChecks.put(key, componentAccess);
}
/**
* Add a form to the set of forms which could be used to edit the
* properties.
*
* @param key The symbolic key for the form; must be unique for this
* <code>PropertyEditor</code>
* @param label The label for the link to access the form
* @param componentAccess The form ComponentAccess
*
* @deprecated use add(String,GlobalizedMessage,ComponentAccess)
*/
public void add(final String key,
final String label,
final ComponentAccess componentAccess) {
final Component component = componentAccess.getComponent();
if (component instanceof Form) {
final Form form = (Form) component;
accessChecks.put(key, componentAccess);
add(key, label, form);
addSecurityListener(form);
} else if (component instanceof FormSection) {
final FormSection section = (FormSection) componentAccess.
getComponent();
accessChecks.put(key, componentAccess);
add(key, label, section);
addSecurityListener(section);
} else {
throw new IllegalArgumentException(
"The ComponentAccess object does "
+ "not contain a form section.");
}
}
/**
* Add a form to the set of forms which could be used to edit the
* properties.
*
* @param key The symbolic key for the form; must be unique for this
* <code>PropertyEditor</code>
* @param label The label for the link to access the form
* @param componentAccess The form ComponentAccess
*/
public void add(final String key,
final GlobalizedMessage label,
final ComponentAccess componentAccess) {
final Component component = componentAccess.getComponent();
if (component instanceof Form) {
final Form form = (Form) component;
accessChecks.put(key, componentAccess);
add(key, label, form);
addSecurityListener(form);
} else if (component instanceof FormSection) {
final FormSection section = (FormSection) componentAccess.
getComponent();
accessChecks.put(key, componentAccess);
add(key, label, section);
addSecurityListener(section);
} else {
throw new IllegalArgumentException(
"The ComponentAccess object does "
+ "not contain a form section.");
}
}
/**
* Add a form to the set of forms which could be used to edit the properties
*
* @param key The symbolic key for the form; must be unique for this
* <code>PropertyEditor</code>
* @param label The label for the link to access the form.
* @param componentAccess The form ComponentAccess
* @param cancelButton The Cancel button on the form.
*
* @deprecated use add(String,GlobalizedMessage,ComponentAccess,Submit)
* instead
*/
public void add(final String key,
final String label,
final ComponentAccess componentAccess,
final Submit cancelButton) {
add(key, label, componentAccess);
addCancelListener((FormSection) componentAccess.getComponent(),
cancelButton);
}
/**
* Add a form to the set of forms which could be used to edit the properties
*
* @param key The symbolic key for the form; must be unique for this
* <code>PropertyEditor</code>
* @param label The label for the link to access the form.
* @param componentAccess The form ComponentAccess
* @param cancelButton The Cancel button on the form.
*/
public void add(final String key,
final GlobalizedMessage label,
final ComponentAccess componentAccess,
final Submit cancelButton) {
add(key, label, componentAccess);
addCancelListener((FormSection) componentAccess.getComponent(),
cancelButton);
}
/**
* Add a submission listener to the form that will hide all components and
* show the display pane. This method should be used to add submission
* listeners to forms which are buried deep inside some component, and are
* not members of this <code>PropertyEditor</code>.
*
* @param form The form
*/
public void addSecurityListener(final FormSection form) {
form.addSubmissionListener(new FormSubmissionListener() {
@Override
public void submitted(final FormSectionEvent event) throws
FormProcessException {
final PageState state = event.getPageState();
// Cancel the form if the user does not pass the access checks.
final String key = (String) getList().getSelectedKey(state);
final ComponentAccess componentAccess
= (ComponentAccess) accessChecks.get(key);
if (key == null || componentAccess == null) {
// no components currently selected and therefore
// no access checks to run for visibility
// or
// there are no access restrictions on the form
return;
}
if (!componentAccess.canAccess()) {
showDisplayPane(state);
throw new FormProcessException(new GlobalizedMessage(
"cms.ui.insufficient_privileges",
CmsConstants.CMS_BUNDLE));
}
}
});
}
/**
* Add all required listeners to the form to ensure that if the form is
* submitted successfully or cancelled, the display pane will be shown. This
* method should be used to add listeners to forms which are buried deep
* inside some component, and are not members of this
* <code>PropertyEditor</code>.
*
* @param form The form
* @param cancelButton the "Cancel" button on the form
*/
@Override
public void addListeners(final FormSection form,
final Submit cancelButton) {
addSecurityListener(form);
super.addListeners(form, cancelButton);
}
/**
* Return the map of keys to access checks
*
* @return Map of keys to access check
*/
protected final Map<String, ComponentAccess> getAccessMap() {
return accessChecks;
}
/**
* Returns an {@link SecurityPropertyEditor.AccessListModel} during each
* request
*/
protected static class AccessListModelBuilder extends DefaultModelBuilder {
public AccessListModelBuilder() {
super();
}
@Override
public PropertyEditorModel makeModel(
final PropertyEditor propertyEditor, final PageState state) {
return new AccessListModel(
getProperties(propertyEditor),
((SecurityPropertyEditor) propertyEditor).getAccessMap(),
state);
}
}
/**
* Performs access checks for each property; skips the properties that the
* user is not allowed to access
*/
protected static class AccessListModel extends DefaultModel {
private final Map<String, ComponentAccess> accessMap;
private final PageState state;
public AccessListModel(final Iterator iter,
final Map<String, ComponentAccess> accessMap,
final PageState state) {
super(iter);
this.accessMap = accessMap;
this.state = state;
}
@Override
public boolean next() {
while (super.next()) {
final Object key = getKey();
final ComponentAccess ca = accessMap.get(key.toString());
if (ca == null) {
return true;
}
if (ca.canAccess()) {
return true;
}
// Otherwise, skip the property
}
return false;
}
}
}

View File

@ -43,6 +43,7 @@ import com.arsdigita.cms.ui.authoring.LanguageWidget;
import org.librecms.util.LanguageUtil; import org.librecms.util.LanguageUtil;
import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.kernel.KernelConfig;
import com.arsdigita.toolbox.ui.ActionGroup; import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.toolbox.ui.LayoutPanel; import com.arsdigita.toolbox.ui.LayoutPanel;
import com.arsdigita.toolbox.ui.Section; import com.arsdigita.toolbox.ui.Section;
@ -60,8 +61,11 @@ import org.librecms.contentsection.ContentItemL10NManager;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.TooManyListenersException; import java.util.TooManyListenersException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.libreccm.configuration.ConfigurationManager;
import org.librecms.CmsConstants;
/** /**
* Displays the "Language instances" pane, with all the language instances in * Displays the "Language instances" pane, with all the language instances in
@ -81,10 +85,10 @@ public class ItemLanguages extends LayoutPanel {
/** /**
* Constructs a new <code>ItemLanguages</code>. * Constructs a new <code>ItemLanguages</code>.
* *
* @param selectionModel the {@link ItemSelectionModel} which will supply * @param selectionModel the {@link ItemSelectionModel} which will supply
* the current item * the current item
* @param selectedLanguage {@link SingleSelectionModel} for the selected * @param selectedLanguage {@link SingleSelectionModel} for the selected
* language. * language.
*/ */
public ItemLanguages(final ItemSelectionModel selectionModel, public ItemLanguages(final ItemSelectionModel selectionModel,
final SingleSelectionModel<String> selectedLanguage) { final SingleSelectionModel<String> selectedLanguage) {
@ -141,22 +145,22 @@ public class ItemLanguages extends LayoutPanel {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final LanguageUtil languageUtil = cdiUtil.findBean( final LanguageUtil languageUtil = cdiUtil.findBean(
LanguageUtil.class); LanguageUtil.class);
final ContentItemL10NManager l10NManager = cdiUtil.findBean( final ContentItemL10NManager l10NManager = cdiUtil.findBean(
ContentItemL10NManager.class); ContentItemL10NManager.class);
final List<String> creatableLangs = l10NManager.creatableLocales( final List<String> creatableLangs = l10NManager.creatableLocales(
item).stream() item).stream()
.map(locale -> locale.toString()) .map(locale -> locale.toString())
.collect(Collectors.toList()); .collect(Collectors.toList());
final List<Pair> languages = languageUtil.convertToG11N( final List<Pair> languages = languageUtil.convertToG11N(
creatableLangs); creatableLangs);
for(final Pair pair : languages) { for (final Pair pair : languages) {
final String langCode = (String) pair.getKey(); final String langCode = (String) pair.getKey();
final GlobalizedMessage langName final GlobalizedMessage langName
= (GlobalizedMessage) pair = (GlobalizedMessage) pair
.getValue(); .getValue();
optionGroup.addOption(new Option(langCode, new Label(langName))); optionGroup.addOption(new Option(langCode, new Label(langName)));
} }
} }
@ -170,64 +174,46 @@ public class ItemLanguages extends LayoutPanel {
@Override @Override
public final void process(final FormSectionEvent event) public final void process(final FormSectionEvent event)
throws FormProcessException { throws FormProcessException {
PageState state = event.getPageState();
String lang = (String) languageWidget.getValue(state); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
ContentPage item = (ContentPage) selectionModel.getSelectedItem(
state); final PageState state = event.getPageState();
ContentBundle bundle = item.getContentBundle(); final String lang = (String) languageWidget.getValue(state);
String name = bundle.getName(); final ContentItem item = (ContentItem) selectionModel
.getSelectedItem(state);
final ConfigurationManager confManager = cdiUtil.findBean(
ConfigurationManager.class);
final KernelConfig kernelConfig = confManager.findConfiguration(
KernelConfig.class);
final Locale defaultLocale = kernelConfig.getDefaultLocale();
final String name = item.getName().getValue(defaultLocale);
if (createSubmit.isSelected(state)) { if (createSubmit.isSelected(state)) {
ContentSection section = item.getContentSection(); final ContentSection section = item.getContentType().
getContentSection();
Assert.exists(section, ContentSection.class); Assert.exists(section, ContentSection.class);
ContentType type = item.getContentType(); final ContentItemL10NManager l10NManager = cdiUtil.findBean(
ContentItemL10NManager.class);
item = (ContentPage) item.copy(lang); l10NManager.addLanguage(item, new Locale(lang));
item.setLanguage(lang);
item.setName(name);
// Apply default workflow
WorkflowTemplate template
= ContentTypeWorkflowTemplate
.getWorkflowTemplate(section, type);
if (template != null) {
Workflow w = template.instantiateNewWorkflow();
w.setObjectID(item.getID());
w.start(Kernel.getContext().getUser());
w.save();
}
selectionModel.setSelectedObject(state, item);
// redirect to ContentItemPage.AUTHORING_TAB of the new instance // redirect to ContentItemPage.AUTHORING_TAB of the new instance
final String target = URL.getDispatcherPath() + ContentItemPage. final String target = String.join(
getItemURL(item, "", URL.getDispatcherPath(),
ContentItemPage.AUTHORING_TAB); ContentItemPage.getItemURL(item,
ContentItemPage.AUTHORING_TAB));
throw new RedirectSignal(target, true); throw new RedirectSignal(target, true);
} else if (changeSubmit.isSelected(state)) { }
String oldLang = item.getLanguage();
item.setLanguage(lang);
// propagate language change to the Name attribute
item.setName(name);
item.save();
// if the item being changed is the default, update the bundle
// to keep this item as the default
if (bundle.getDefaultLanguage().equals(oldLang)) {
bundle.setDefaultLanguage(lang);
bundle.save();
}
}
} }
} }
protected static final GlobalizedMessage gz(final String key) { protected static final GlobalizedMessage gz(final String key) {
return GlobalizationUtil.globalize(key); return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE);
} }
protected static final String lz(final String key) { protected static final String lz(final String key) {

View File

@ -164,7 +164,7 @@ public class ItemLanguagesTable extends Table {
final ContentItemL10NManager l10nManager = cdiUtil.findBean( final ContentItemL10NManager l10nManager = cdiUtil.findBean(
ContentItemL10NManager.class); ContentItemL10NManager.class);
l10nManager.removeLangauge(item, new Locale(selectedLang)); l10nManager.removeLanguage(item, new Locale(selectedLang));
} }
@Override @Override

View File

@ -0,0 +1,455 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.item;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import com.arsdigita.bebop.PageState;
import com.arsdigita.categorization.Category;
import com.arsdigita.categorization.CategoryCollection;
import com.arsdigita.cms.CMS;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.ContentPage;
import com.arsdigita.cms.ContentSection;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.SecurityManager;
import com.arsdigita.cms.dispatcher.CMSDispatcher;
import com.arsdigita.cms.lifecycle.Lifecycle;
import com.arsdigita.cms.ui.CMSContainer;
import com.arsdigita.cms.util.SecurityConstants;
import com.arsdigita.cms.workflow.CMSEngine;
import com.arsdigita.cms.workflow.CMSTask;
import com.arsdigita.domain.DataObjectNotFoundException;
import com.arsdigita.domain.DomainServiceInterfaceExposer;
import com.arsdigita.kernel.ACSObject;
import com.arsdigita.kernel.User;
import com.arsdigita.kernel.permissions.PermissionDescriptor;
import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.persistence.Filter;
import com.arsdigita.toolbox.ui.FormatStandards;
import com.arsdigita.util.Assert;
import com.arsdigita.util.GraphSet;
import com.arsdigita.util.Graphs;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.versioning.Transaction;
import com.arsdigita.versioning.TransactionCollection;
import com.arsdigita.versioning.Versions;
import com.arsdigita.web.RedirectSignal;
import com.arsdigita.web.Web;
import com.arsdigita.web.WebContext;
import com.arsdigita.workflow.simple.Engine;
import com.arsdigita.workflow.simple.Task;
import com.arsdigita.workflow.simple.TaskCollection;
import com.arsdigita.workflow.simple.TaskComment;
import com.arsdigita.workflow.simple.Workflow;
import com.arsdigita.workflow.simple.WorkflowTemplate;
import com.arsdigita.xml.Element;
import java.io.UnsupportedEncodingException;
/**
* <p>
* This panel displays basic details about a content item such as attributes and associations.</p>
*
* <p>
* Container: {@link com.arsdigita.cms.ui.ContentItemPage}
*
* <p>
* This panel uses an {@link com.arsdigita.cms.dispatcher.XMLGenerator} to convert content items
* into XML.</p>
*
* @author Michael Pih (pihman@arsdigita.com)
* @version $Id: Summary.java 1940 2009-05-29 07:15:05Z terry $
*/
public class Summary extends CMSContainer {
private static final String SUMMARY = "itemAdminSummary";
private static final String RESTART_WORKFLOW = "restartWorkflow";
private final ItemSelectionModel m_item;
public Summary(ItemSelectionModel m) {
super();
m_item = m;
}
/**
* Generate XML representation of an item summary.
*
* @param state The page state
* @param parent The parent DOM element
*
* @pre ( state != null )
* @pre ( parent != null )
*/
@Override
public void generateXML(PageState state, Element parent) {
if (isVisible(state)) {
// Determine the item's environment
ContentItem item = getContentItem(state);
ContentSection section = getContentSection(state);
User user = Web.getWebContext().getUser();
// Setup xml element for item's properties
Element itemElement = new Element("cms:itemSummary", CMS.CMS_XML_NS);
// Determine item's name / url stub
itemElement.addAttribute("name", item.getName());
// obviously getName() here gets the 'semantically meaningful name'
// from database using class DataType. It is not localizable! And
// it is not really 'semantically meaningful'
String objectType = item.getObjectType().getName();
// Quasimodo: ObjectType for summary
itemElement.addAttribute("objectType", objectType);
// NOT USED - CUSTOMIZED SUMMARY
// Take advantage of caching in the CMS Dispatcher.
// XMLGenerator xmlGenerator = section.getXMLGenerator();
// xmlGenerator.generateXML(state, parent, SUMMARY);
String descriptionAttribute = "";
if (objectType.equals("NewsItem") || objectType.equals("Article")) {
descriptionAttribute = "lead";
} else if (objectType.equals("FileStorageItem") || objectType.equals("Minutes")) {
descriptionAttribute = "description";
} else if (objectType.equals("Job")) {
descriptionAttribute = "jobDescription";
} else if (objectType.equals("MultiPartArticle") || objectType.equals("Agenda")
|| objectType.equals("PressRelease") || objectType.equals("Service")) {
descriptionAttribute = "summary";
}
if (!descriptionAttribute.equals("")) {
itemElement.addAttribute("description", (String) DomainServiceInterfaceExposer.get(
item, descriptionAttribute));
}
try {
ContentPage page = new ContentPage(item.getID());
itemElement.addAttribute("title", page.getTitle());
} catch (DataObjectNotFoundException ex) {
//
}
// subject category
Element subjectsElement = new Element("cms:subjectCategories", CMS.CMS_XML_NS);
itemElement.addContent(subjectsElement);
Category itemCategory = null;
Category subjectCategory = Category.getRootForObject(section, "subject");
if (subjectCategory != null) {
CategoryCollection categories = item.getCategoryCollection();
while (categories.next()) {
Category category = categories.getCategory();
CategoryCollection parents = category.getDefaultAscendants();
parents.addOrder(Category.DEFAULT_ANCESTORS);
if (parents.next()) {
Category parentCategory = parents.getCategory();
if (parentCategory.equals(subjectCategory)) {
Element subjectElement = new Element("cms:subjectCategory",
CMS.CMS_XML_NS);
subjectElement.addAttribute("name", category.getName());
subjectElement.setText(category.getPreferredQualifiedName(" -&gt; ",
true));
subjectsElement.addContent(subjectElement);
}
parents.close();
}
}
}
// URL
Element linkElement = new Element("cms:linkSummary", CMS.CMS_XML_NS);
try {
linkElement.addAttribute("url",
String.format("%s/redirect?oid=%s",
Web.getWebappContextPath(),
URLEncoder.encode(item.getDraftVersion()
.getOID()
.toString(), "utf-8")));
} catch (UnsupportedEncodingException ex) {
throw new UncheckedWrapperException(ex);
}
//"/redirect?oid=" + URLEncoder.encode(item.getDraftVersion().getOID().toString()));
// WORKFLOW
Element workflowElement = new Element("cms:workflowSummary", CMS.CMS_XML_NS);
Workflow workflow = Workflow.getObjectWorkflow(item);
SecurityManager sm = CMS.getContext().getSecurityManager();
if (canWorkflowBeExtended(user, item, workflow)) {
// control event for restarting workflow in edit mode
try {
state.setControlEvent(this, RESTART_WORKFLOW, item.getID().toString());
workflowElement.addAttribute("restartWorkflowURL", state.stateAsURL());
state.clearControlEvent();
} catch (java.io.IOException ex) {
//
}
}
if (workflow == null) {
workflowElement.addAttribute("noWorkflow", "1");
} else {
workflowElement.addAttribute("name", workflow.getDisplayName());
TaskCollection tc = workflow.getTaskCollection();
GraphSet g = new GraphSet();
while (tc.next()) {
Task t = tc.getTask();
final TaskCollection deps = t.getRequiredTasks();
final StringBuffer buffer = new StringBuffer();
while (deps.next()) {
Task dep = deps.getTask();
g.addEdge(t, dep, null);
buffer.append(dep.getLabel() + ", ");
}
final int len = buffer.length();
if (len >= 2) {
buffer.setLength(len - 2);
} else {
g.addNode(t);
}
deps.close();
}
List taskList = new ArrayList();
outer:
while (g.nodeCount() > 0) {
List l = Graphs.getSinkNodes(g);
for (Iterator it = l.iterator(); it.hasNext();) {
Task t = (Task) it.next();
taskList.add(0, t);
g.removeNode(t);
continue outer;
}
// break loop if no nodes removed
break;
}
Iterator tasks = taskList.iterator();
while (tasks.hasNext()) {
Task task = (Task) tasks.next();
Element taskElement = new Element("cms:task", CMS.CMS_XML_NS);
taskElement.addAttribute("name", task.getDisplayName());
taskElement.addAttribute("state", task.getStateString());
Iterator comments = task.getComments();
while (comments.hasNext()) {
TaskComment comment = (TaskComment) comments.next();
Element commentElement = new Element("cms:taskComment", CMS.CMS_XML_NS);
User author = comment.getUser();
String authorName = "Anonymous";
if (author != null) {
authorName = author.getDisplayName();
}
commentElement.addAttribute("author", authorName);
commentElement.addAttribute("comment", comment.getComment());
commentElement.addAttribute("date", FormatStandards.formatDate(comment
.getDate()));
taskElement.addContent(commentElement);
}
workflowElement.addContent(taskElement);
}
}
// REVISION HISTORY
Element transactionElement = new Element("cms:transactionSummary", CMS.CMS_XML_NS);
transactionElement.addAttribute("creationDate", FormatStandards.formatDate(item
.getCreationDate()));
transactionElement.addAttribute("lastModifiedDate", FormatStandards.formatDate(item
.getLastModifiedDate()));
TransactionCollection transactions = Versions.getTaggedTransactions(item.getOID());
while (transactions.next()) {
Transaction transaction = transactions.getTransaction();
Element element = new Element("cms:transaction", CMS.CMS_XML_NS);
element.addAttribute("date", FormatStandards.formatDate(transaction.getTimestamp()));
String authorName = "Anonymous";
User author = transaction.getUser();
if (author != null) {
authorName = author.getDisplayName();
}
element.addAttribute("author", authorName);
String url = section.getItemResolver().generateItemURL(state, item, section,
CMSDispatcher.PREVIEW)
+ "?transID=" + transaction.getID();
element.addAttribute("url", url);
transactionElement.addContent(element);
}
transactions.close();
// CATEGORY
Element categoryElement = new Element("cms:categorySummary", CMS.CMS_XML_NS);
CategoryCollection categories = item.getCategoryCollection();
while (categories.next()) {
Category category = categories.getCategory();
Element element = new Element("cms:category", CMS.CMS_XML_NS);
element.setText(category.getPreferredQualifiedName(" -&gt; ", true));
categoryElement.addContent(element);
}
categories.close();
// LIFECYCLE
Element lifecycleElement = new Element("cms:lifecycleSummary", CMS.CMS_XML_NS);
Lifecycle lifecycle = item.getLifecycle();
if (lifecycle == null) {
lifecycleElement.addAttribute("noLifecycle", "1");
} else {
lifecycleElement.addAttribute("name", lifecycle.getLabel());
lifecycleElement.addAttribute("startDate", FormatStandards.formatDate(lifecycle
.getStartDate()));
java.util.Date endDate = lifecycle.getEndDate();
if (endDate == null) {
lifecycleElement.addAttribute("endDateString", "last forever");
} else {
lifecycleElement.addAttribute("endDateString", "expire on " + FormatStandards
.formatDate(endDate));
lifecycleElement.addAttribute("endDate", FormatStandards.formatDate(endDate));
}
lifecycleElement.addAttribute("hasBegun", (new Boolean(lifecycle.hasBegun()))
.toString());
lifecycleElement.addAttribute("hasEnded", (new Boolean(lifecycle.hasEnded()))
.toString());
}
parent.addContent(itemElement);
parent.addContent(categoryElement);
parent.addContent(linkElement);
parent.addContent(lifecycleElement);
parent.addContent(workflowElement);
parent.addContent(transactionElement);
}
}
/**
* Fetch the selected content item.
*
* @param state The page state
*
* @return The selected item
*
* @pre ( state != null )
*/
protected ContentItem getContentItem(PageState state) {
ContentItem item = (ContentItem) m_item.getSelectedObject(state);
Assert.exists(item);
return item;
}
/**
* Fetch the current content section.
*
* @param state The page state
*
* @return The content section
*
* @pre ( state != null )
*/
protected ContentSection getContentSection(PageState state) {
ContentSection section = CMS.getContext().getContentSection();
return section;
}
public void respond(PageState state) throws ServletException {
String key = state.getControlEventName();
String value = state.getControlEventValue();
if (RESTART_WORKFLOW.equals(key)) {
User user = Web.getWebContext().getUser();
ContentItem item = getContentItem(state);
ContentSection section = item.getContentSection();
Workflow w = Workflow.getObjectWorkflow(item);
if (canWorkflowBeExtended(user, item, w)) {
WorkflowTemplate template = w.getWorkflowTemplate();
if (template != null) {
template.extendWorkflow(w);
w.save();
}
// lock the next task
Engine engine = Engine.getInstance(CMSEngine.CMS_ENGINE_TYPE);
Iterator i = engine.getEnabledTasks(user, w.getID()).iterator();
if (i.hasNext()) {
CMSTask task = (CMSTask) i.next();
if (!task.isLocked()) {
task.lock(user);
}
}
}
String redirectURL = Web.getConfig().getDispatcherServletPath() + item
.getContentSection().getPath() + "/admin/item.jsp?item_id=" + item.getID()
+ "&set_tab=1";
throw new RedirectSignal(redirectURL, true);
} else {
throw new ServletException("Unknown control event: " + key);
}
}
/*
* Checks if workflow can be extended
*/
protected boolean canWorkflowBeExtended(User user, ContentItem item, Workflow workflow) {
boolean canBeExtended = true;
if (workflow == null) {
canBeExtended = false;
} else if (!workflow.isFinished()) {
canBeExtended = false;
} else if (workflow.getWorkflowTemplate() == null) {
canBeExtended = false;
} else {
TaskCollection templates = item.getContentSection().getWorkflowTemplates();
Filter f = templates.addInSubqueryFilter("id",
"com.arsdigita.cms.getWorkflowTemplateUserFilter");
f.set("userId", Web.getWebContext().getUser().getID());
templates.addEqualsFilter(ACSObject.ID, workflow.getWorkflowTemplate().getID());
PrivilegeDescriptor pd = PrivilegeDescriptor.get(SecurityConstants.CMS_WORKFLOW_ADMIN);
PermissionDescriptor perm = new PermissionDescriptor(pd, item, user);
if (!(templates.next() || PermissionService.checkPermission(perm))) {
canBeExtended = false;
}
templates.close();
}
return canBeExtended;
}
}

View File

@ -0,0 +1,210 @@
/*
* 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.ControlLink;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.categorization.Category;
import com.arsdigita.categorization.CategoryCollection;
import com.arsdigita.cms.CMS;
import com.arsdigita.cms.CMSConfig;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.lifecycle.Lifecycle;
import com.arsdigita.cms.ui.BaseItemPane;
import com.arsdigita.cms.ui.ContentItemPage;
import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
import com.arsdigita.toolbox.ui.LayoutPanel;
import com.arsdigita.web.RedirectSignal;
import com.arsdigita.web.URL;
import org.apache.log4j.Logger;
/**
* @author Michael Pih
* @author Jack Chung
* @author Justin Ross &lt;jross@redhat.com&gt;
* @author Jens Pelzetter jens@jp-digital.de
* @version $Id: ItemLifecycleAdminPane.java 1942 2009-05-29 07:53:23Z terry $
*/
public class ItemLifecycleAdminPane extends BaseItemPane {
private static final Logger s_log = Logger.getLogger(
ItemLifecycleAdminPane.class);
private final ContentItemRequestLocal m_item;
private final LifecycleRequestLocal m_lifecycle;
private final LayoutPanel m_introPane;
private final LayoutPanel m_detailPane;
private final LayoutPanel m_selectPane;
private final LayoutPanel m_lockedPane;
private final LayoutPanel m_errorPane;
private final LayoutPanel m_cantPublishPane;
public ItemLifecycleAdminPane(final ContentItemRequestLocal item) {
m_item = item;
m_lifecycle = new ItemLifecycleRequestLocal();
m_introPane = new LayoutPanel();
add(m_introPane);
final Label message = new Label(gz("cms.ui.item.lifecycle.intro"));
m_introPane.setBody(message);
m_detailPane = new LayoutPanel();
add(m_detailPane);
final ItemLifecycleItemPane itemPane =
new ItemLifecycleItemPane(m_item,
m_lifecycle);
m_detailPane.setBody(itemPane);
m_selectPane = new LayoutPanel();
add(m_selectPane);
final ItemLifecycleSelectForm selectForm =
new ItemLifecycleSelectForm(m_item);
m_selectPane.setBody(selectForm);
m_lockedPane = new LayoutPanel();
add(m_lockedPane);
final Label lockedMsg = new Label(gz(
"cms.ui.item.lifecycle.publish_locked"));
m_lockedPane.setBody(lockedMsg);
final ControlLink lockedUpdateLink = new ControlLink(new Label(gz(
"cms.ui.item.lifecycle.publish_locked.update")));
lockedUpdateLink.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent event) {
throw new RedirectSignal(
URL.getDispatcherPath()
+ ContentItemPage.getItemURL(
item.getContentItem(event.getPageState()),
ContentItemPage.PUBLISHING_TAB),
true);
}
});
m_lockedPane.setBottom(lockedUpdateLink);
m_errorPane = new LayoutPanel();
add(m_errorPane);
final Label errorMsg = new Label(gz("cms.ui.lifecycle.publish.error"));
m_errorPane.setBody(errorMsg);
m_cantPublishPane = new LayoutPanel();
add(m_cantPublishPane);
final Label cantPublish = new Label(gz("cms.ui.lifecycle.publish.not_possible_abstract_category"));
m_cantPublishPane.setBody(cantPublish);
connect(selectForm, m_detailPane);
}
private class ItemLifecycleRequestLocal extends LifecycleRequestLocal {
protected final Object initialValue(final PageState state) {
final ContentItem item = m_item.getContentItem(state);
final Lifecycle lifecycle = item.getLifecycle();
s_log.debug("Returning lifecycle " + lifecycle);
return lifecycle;
}
}
public final void register(final Page page) {
super.register(page);
page.addActionListener(new VisibilityListener());
}
private class VisibilityListener implements ActionListener {
public final void actionPerformed(final ActionEvent e) {
s_log.debug("Determining which pane to show");
final PageState state = e.getPageState();
if (CMSConfig.getInstanceOf().getThreadedPublishing()
&& PublishLock.getInstance().isLocked(m_item.getContentItem(
state))) {
if (PublishLock.getInstance().hasError(m_item.getContentItem(
state))) {
push(state, m_errorPane);
} else {
push(state, m_lockedPane);
state.getResponse().addIntHeader("Refresh", 5);
}
} else if(isAssignedToAbstractCategory(m_item.getContentItem(state))) {
push(state, m_cantPublishPane);
} else {
if (state.isVisibleOnPage(ItemLifecycleAdminPane.this)) {
if (m_lifecycle.getLifecycle(state) == null) {
if (hasPermission(state)) {
push(state, m_selectPane);
} else {
push(state, m_introPane);
}
} else {
push(state, m_detailPane);
}
}
}
}
}
private boolean hasPermission(final PageState state) {
final ContentItem item = m_item.getContentItem(state);
return CMS.getContext().getSecurityManager().canAccess(
state.getRequest(), SCHEDULE_PUBLICATION, item);
}
/**
* Checks if the item is assigned to an abstract category.
*
* A category is abstract if not items can assigned to it.
*
* @param item
* @return {@code true} if assigned to a abstract category, {@code false} if not.
*/
private boolean isAssignedToAbstractCategory(final ContentItem item) {
final CategoryCollection categories = item.getCategoryCollection();
boolean result = false;
Category category;
while(categories.next()) {
category = categories.getCategory();
if (category.isAbstract()) {
result = true;
break;
}
}
categories.close();
return result;
}
}

View File

@ -0,0 +1,316 @@
/*
* 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")));
}
}
}
}
}

View File

@ -0,0 +1,258 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.templates;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SegmentedPanel;
import com.arsdigita.bebop.SingleSelectionModel;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.event.TableActionAdapter;
import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.table.TableCellRenderer;
import com.arsdigita.bebop.table.TableColumn;
import com.arsdigita.cms.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.Template;
import com.arsdigita.cms.TemplateCollection;
import com.arsdigita.cms.TemplateManagerFactory;
import com.arsdigita.cms.ui.SecurityPropertyEditor;
import com.arsdigita.cms.ui.workflow.WorkflowLockedComponentAccess;
import com.arsdigita.toolbox.ui.LayoutPanel;
import com.arsdigita.util.Assert;
/**
* This component will eventually contain the full templates UI for
* content items. It is just a placeholder for now.
*
* @author Stanislav Freidin
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ItemTemplates extends SecurityPropertyEditor {
private ItemSelectionModel m_itemModel;
public static final String ASSIGN_TEMPLATE = "assignTemplate";
/**
* Construct a new ItemTemplates component
*
* @param model the <code>ItemSelectionModel</code> that will supply the
* current content item
*/
public ItemTemplates(ItemSelectionModel model) {
super();
m_itemModel = model;
ItemTemplatesListingImpl l = new ItemTemplatesListingImpl(model);
final LayoutPanel layout = new LayoutPanel();
setDisplayComponent(layout);
SegmentedPanel st = new SegmentedPanel();
layout.setBody(st);
st.addSegment(new Label(GlobalizationUtil.globalize("cms.ui.templates.assigned_templates")), l);
SegmentedPanel sa = new SegmentedPanel();
Label assignLabel = new Label(GlobalizationUtil.globalize("cms.ui.templates.dummy"));
assignLabel.addPrintListener(new PrintListener() {
public void prepare(PrintEvent e) {
PageState s = e.getPageState();
Label targetLabel = (Label)e.getTarget();
ContentPage item = (ContentPage)m_itemModel.getSelectedItem(s);
Assert.exists(item, "item");
targetLabel.setLabel( (String) GlobalizationUtil.globalize("cms.ui.templates.assign_a_template_to").localize() + item.getTitle());
}
});
sa.addSegment(assignLabel,
new AvailableTemplatesListing(l.getRowSelectionModel()));
addComponent(ASSIGN_TEMPLATE, sa);
}
/**
* Displays a list of templates which are currently assigned to
* the current item
*/
protected class ItemTemplatesListingImpl extends ItemTemplatesListing {
private WorkflowLockedComponentAccess m_access;
public ItemTemplatesListingImpl(ItemSelectionModel model) {
super(model);
m_access = new WorkflowLockedComponentAccess(null, model);
}
public void assignLinkClicked(PageState s,
ContentItem item,
String useContext) {
showComponent(s, ASSIGN_TEMPLATE);
}
public void register(Page p) {
super.register(p);
// Hide action columns if user has no access
p.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final PageState state = e.getPageState();
if (state.isVisibleOnPage(ItemTemplates.this)) {
if (m_access.canAccess
(state,
CMS.getContext().getSecurityManager())) {
getRemoveColumn().setVisible(state, true);
getAssignColumn().setVisible(state, true);
} else {
getRemoveColumn().setVisible(state, false);
getAssignColumn().setVisible(state, false);
}
}
}
});
}
}
/**
* Displays a list of templates for the given content item in the
* given context, along with a link to select a template
*/
protected class AvailableTemplatesListing extends TemplatesListing {
TableColumn m_assignCol;
SingleSelectionModel m_contextModel;
/**
* Construct a new AvailableTemplatesListing
*
* @param contextModel the SingleSelectionModel that will define the
* current use context
*/
public AvailableTemplatesListing(SingleSelectionModel contextModel) {
super();
m_contextModel = contextModel;
// Add the "assign" column and corresponding action listener
m_assignCol = addColumn("Assign",
TemplateCollection.TEMPLATE, false,
new AssignCellRenderer());
addTableActionListener(new TableActionAdapter() {
public void cellSelected(TableActionEvent e) {
PageState s = e.getPageState();
TemplatesListing l = (TemplatesListing)e.getSource();
int i = e.getColumn().intValue();
TableColumn c = l.getColumnModel().get(i);
// Safe to check pointer equality since the column is
// created statically
if(c == m_assignCol) {
SectionTemplateMapping m =
(SectionTemplateMapping)getMappingModel().getSelectedObject(s);
assignTemplate(s, m.getTemplate());
}
}
});
}
/**
* Get all the templates for the given context in the current section
*/
protected TemplateCollection getTemplateCollection(PageState s) {
ContentSection sec = CMS.getContext().getContentSection();
ContentItem item = m_itemModel.getSelectedItem(s);
Assert.exists(item, "item");
ContentType type = item.getContentType();
Assert.exists(type, "content type");
MimeType mimeType = getMimeType(s);
TemplateCollection c =
TemplateManagerFactory.getInstance().getTemplates(sec, type);
if (mimeType != null) {
c.addEqualsFilter(TemplateCollection.TEMPLATE + "." +
Template.MIME_TYPE + "." +
MimeType.MIME_TYPE, mimeType.getMimeType());
}
c.addEqualsFilter(TemplateCollection.USE_CONTEXT,
getUseContext(s));
return c;
}
// TODO: this is a 100% convoluted interdependent mess that
// really needs to be reworked
/**
* Get the currently selected use context
*/
protected String getUseContext(PageState s) {
String c = (String)m_contextModel.getSelectedKey(s);
Assert.exists(c, "use context");
return ItemTemplatesListing.getUseContextFromKey(c);
}
protected MimeType getMimeType(PageState s) {
String key = (String)m_contextModel.getSelectedKey(s);
return ItemTemplatesListing.getMimeTypeFromKey(key);
}
/**
* Assign a template to the current item
*/
public void assignTemplate(PageState s, Template t) {
ContentItem item = m_itemModel.getSelectedItem(s);
Assert.exists(item, "item");
TemplateManagerFactory.getInstance()
.addTemplate(item, t, getUseContext(s));
showDisplayPane(s);
}
/**
* Render the "assign" link
*/
protected class AssignCellRenderer implements TableCellRenderer {
private ControlLink m_link;
public AssignCellRenderer() {
m_link = new ControlLink
(new Label(GlobalizationUtil.globalize
("cms.ui.templates.assign_this_template")));
m_link.setClassAttr("assignTemplateLink");
}
public Component getComponent(Table table, PageState state, Object value,
boolean isSelected, Object key,
int row, int column) {
return m_link;
}
}
}
}

View File

@ -40,8 +40,6 @@ import org.libreccm.security.User;
import com.arsdigita.toolbox.ui.ActionGroup; import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.toolbox.ui.PropertyList; import com.arsdigita.toolbox.ui.PropertyList;
import com.arsdigita.toolbox.ui.Section; import com.arsdigita.toolbox.ui.Section;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.web.Web;
import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.security.Shiro; import org.libreccm.security.Shiro;
@ -49,48 +47,45 @@ import org.libreccm.workflow.Task;
import org.libreccm.workflow.TaskManager; import org.libreccm.workflow.TaskManager;
import org.libreccm.workflow.TaskRepository; import org.libreccm.workflow.TaskRepository;
import org.libreccm.workflow.Workflow; import org.libreccm.workflow.Workflow;
import org.libreccm.workflow.WorkflowManager;
import org.librecms.CmsConstants;
import org.librecms.contentsection.privileges.AdminPrivileges; import org.librecms.contentsection.privileges.AdminPrivileges;
import org.librecms.workflow.CmsTaskType; import org.librecms.workflow.CmsTaskType;
import java.math.BigDecimal;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
abstract class BaseWorkflowItemPane extends BaseItemPane { abstract class BaseWorkflowItemPane extends BaseItemPane {
final WorkflowRequestLocal m_workflow; final WorkflowRequestLocal workflowRequestLocal;
final TaskRequestLocal m_task; final TaskRequestLocal taskRequestLocal;
ActionGroup m_actionGroup; ActionGroup actionGroup;
final TaskTable m_tasks; final TaskTable taskTable;
final SimpleContainer m_detailPane; final SimpleContainer detailPane;
final TaskItemPane m_taskPane; final TaskItemPane taskItemPane;
final SummarySection m_summarySection; final SummarySection summarySection;
public BaseWorkflowItemPane(final WorkflowRequestLocal workflow, public BaseWorkflowItemPane(final WorkflowRequestLocal workflow,
final ActionLink editLink, final ActionLink editLink,
final ActionLink deleteLink) { final ActionLink deleteLink) {
m_workflow = workflow; workflowRequestLocal = workflow;
m_tasks = new TaskTable(); taskTable = new TaskTable();
m_task = new TaskSelectionRequestLocal(); taskRequestLocal = new TaskSelectionRequestLocal();
m_detailPane = new SimpleContainer(); detailPane = new SimpleContainer();
// Tasks // Tasks
final FinishLink taskFinishLink = new FinishLink(); final FinishLink taskFinishLink = new FinishLink();
final ActionLink taskAddLink = new ActionLink(new Label(gz( final ActionLink taskAddLink = new ActionLink(new Label(gz(
"cms.ui.workflow.task.add"))); "cms.ui.workflow.task.add")));
final TaskAddForm taskAddForm = new TaskAddForm(m_workflow, m_tasks final TaskAddForm taskAddForm = new TaskAddForm(workflowRequestLocal, taskTable
.getRowSelectionModel()); .getRowSelectionModel());
final ActionLink taskEditLink = new ActionLink(new Label(gz( final ActionLink taskEditLink = new ActionLink(new Label(gz(
"cms.ui.workflow.task.edit"))); "cms.ui.workflow.task.edit")));
final TaskEditForm taskEditForm = new TaskEditForm(m_workflow, m_task); final TaskEditForm taskEditForm = new TaskEditForm(workflowRequestLocal, taskRequestLocal);
final ActionLink taskDeleteLink = new ActionLink(new Label(gz( final ActionLink taskDeleteLink = new ActionLink(new Label(gz(
"cms.ui.workflow.task.delete"))); "cms.ui.workflow.task.delete")));
@ -100,31 +95,31 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
"cms.ui.workflow.task.return"))); "cms.ui.workflow.task.return")));
backLink.addActionListener(new ResetListener()); backLink.addActionListener(new ResetListener());
m_taskPane = new TaskItemPane(m_workflow, m_task, taskItemPane = new TaskItemPane(workflowRequestLocal, taskRequestLocal,
taskFinishLink, taskEditLink, taskFinishLink, taskEditLink,
taskDeleteLink, backLink); taskDeleteLink, backLink);
m_summarySection = new SummarySection(editLink, deleteLink); summarySection = new SummarySection(editLink, deleteLink);
m_detailPane.add(m_summarySection); detailPane.add(summarySection);
m_detailPane.add(new TaskSection(taskAddLink)); detailPane.add(new TaskSection(taskAddLink));
add(m_detailPane); add(detailPane);
setDefault(m_detailPane); setDefault(detailPane);
add(m_taskPane); add(taskItemPane);
add(taskAddForm); add(taskAddForm);
add(taskEditForm); add(taskEditForm);
add(taskDeleteForm); add(taskDeleteForm);
connect(m_tasks, 0, m_taskPane); connect(taskTable, 0, taskItemPane);
connect(taskAddLink, taskAddForm); connect(taskAddLink, taskAddForm);
connect(taskAddForm, m_taskPane); connect(taskAddForm, taskItemPane);
connect(taskEditLink, taskEditForm); connect(taskEditLink, taskEditForm);
connect(taskEditForm); connect(taskEditForm);
connect(taskDeleteLink, taskDeleteForm); connect(taskDeleteLink, taskDeleteForm);
connect(taskDeleteForm, m_detailPane); connect(taskDeleteForm, detailPane);
} }
protected class AdminVisible extends VisibilityComponent { protected class AdminVisible extends VisibilityComponent {
@ -146,7 +141,7 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
@Override @Override
public final boolean isVisible(final PageState state) { public final boolean isVisible(final PageState state) {
final CmsTask task = m_task.getTask(state); final CmsTask task = taskRequestLocal.getTask(state);
final User lockingUser = task.getLockingUser(); final User lockingUser = task.getLockingUser();
final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final Shiro shiro = cdiUtil.findBean(Shiro.class); final Shiro shiro = cdiUtil.findBean(Shiro.class);
@ -165,7 +160,7 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final TaskManager taskManager = cdiUtil.findBean(TaskManager.class); final TaskManager taskManager = cdiUtil.findBean(TaskManager.class);
final Task task = m_task.getTask(state); final Task task = taskRequestLocal.getTask(state);
taskManager.finish(task); taskManager.finish(task);
} }
@ -177,7 +172,7 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
public void reset(final PageState state) { public void reset(final PageState state) {
super.reset(state); super.reset(state);
m_tasks.getRowSelectionModel().clearSelection(state); taskTable.getRowSelectionModel().clearSelection(state);
} }
private class TaskDeleteForm extends BaseDeleteForm { private class TaskDeleteForm extends BaseDeleteForm {
@ -197,10 +192,10 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
final TaskRepository taskRepo = cdiUtil.findBean( final TaskRepository taskRepo = cdiUtil.findBean(
TaskRepository.class); TaskRepository.class);
final Task task = m_task.getTask(state); final Task task = taskRequestLocal.getTask(state);
taskRepo.delete(task); taskRepo.delete(task);
m_tasks.getRowSelectionModel().clearSelection(state); taskTable.getRowSelectionModel().clearSelection(state);
} }
} }
@ -209,7 +204,7 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
@Override @Override
protected final Object initialValue(final PageState state) { protected final Object initialValue(final PageState state) {
final String key = m_tasks.getRowSelectionModel().getSelectedKey( final String key = taskTable.getRowSelectionModel().getSelectedKey(
state).toString(); state).toString();
return CmsTaskType.valueOf(key); return CmsTaskType.valueOf(key);
@ -223,13 +218,13 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
final ActionLink deleteLink) { final ActionLink deleteLink) {
setHeading(new Label(gz("cms.ui.workflow.details"))); setHeading(new Label(gz("cms.ui.workflow.details")));
m_actionGroup = new ActionGroup(); actionGroup = new ActionGroup();
setBody(m_actionGroup); setBody(actionGroup);
m_actionGroup.setSubject(new Properties()); actionGroup.setSubject(new Properties());
m_actionGroup.addAction(new AdminVisible(editLink), actionGroup.addAction(new AdminVisible(editLink),
ActionGroup.EDIT); ActionGroup.EDIT);
m_actionGroup.addAction(new AdminVisible(deleteLink), actionGroup.addAction(new AdminVisible(deleteLink),
ActionGroup.DELETE); ActionGroup.DELETE);
} }
@ -239,7 +234,7 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
protected final List<Property> properties(final PageState state) { protected final List<Property> properties(final PageState state) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final List<Property> props = super.properties(state); final List<Property> props = super.properties(state);
final Workflow workflow = (Workflow) m_workflow.get(state); final Workflow workflow = (Workflow) workflowRequestLocal.get(state);
final KernelConfig kernelConfig = KernelConfig.getConfig(); final KernelConfig kernelConfig = KernelConfig.getConfig();
final Locale defaultLocale = kernelConfig.getDefaultLocale(); final Locale defaultLocale = kernelConfig.getDefaultLocale();
@ -269,7 +264,7 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
final ActionGroup group = new ActionGroup(); final ActionGroup group = new ActionGroup();
setBody(group); setBody(group);
group.setSubject(m_tasks); group.setSubject(taskTable);
group.addAction(new AdminVisible(taskAddLink), ActionGroup.ADD); group.addAction(new AdminVisible(taskAddLink), ActionGroup.ADD);
} }
@ -286,7 +281,7 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
private class TaskTable extends Table { private class TaskTable extends Table {
public TaskTable() { public TaskTable() {
super(new TaskTableModelBuilder(m_workflow), s_columns); super(new TaskTableModelBuilder(workflowRequestLocal), s_columns);
setEmptyView(new Label(gz("cms.ui.workflow.task.none"))); setEmptyView(new Label(gz("cms.ui.workflow.task.none")));

View File

@ -0,0 +1,117 @@
/*
* 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.workflow;
import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.ParameterSingleSelectionModel;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.parameters.LongParameter;
import com.arsdigita.cms.ui.BaseItemPane;
import com.arsdigita.toolbox.ui.LayoutPanel;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.workflow.WorkflowRepository;
/**
* Panel for applying a workflow template to a content item. By
* default this panel display a list of workflows that can be applied
* to the content item. If a workflow is applied, it displays the item
* details page.
*
* @author Uday Mathur
* @author Michael Pih
* @author Justin Ross &lt;jross@redhat.com&gt;
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ItemWorkflowAdminPane extends BaseItemPane {
private final ParameterSingleSelectionModel m_model;
private final WorkflowRequestLocal m_workflow;
private final LayoutPanel m_detailPane;
private final LayoutPanel m_selectPane;
public ItemWorkflowAdminPane(final LongParameter itemIdParameter) {
m_model = new ItemWorkflowSelectionModel(itemIdParameter);
m_workflow = new SelectionRequestLocal();
final ActionLink editLink = new ActionLink
(new Label(gz("cms.ui.workflow.edit")));
final WorkflowEditForm editForm = new WorkflowEditForm(m_workflow);
final ActionLink deleteLink = new ActionLink
(new Label(gz("cms.ui.workflow.delete")));
final WorkflowDeleteForm deleteForm = new WorkflowDeleteForm
(m_workflow);
m_detailPane = new LayoutPanel();
m_detailPane.setBody(new ItemWorkflowItemPane
(m_workflow, editLink, deleteLink));
final ItemWorkflowSelectForm workflowSelectForm =
new ItemWorkflowSelectForm();
m_selectPane = new LayoutPanel();
m_selectPane.setBody(workflowSelectForm);
add(m_detailPane);
setDefault(m_detailPane);
add(m_selectPane);
add(editForm);
add(deleteForm);
connect(workflowSelectForm, m_detailPane);
connect(editLink, editForm);
connect(deleteLink, deleteForm);
connect(deleteForm, m_selectPane);
}
private class SelectionRequestLocal extends WorkflowRequestLocal {
@Override
protected final Object initialValue(final PageState state) {
final String workflowId = m_model.getSelectedKey(state).toString();
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final WorkflowRepository workflowRepo = cdiUtil.findBean(WorkflowRepository.class);
return workflowRepo.findById(Long.parseLong(workflowId));
}
}
@Override
public final void register(final Page page) {
super.register(page);
page.addActionListener(new ActionListener() {
@Override
public final void actionPerformed(final ActionEvent event) {
final PageState state = event.getPageState();
if (state.isVisibleOnPage(ItemWorkflowAdminPane.this)
&& m_model.getSelectedKey(state) == null) {
push(state, m_selectPane);
}
}
});
}
}

View File

@ -0,0 +1,170 @@
/*
* 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.workflow;
import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.cms.CMS;
import org.librecms.workflow.CmsTask;
import com.arsdigita.web.Web;
import org.libreccm.workflow.Workflow;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.security.PermissionChecker;
import org.libreccm.workflow.TaskRepository;
import org.libreccm.workflow.WorkflowManager;
import org.libreccm.workflow.WorkflowState;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.privileges.AdminPrivileges;
/**
* @author Justin Ross &lt;jross@redhat.com&gt;
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
final class ItemWorkflowItemPane extends BaseWorkflowItemPane {
private final AssignedTaskTable assignedTaskTable;
public ItemWorkflowItemPane(final WorkflowRequestLocal workflowRequestLocal,
final ActionLink editLink,
final ActionLink deleteLink) {
super(workflowRequestLocal, editLink, deleteLink);
actionGroup.addAction(new AdminVisible(new StartLink()));
actionGroup.addAction(new AdminVisible(new StopLink()));
assignedTaskTable = new AssignedTaskTable(workflowRequestLocal);
detailPane.add(new AssignedTaskSection(workflowRequestLocal,
assignedTaskTable));
final TaskFinishForm taskFinishForm = new TaskFinishForm(
new TaskSelectionRequestLocal());
add(taskFinishForm);
connect(assignedTaskTable, 2, taskFinishForm);
connect(taskFinishForm);
}
private final class TaskSelectionRequestLocal extends TaskRequestLocal {
@Override
protected final Object initialValue(final PageState state) {
final String taskId = assignedTaskTable.getRowSelectionModel().
getSelectedKey(state).toString();
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final TaskRepository taskRepo = cdiUtil.findBean(
TaskRepository.class);
return (CmsTask) taskRepo.findById(Long.parseLong(taskId));
}
}
private boolean hasAdmin(final PageState state) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionChecker permissionChecker = cdiUtil.findBean(
PermissionChecker.class);
final ContentSection section = CMS.getContext().getContentSection();
return permissionChecker.isPermitted(
AdminPrivileges.ADMINISTER_WORKFLOW, section);
}
private class StopLink extends ActionLink {
StopLink() {
super(new Label(gz("cms.ui.item.workflow.stop")));
addActionListener(new Listener());
}
@Override
public final boolean isVisible(final PageState state) {
final Workflow workflow = workflowRequestLocal.getWorkflow(state);
return workflow.getState() == WorkflowState.STARTED;
}
private class Listener implements ActionListener {
@Override
public final void actionPerformed(final ActionEvent event) {
final PageState state = event.getPageState();
if (hasAdmin(state)) {
final Workflow workflow = workflowRequestLocal.getWorkflow(
state);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final WorkflowManager workflowManager = cdiUtil.findBean(
WorkflowManager.class);
workflowManager.stop(workflow);
}
}
}
}
private class StartLink extends ActionLink {
StartLink() {
super(new Label(gz("cms.ui.item.workflow.start")));
addActionListener(new Listener());
}
@Override
public final boolean isVisible(final PageState state) {
final Workflow workflow = workflowRequestLocal.getWorkflow(state);
// Start link should be visible if the workflow state is stopped
// or init
return workflow.getState() == WorkflowState.STOPPED
|| workflow.getState() == WorkflowState.INIT;
}
private class Listener implements ActionListener {
@Override
public final void actionPerformed(final ActionEvent event) {
final PageState state = event.getPageState();
if (hasAdmin(state)) {
final Workflow workflow = workflowRequestLocal.getWorkflow(
state);
final CdiUtil cdiUtil =CdiUtil.createCdiUtil();
final WorkflowManager workflowManager = cdiUtil.findBean(
WorkflowManager.class);
workflowManager.start(workflow);
}
}
}
}
}

View File

@ -0,0 +1,110 @@
/*
* 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.workflow;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.form.RadioGroup;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.bebop.parameters.BigDecimalParameter;
import com.arsdigita.bebop.parameters.NotNullValidationListener;
import com.arsdigita.cms.CMS;
import com.arsdigita.cms.ui.CMSForm;
import com.arsdigita.web.Web;
import org.libreccm.workflow.Workflow;
import org.libreccm.workflow.WorkflowTemplate;
import org.apache.logging.log4j.Logger;
import java.math.BigDecimal;
import java.util.TooManyListenersException;
import org.apache.logging.log4j.LogManager;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.workflow.WorkflowManager;
import org.libreccm.workflow.WorkflowTemplateRepository;
import org.librecms.contentsection.ContentItem;
/**
* This panel displays a radio group of available Workflow Templates in this
* content section that can be applied to this item.
*
* @author Uday Mathur
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
class ItemWorkflowSelectForm extends CMSForm {
private static final Logger LOGGER = LogManager.getLogger(
ItemWorkflowSelectForm.class);
private RadioGroup radioGroup;
public ItemWorkflowSelectForm() {
super("applyWorkflow", new SimpleContainer());
addFormWidgets();
addProcessListener(new ProcessListener());
}
protected void addFormWidgets() {
radioGroup = new RadioGroup(new BigDecimalParameter("workflowSelect"));
radioGroup.setClassAttr("vertical");
try {
radioGroup.addPrintListener(new WorkflowsOptionPrintListener());
} catch (TooManyListenersException t) {
LOGGER.error("Too many listeners", t);
}
radioGroup.addValidationListener(new NotNullValidationListener());
add(radioGroup);
add(new Submit("apply_wf", "Apply Workflow"));
}
/**
* Adds a FormProcessListener to that applies a clone of the
* WorkflowTemplate to this ContentItem. In case of double-click, no change
* is made.
*/
private class ProcessListener implements FormProcessListener {
@Override
public final void process(final FormSectionEvent event)
throws FormProcessException {
final PageState state = event.getPageState();
final Long flowId = (Long) radioGroup.getValue(state);
final ContentItem item = CMS.getContext().getContentItem();
if (item.getWorkflow() == null) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final WorkflowTemplateRepository templateRepo = cdiUtil.
findBean(WorkflowTemplateRepository.class);
final WorkflowManager workflowManager = cdiUtil.findBean(
WorkflowManager.class);
final WorkflowTemplate template = templateRepo.findById(flowId);
workflowManager.createWorkflow(template, item);
}
}
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (C) 2002-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.workflow;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.ParameterSingleSelectionModel;
import com.arsdigita.bebop.parameters.LongParameter;
import com.arsdigita.cms.ItemSelectionModel;
import org.libreccm.cdi.utils.CdiUtil;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemRepository;
class ItemWorkflowSelectionModel extends ParameterSingleSelectionModel {
private final ItemSelectionModel itemSelectionModel;
public ItemWorkflowSelectionModel(final LongParameter itemIdParameter) {
super(itemIdParameter);
itemSelectionModel = new ItemSelectionModel(itemIdParameter);
}
public ItemWorkflowSelectionModel(
final ItemSelectionModel itemSelectionModel) {
super(itemSelectionModel.getStateParameter());
this.itemSelectionModel = itemSelectionModel;
}
@Override
public Object getSelectedKey(final PageState state) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemRepository itemRepo = cdiUtil.findBean(ContentItemRepository.class);
final ContentItem item = itemRepo.findById((Long) super.getSelectedKey(
state));
return item.getWorkflow().getWorkflowId();
}
public ItemSelectionModel getItemSelectionModel() {
return itemSelectionModel;
}
}

View File

@ -179,7 +179,6 @@ public final class TaskFinishForm extends CommentAddForm {
final TaskManager taskManager = cdiUtil.findBean(TaskManager.class); final TaskManager taskManager = cdiUtil.findBean(TaskManager.class);
final AssignableTaskManager assignableTaskManager = cdiUtil final AssignableTaskManager assignableTaskManager = cdiUtil
.findBean(AssignableTaskManager.class); .findBean(AssignableTaskManager.class);
final Shiro shiro = cdiUtil.findBean(Shiro.class);
final ConfigurationManager confManager = cdiUtil.findBean( final ConfigurationManager confManager = cdiUtil.findBean(
ConfigurationManager.class); ConfigurationManager.class);
final KernelConfig kernelConfig = confManager.findConfiguration( final KernelConfig kernelConfig = confManager.findConfiguration(
@ -221,7 +220,6 @@ public final class TaskFinishForm extends CommentAddForm {
final TaskFinishFormController controller = cdiUtil.findBean( final TaskFinishFormController controller = cdiUtil.findBean(
TaskFinishFormController.class); TaskFinishFormController.class);
final Workflow workflow = task.getWorkflow(); final Workflow workflow = task.getWorkflow();
final User user = shiro.getUser();
final List<AssignableTask> tasks = controller.findEnabledTasks( final List<AssignableTask> tasks = controller.findEnabledTasks(
workflow); workflow);
for (final AssignableTask currentTask : tasks) { for (final AssignableTask currentTask : tasks) {
@ -243,7 +241,7 @@ public final class TaskFinishForm extends CommentAddForm {
throw new RedirectSignal( throw new RedirectSignal(
URL.there(state.getRequest(), URL.there(state.getRequest(),
ContentItemPage.getItemURL( ContentItemPage.getItemURL(
item, item.get(),
ContentItemPage.PUBLISHING_TAB)), ContentItemPage.PUBLISHING_TAB)),
true); true);
} }

View File

@ -0,0 +1,54 @@
/*
* 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.workflow;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.cms.ui.BaseDeleteForm;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.workflow.Workflow;
import org.libreccm.workflow.WorkflowRepository;
/*
* @author Justin Ross &lt;jross@redhat.com&gt;
* @version $Id: WorkflowDeleteForm.java 287 2005-02-22 00:29:02Z sskracic $
*/
class WorkflowDeleteForm extends BaseDeleteForm {
final WorkflowRequestLocal m_workflow;
WorkflowDeleteForm(final WorkflowRequestLocal workflow) {
super(new Label(gz("cms.ui.workflow.delete_prompt")));
m_workflow = workflow;
}
@Override
public final void process(final FormSectionEvent event)
throws FormProcessException {
final Workflow workflow = m_workflow.getWorkflow(event.getPageState());
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final WorkflowRepository workflowRepo = cdiUtil.findBean(WorkflowRepository.class);
workflowRepo.delete(workflow);
}
}

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.workflow;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.OptionGroup;
import com.arsdigita.cms.CMS;
import com.arsdigita.kernel.KernelConfig;
import java.util.List;
import org.libreccm.cdi.utils.CdiUtil;
import org.librecms.contentsection.ContentSection;
import org.libreccm.workflow.Task;
import org.libreccm.workflow.WorkflowTemplate;
/**
* Builds a list of workflow templates registered to the current content
* section.
*
* @author Uday Mathur (umathur@arsdigita.com)
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class WorkflowsOptionPrintListener implements PrintListener {
protected List<WorkflowTemplate> getCollection(final PageState state) {
final ContentSection section = getContentSection(state);
return section.getWorkflowTemplates();
}
protected ContentSection getContentSection(final PageState state) {
return CMS.getContext().getContentSection();
}
@Override
public void prepare(final PrintEvent event) {
final PageState state = event.getPageState();
final OptionGroup target = (OptionGroup) event.getTarget();
target.clearOptions();
final List<WorkflowTemplate> templates = getCollection(state);
for (final WorkflowTemplate template : templates) {
target.addOption(new Option(
Long.toString(template.getWorkflowId()),
template.getName().getValue(KernelConfig
.getConfig()
.getDefaultLocale())));
}
}
}

View File

@ -308,7 +308,7 @@ public class ContentItemL10NManager {
*/ */
@AuthorizationRequired @AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public void removeLangauge( public void removeLanguage(
@RequiresPrivilege(ItemPrivileges.EDIT) @RequiresPrivilege(ItemPrivileges.EDIT)
final ContentItem item, final ContentItem item,
final Locale locale) { final Locale locale) {
@ -330,7 +330,7 @@ public class ContentItemL10NManager {
} }
findLocalizedStringProperties(item) findLocalizedStringProperties(item)
.forEach(property -> removeLanguage(item, locale, property)); .forEach(property -> ContentItemL10NManager.this.removeLanguage(item, locale, property));
itemRepo.save(item); itemRepo.save(item);
} }

View File

@ -299,7 +299,7 @@ public class ContentItemL10NManagerTest {
/** /**
* Tries to remove language from a content item by using * Tries to remove language from a content item by using
* {@link ContentItemL10NManager#removeLangauge(org.librecms.contentsection.ContentItem, java.util.Locale)}. * {@link ContentItemL10NManager#removeLanguage(org.librecms.contentsection.ContentItem, java.util.Locale)}.
*/ */
@Test @Test
@InSequence(70) @InSequence(70)
@ -313,12 +313,12 @@ public class ContentItemL10NManagerTest {
final Optional<ContentItem> item = itemRepo.findById(-10100L); final Optional<ContentItem> item = itemRepo.findById(-10100L);
assertThat(item.isPresent(), is(true)); assertThat(item.isPresent(), is(true));
l10nManager.removeLangauge(item.get(), Locale.FRENCH); l10nManager.removeLanguage(item.get(), Locale.FRENCH);
} }
/** /**
* Verifies that * Verifies that
* {@link ContentItemL10NManager#removeLangauge(org.librecms.contentsection.ContentItem, java.util.Locale)} * {@link ContentItemL10NManager#removeLanguage(org.librecms.contentsection.ContentItem, java.util.Locale)}
* has not effect if called for not present language. * has not effect if called for not present language.
*/ */
@Test @Test
@ -332,12 +332,12 @@ public class ContentItemL10NManagerTest {
final Optional<ContentItem> item = itemRepo.findById(-10100L); final Optional<ContentItem> item = itemRepo.findById(-10100L);
assertThat(item.isPresent(), is(true)); assertThat(item.isPresent(), is(true));
l10nManager.removeLangauge(item.get(), Locale.GERMAN); l10nManager.removeLanguage(item.get(), Locale.GERMAN);
} }
/** /**
* Verifies that * Verifies that
* {@link ContentItemL10NManager#removeLangauge(org.librecms.contentsection.ContentItem, java.util.Locale)} * {@link ContentItemL10NManager#removeLanguage(org.librecms.contentsection.ContentItem, java.util.Locale)}
* throws an {@link IllegalArgumentException} if called with {@code null} * throws an {@link IllegalArgumentException} if called with {@code null}
* for the item. * for the item.
*/ */
@ -352,12 +352,12 @@ public class ContentItemL10NManagerTest {
public void removeLanguageItemIsNull() { public void removeLanguageItemIsNull() {
final ContentItem item = null; final ContentItem item = null;
l10nManager.removeLangauge(item, Locale.GERMAN); l10nManager.removeLanguage(item, Locale.GERMAN);
} }
/** /**
* Verifies that * Verifies that
* {@link ContentItemL10NManager#removeLangauge(org.librecms.contentsection.ContentItem, java.util.Locale)} * {@link ContentItemL10NManager#removeLanguage(org.librecms.contentsection.ContentItem, java.util.Locale)}
* throws an {@link IllegalArgumentException} if called with {@code null} * throws an {@link IllegalArgumentException} if called with {@code null}
* for the language. * for the language.
*/ */
@ -373,7 +373,7 @@ public class ContentItemL10NManagerTest {
final Optional<ContentItem> item = itemRepo.findById(-10100L); final Optional<ContentItem> item = itemRepo.findById(-10100L);
assertThat(item.isPresent(), is(true)); assertThat(item.isPresent(), is(true));
l10nManager.removeLangauge(item.get(), null); l10nManager.removeLanguage(item.get(), null);
} }

View File

@ -0,0 +1,815 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.bebop;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ChangeEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.ChangeListener;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSubmissionListener;
import com.arsdigita.bebop.list.DefaultListCellRenderer;
import com.arsdigita.bebop.list.ListModelBuilder;
import com.arsdigita.bebop.list.ListModel;
import com.arsdigita.bebop.util.GlobalizationUtil;
import com.arsdigita.util.Assert;
import com.arsdigita.util.LockableImpl;
import com.arsdigita.util.SequentialMap;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.form.FormErrorDisplay;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.globalization.GlobalizedMessage;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
/**
* Maintains a set of forms that are used when editing the
* properties of some object. The component maintains a single
* display pane and a list of forms that are selectable by links.
* <p>
* By default, the component looks something like this:
* <blockquote><pre><code>
* +----------------+
* | |
* | Display Pane |
* | |
* +----------------+
* [link to form1]
* [link to form2]
* [link to form3]
* </code></pre></blockquote>
*
* When the user clicks on a link, the display pane is hidden and the
* corresponding form is shown.
*
* <blockquote><pre><code>
* Enter foo: [ ]
* Enter bar: [ ]
*
* [Save] [Cancel]
* </code></pre></blockquote>
*
* When the user clicks the Save or Cancel button on the form, the form
* is hidden and the display pane (with its list of links)
* is shown once again.
* <p>
* The simple usage pattern for this class is as follows:
*
* <blockquote><pre><code>
* PropertyEditor editor = new PropertyEditor();
* editor.setDisplayComponent(new FooComponent());
* NameEditForm n = new NameEditForm();
* editor.add("name", "Edit Name", n, n.getCancelButton());
* AddressEditForm a = new AddressEditForm();
* editor.add("address", "Edit Address", a, a.getCancelButton());
* </code></pre></blockquote>
*
* The <code>PropertyEditor</code> will automatically add the right
* listeners to the forms.
* <p>
* This class is used extensively in the default authoring kit steps,
* especially <code>PageEdit</code> and <code>TextPageBody</code> in CMS.
* <p>
* <b>Advanced Usage</b>:<br>
* The <code>PropertyEditor</code> may be used to maintain
* visibility of any components, not just forms. The
* {@link #addComponent(String, String, Component)} method
* can be used to add an arbitrary component to the editor. The
* component will be shown in the list of links, along with other components
* and/or forms. The component will be shown as usual when the user clicks
* on a link. However, you must be sure to include a call to
* {@link #showDisplayPane(PageState)} when the component needs to be hidden.
* <p>
* In addition, it is possible to manually generate {@link ActionLink}s
* that will display the right components in the editor. The
* {@link #addComponent(String, Component)} method can be used to add
* a component to the <code>PropertyEditor</code> without automatically
* generating the link for it. The {@link #addVisibilityListener(ActionLink, String)}
* method can then be used to add an appropriate {@link ActionListener} to any
* {@link ActionLink}. For example:
*
* <blockquote><pre><code>// Add a form
* Form fooForm = new FooForm();
* editor.addComponent(FOO_FORM, fooForm);
* editor.addListeners(fooForm, fooForm.getCancelButton());
* // Create a link that shows the form
* fooLink = new ActionLink("Edit the Foo property");
* editor.addVisibilityListener(fooLink, FOO_FORM);</code></pre></blockquote>
*
* Note that the visibility of the form will be handled automatically. There
* is no need to show or hide it manually. This approach allows
* greater flexibility in placing links on a page. The links may be
* part of the editor's display pane, but they do not have to be.
* <p>
* <b>More-advanced Usage</b>:<br>
* The <code>PropertyEditor</code> is backed by a
* {@link PropertyEditorModel} through a {@link PropertyEditorModelBuilder}.
* Therefore, the <code>PropertyEditor</code> is a model-backed component,
* as described in the Bebop tutorials. This means that the list
* of properties for the editor could be generated dynamically during
* each request. The {@link #setModelBuilder(PropertyEditorModelBuilder)} method
* can be used to set a specialized {@link PropertyEditorModelBuilder} for the
* editor. In order to write the model builder, you may choose to extend the
* protected inner classes {@link PropertyEditor.DefaultModelBuilder} and
* {@link PropertyEditor.DefaultModel}. It is also possible to write the model
* builder and the corresponding model from scratch. However, most people won't
* need to do this.
* <p>
* For example, <code>SecurityPropertyEditor</code> uses a custom
* {@link PropertyEditorModelBuilder} in order to hide the links for properties
* which the web user is not allowed to edit.
* <p>
*
* @author Stanislav Freidin
* @version $Id: PropertyEditor.java 1638 2007-09-17 11:48:34Z chrisg23 $
*/
public class PropertyEditor extends SimpleContainer {
private SequentialMap m_forms;
private SequentialMap m_labels;
private Component m_display;
private Container m_displayPane;
private List m_list;
private PropertyEditorModelBuilder m_builder;
private RequestLocal m_model;
private java.util.List m_additionalDisplayComponents = new ArrayList();
/**
* Constructs a new, empty <code>PropertyEditor</code>.
* The {@link #setDisplayComponent(Component)} method must be called before
* this component is locked.
*/
public PropertyEditor() {
this(null);
}
/**
* Constructs a new <code>PropertyEditor</code> with the given
* display component. The pane defaults to a {@link
* com.arsdigita.bebop.SimpleContainer}.
*
* @param display the display component
*/
public PropertyEditor(Component display) {
this(display, new SimpleContainer());
}
/**
* Constructs a new <code>PropertyEditor</code> with the given
* display component and display pane.
*
* @param display the display component
* @param pane the display pane. The caller should pass in a
* freshly allocated Container.
*/
public PropertyEditor(Component display, Container pane) {
super();
setClassAttr("propertyEditor");
m_forms = new SequentialMap();
m_labels = new SequentialMap();
m_display = null;
m_displayPane = pane;
super.add(m_displayPane);
m_list = new List();
m_list.setCellRenderer(new IdentityCellRenderer());
// Change listener: reset visibility
// Should a ComponentSelectionModel be used here instead ? It's tempting,
// but there doesn't seem to be a real need for it
m_list.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
PageState state = e.getPageState();
// Get the visible component
Component c = null;
if ( !m_list.isSelected(state) ) {
// Select the display pane
c = m_displayPane;
} else {
c = getComponent(getSelectedComponentKey(state));
}
// Iterate over the forms
for(Iterator i = m_forms.values().iterator(); i.hasNext(); ) {
Component f = (Component)i.next();
f.setVisible(state, (f == c));
}
m_displayPane.setVisible(state, (m_displayPane == c));
}
});
// Don't add the list yet; add it when we add the display
// component
if(display != null)
setDisplayComponent(display);
// Prepare the model builder
setModelBuilder(new DefaultModelBuilder());
m_model = new RequestLocal() {
@Override
protected Object initialValue(PageState s) {
return getModelBuilder().makeModel(PropertyEditor.this, s);
}
};
}
/** Set the display component visible by default, and the
* form(s) invisible by default.
*/
@Override
public void register(Page p) {
Assert.exists(m_display, "display component");
p.setVisibleDefault(m_displayPane, true);
for(Iterator i = m_forms.values().iterator(); i.hasNext(); ) {
p.setVisibleDefault((Component)i.next(), false);
}
}
/**
* Hides the form(s) and shows the display pane.
*
* @param state the page state
*/
public void showDisplayPane(PageState state) {
m_list.clearSelection(state);
}
/**
* Shows the component that is identified by the specified key.
*
* @param state the page state
* @param key
*/
public void showComponent(PageState state, String key) {
m_list.setSelectedKey(state, key);
}
/**
* Returns the key of the currently visible component, or null if
* the display pane is currently visible.
* @param state the page state
*
* @return the key of the currently visible component, or null if the
* display pane is visible.
*/
public String getSelectedComponentKey(PageState state) {
return (String)m_list.getSelectedKey(state);
}
/**
* add an additional component below the list of links
* @param c
*/
public void addDisplayComponent(Component c) {
m_additionalDisplayComponents.add(c);
}
/**
* Adds the display component if it has not been added already.
*
* @param c the display component to add
*/
public void setDisplayComponent(Component c) {
if(m_display != null) {
throw new IllegalStateException("Display component has already been set");
}
m_displayPane.add(c);
m_displayPane.add(m_list);
Iterator it = m_additionalDisplayComponents.iterator();
while (it.hasNext()) {
m_displayPane.add((Component)it.next());
}
m_display = c;
}
/**
* Adds a component to the property editor. The component will be
* completely invisible. It is up to the user to call
* {@link #showComponent(PageState, String)} to display the component and to
* call {@link #showDisplayPane(PageState)} when the component needs to be hidden.
*
* @param key the symbolic key for the component (must be unique
* for this <code>PropertyEditor</code>)
* @param c the component
*/
public void addComponent(String key, Component c) {
m_forms.put(key, c);
super.add(c);
}
/**
* Adds a component to the list of links. It is up to the component to
* correctly call {@link #showDisplayPane(PageState)} when it is done.
*
* @param key the symbolic key for the component (must be unique
* for this <code>PropertyEditor</code>)
* @param label the label for the link
* @param c the component
* @deprecated use addComponent(String,GlobalizedMessage,Component) instead
*/
public void addComponent(String key, String label, Component c) {
addComponent(key, c);
m_labels.put(key, label);
}
/**
* Adds a component to the list of links. It is up to the component to
* correctly call {@link #showDisplayPane(PageState)} when it is done.
*
* @param key the symbolic key for the component (must be unique
* for this <code>PropertyEditor</code>)
* @param label the label for the link
* @param c the component
*/
public void addComponent(String key, GlobalizedMessage label, Component c) {
addComponent(key, c);
m_labels.put(key, label);
}
/**
* Adds a form to the set of forms that can be used to edit the
* properties.
*
* @param key the symbolic key for the form (must be unique
* for this <code>PropertyEditor</code>)
* @param label the label for the link
* @param form the form component
* @deprecated use add(String,GlobalizedMessage,Form) instead.
*/
public void add(String key, String label, Form form) {
addComponent(key, label, form);
addProcessListener(form);
}
/**
* Adds a form to the set of forms that can be used to edit the
* properties.
*
* @param key the symbolic key for the form (must be unique
* for this <code>PropertyEditor</code>)
* @param label the label for the link
* @param form the form component
*/
public void add(String key, GlobalizedMessage label, Form form) {
addComponent(key, label, form);
addProcessListener(form);
}
/**
* Adds a form to the set of forms that can be used to edit the
* properties.
*
* @param key the symbolic key for the form (must be unique
* for this <code>PropertyEditor</code>)
* @param label the label for the link
* @param form the form component
* @param cancelButton the Cancel button on the form
* @deprecated use add(String,GlobalizedMessage,Form,Submit) instead.
*/
public void add(String key, String label, Form form, Submit cancelButton) {
add(key, label, form);
addListeners(form, cancelButton);
}
/**
* Adds a form to the set of forms that can be used to edit the
* properties.
*
* @param key the symbolic key for the form (must be unique
* for this <code>PropertyEditor</code>)
* @param label the label for the link
* @param form the form component
* @param cancelButton the Cancel button on the form
*/
public void add(String key, GlobalizedMessage label, Form form, Submit cancelButton) {
add(key, label, form);
addListeners(form, cancelButton);
}
/**
* Adds a form to the set of forms that can be used to edit the
* properties.
*
* @param key the symbolic key for the form (must be unique
* for this <code>PropertyEditor</code>)
* @param label the label for the link
* @param formSection the form component
*
* @pre !(formSection instanceof Form)
* @deprecated use add(String,GlobalizedMessage,FormSection) instead.
*/
public void add(String key, String label, FormSection formSection) {
if (formSection instanceof Form) {
throw new IllegalArgumentException("formSection is an instance of Form");
}
Form form = new Form("property" + key);
form.add(new FormErrorDisplay(form), ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);
form.add(formSection);
form.setMethod(Form.POST);
form.setEncType("multipart/form-data");
add(key, label , form);
}
/**
* Adds a form to the set of forms that can be used to edit the
* properties.
*
* @param key the symbolic key for the form (must be unique
* for this <code>PropertyEditor</code>)
* @param label the label for the link
* @param formSection the form component
*
* @pre !(formSection instanceof Form)
*/
public void add(String key, GlobalizedMessage label, FormSection formSection) {
if (formSection instanceof Form) {
throw new IllegalArgumentException("formSection is an instance of Form");
}
Form form = new Form("property" + key);
form.add(new FormErrorDisplay(form), ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);
form.add(formSection);
form.setMethod(Form.POST);
form.setEncType("multipart/form-data");
add(key, label , form);
}
/**
* Adds a form to the set of forms that can be used to edit the properties.
*
* @param key the symbolic key for the form (must be unique
* for this <code>PropertyEditor</code>)
* @param label the label for the link
* @param formSection the form component
* @param cancelButton the Cancel button on the form
* @deprecated use add(String,GlobalizedMessage,FormSection,Submit) instead.
*/
public void add(String key,
String label,
FormSection formSection,
Submit cancelButton) {
Form form = new Form("property" + key);
form.add(new FormErrorDisplay(form), ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);
form.add(formSection);
form.setMethod(Form.POST);
form.setEncType("multipart/form-data");
add(key, label , form, cancelButton);
}
/**
* Adds a form to the set of forms that can be used to edit the
* properties.
*
* @param key the symbolic key for the form (must be unique
* for this <code>PropertyEditor</code>)
* @param label the label for the link as a GlobalizedMessage
* @param formSection the form component
* @param cancelButton the Cancel button on the form
*/
public void add(String key,
GlobalizedMessage label,
FormSection formSection,
Submit cancelButton) {
Form form = new Form("property" + key);
form.add(new FormErrorDisplay(form), ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);
form.add(formSection);
form.setMethod(Form.POST);
form.setEncType("multipart/form-data");
add(key, label , form, cancelButton);
}
/**
* Retrieves the component at the specified key.
*
* @param key the key of the component to retrieve
* @return a component that has been added to this
* <code>PropertyEditor</code> at the specified key, or null
* if no such component exists.
*/
public Component getComponent(String key) {
return (Component)m_forms.get(key);
}
/**
* Adds a submission listener to the form that will hide all components
* and show the display pane. This method should be used to add
* submission listeners to forms that are buried deep inside some
* component and are not members of this <code>PropertyEditor</code>.
*
* @param form the form
* @param cancelButton the Cancel button on the form
*/
public void addCancelListener(FormSection form, Submit cancelButton) {
// Add a different submission listener for each form since the
// cancel button may be different
final Submit theButton = cancelButton;
form.addSubmissionListener(new FormSubmissionListener() {
@Override
public void submitted(FormSectionEvent e) throws FormProcessException {
PageState state = e.getPageState();
if(theButton.isSelected(state)) {
showDisplayPane(state);
throw new FormProcessException(
"Submission Cancelled",
GlobalizationUtil.globalize("bebop.cancel.msg"));
}
}
});
}
/**
* Adds a process listener to the form that will hide all components
* and show the display pane. This method should be used to add
* process listeners to forms that are buried deep inside some
* component and are not members of this <code>PropertyEditor</code>.
*
* @param form the form
*/
public void addProcessListener(FormSection form) {
form.addProcessListener(new FormProcessListener() {
@Override
public void process(FormSectionEvent e) throws FormProcessException {
PageState state = e.getPageState();
showDisplayPane(state);
}
});
}
/**
* Adds all required listeners to the form to ensure that
* if the form is either submitted successfully or cancelled,
* the display pane will be shown. This method should be used
* to add listeners to forms that are buried deep inside some
* component, and are not members of this <code>PropertyEditor</code>.
*
* @param form the form
* @param cancelButton the Cancel button on the form
*/
public void addListeners(FormSection form, Submit cancelButton) {
addCancelListener(form, cancelButton);
addProcessListener(form);
}
/**
* This method can be used to add an {@link ActionListener} to any
* {@link ActionLink}, causing the action link to show the specified
* component when it is clicked. For example, this method may be useful
* if the {@link ActionLink} that is supposed to show the component is
* buried somewhere deep within the UI.
*
* @param l the {@link ActionLink}
* @param key the key of the component that will be shown when the link
* is clicked, as specified in the
* {@link #addComponent(String, Component)} method
* @see #addComponent(String, Component)
*/
public void addVisibilityListener(ActionLink l, String key) {
final String t_key = key;
l.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
showComponent(e.getPageState(), t_key);
}
});
}
/**
* Returns the {@link List} that contains all the links.
* @return the {@link List} that contains all the links.
*/
public List getList() {
return m_list;
}
/**
* Returns the {@link PropertyEditorModelBuilder} that supplies this
* property editor with its {@link PropertyEditorModel} during each
* request.
*
* @return the {@link PropertyEditorModelBuilder} for this component.
*/
protected final PropertyEditorModelBuilder getModelBuilder() {
return m_builder;
}
/**
* Sets the {@link PropertyEditorModelBuilder} that will supply this
* property editor with its {@link PropertyEditorModel} during each
* request.
* @param b the property editor model builder
*/
protected final void setModelBuilder(PropertyEditorModelBuilder b) {
Assert.isUnlocked(this);
m_builder = b;
m_list.setModelBuilder(new BuilderAdapter(this));
}
/**
* Returns the {@link PropertyEditorModel} in use during the current
* request.
*
* @param s represents the current request
* @return the {@link PropertyEditorModel} that supplies the properties
* for the current request.
*/
protected final PropertyEditorModel getModel(PageState s) {
return (PropertyEditorModel)m_model.get(s);
}
/**
* Returns the display component.
* @return the display component.
*/
public Component getDisplayComponent() {
return m_display;
}
/**
* Returns the display pane (component + list).
* @return the display pane (component + list).
*/
public Container getDisplayPane() {
return m_displayPane;
}
/**
* Returns the map of labels.
* @return the map of labels.
*/
protected SequentialMap getLabelsMap() {
return m_labels;
}
/**
* Locks this component.
*/
@Override
public void lock() {
getModelBuilder().lock();
super.lock();
}
/**
* Renders the components generated by the model directly
*/
protected static class IdentityCellRenderer extends DefaultListCellRenderer {
@Override
public Component getComponent(List list, PageState state, Object value,
String key, int index, boolean isSelected) {
return (Component)value;
}
}
/**
* Default implementation of the {@link PropertyEditorModelBuilder}.
* Takes in a SequentialMap of key->label, and constructs a ControlLink for each
* label.
*/
protected static class DefaultModelBuilder
extends LockableImpl implements PropertyEditorModelBuilder {
public DefaultModelBuilder() {
super();
}
/**
* Return an iterator of all properties of the specified property
* editor. These properties should be passed into the constructor
* of the {@link PropertyEditor.DefaultModel}
* @param p
* @return
*/
protected Iterator getProperties(PropertyEditor p) {
return p.getLabelsMap().entrySet().iterator();
}
/**
* Construct a {@link PropertyEditorModel} for the current
* request.
*/
@Override
public PropertyEditorModel makeModel(PropertyEditor p, PageState s) {
return new DefaultModel(getProperties(p));
}
}
/**
* Internal class with default implementation of the {@link PropertyEditorModel}.
* Takes in an iterator of key->label pairs, and constructs a ControlLink
* for each label.
*/
protected static class DefaultModel implements PropertyEditorModel {
protected Iterator m_iter;
protected Map.Entry m_entry;
public DefaultModel(Iterator iter) {
m_iter = iter;
m_entry = null;
}
@Override
public boolean next() {
if(!m_iter.hasNext()) {
m_entry = null;
return false;
}
m_entry = (Map.Entry)m_iter.next();
return true;
}
/**
* Actually retrieve action link and label. Will be executed at each
* request to ensure proper localization.
* @return
*/
@Override
public Component getComponent() {
Assert.exists(m_entry);
if ( m_entry.getValue() instanceof GlobalizedMessage ) {
ControlLink l = new ControlLink(new
Label((GlobalizedMessage)m_entry.getValue()));
l.setClassAttr("actionLink");
return l;
} else {
ControlLink l = new ControlLink(new Label((String)m_entry.getValue()));
l.setClassAttr("actionLink");
return l;
}
}
@Override
public Object getKey() {
Assert.exists(m_entry);
return m_entry.getKey();
}
}
/**
* Adapts a {@link PropertyEditorModelBuilder} to a {@link ListModelBuilder}
*/
private static final class BuilderAdapter extends LockableImpl
implements ListModelBuilder {
private final PropertyEditor m_parent;
public BuilderAdapter(PropertyEditor parent) {
super();
m_parent = parent;
}
@Override
public ListModel makeModel(List l, PageState state) {
return new ModelAdapter(m_parent.getModel(state));
}
}
/**
* Adapts a {@link PropertyEditorModel} to a {@link ListModel}
*/
private static final class ModelAdapter implements ListModel {
private final PropertyEditorModel m_model;
public ModelAdapter(PropertyEditorModel model) {
m_model = model;
}
@Override
public boolean next() { return m_model.next(); }
@Override
public Object getElement() { return m_model.getComponent(); }
@Override
public String getKey() { return m_model.getKey().toString(); }
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.bebop;
/**
* Provides properties for the {@link PropertyEditor} during
* each request. This class is intended for advanced users only.
*
* @author Stanislav Freidin
* @version $Id: PropertyEditorModel.java 287 2005-02-22 00:29:02Z sskracic $
* @see PropertyEditorModelBuilder
*/
public interface PropertyEditorModel {
/**
* Advances to the next property, if possible.
*
* @return <code>false</code> if there are no more properties;
* <code>true</code> otherwise.
*/
boolean next();
/**
* Returns the component that should act as a "button" for editing the
* property. Typically, this method returns a {@link ControlLink}
* of some sort. When the link is clicked, the {@link PropertyEditor}
* will display the pane for editing the property.
*
* @return a component (usually a {@link ControlLink}) that will act
* as the "button" for editing the property.
*/
Component getComponent();
/**
* Returns the unique key of the current property, usually
* a simple String.
*
* @return the key of the current property.
*/
Object getKey();
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.bebop;
import com.arsdigita.util.Lockable;
/**
* Generates a {@link PropertyEditorModel} for the {@link PropertyEditor}
* during each request. This class is intended for advanced users only.
*
* @author Stanislav Freidin
* @version $Id: PropertyEditorModelBuilder.java 287 2005-02-22 00:29:02Z sskracic $
* @see PropertyEditor
*/
public interface PropertyEditorModelBuilder extends Lockable {
/**
* Constructs a {@link PropertyEditorModel} for the current request.
* @param p the parent {@link PropertyEditor}
* @param s represents the current request
* @return the {@link PropertyEditorModel} for the current request.
*/
PropertyEditorModel makeModel(PropertyEditor p, PageState s);
}

View File

@ -25,6 +25,7 @@ import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.parameters.ParameterModel; import com.arsdigita.bebop.parameters.ParameterModel;
import com.arsdigita.bebop.parameters.BigDecimalParameter; import com.arsdigita.bebop.parameters.BigDecimalParameter;
import com.arsdigita.bebop.event.ChangeListener; import com.arsdigita.bebop.event.ChangeListener;
import com.arsdigita.bebop.parameters.LongParameter;
import com.arsdigita.util.Assert; import com.arsdigita.util.Assert;
import com.arsdigita.util.UncheckedWrapperException; import com.arsdigita.util.UncheckedWrapperException;
@ -40,20 +41,26 @@ import org.libreccm.core.CcmObject;
import org.libreccm.core.CcmObjectRepository; import org.libreccm.core.CcmObjectRepository;
/** /**
* Loads a subclass of an ACSObject from the database. * Loads a subclass of an ACSObject from the database. By default, uses a
* By default, uses a BigDecimal state parameter in order to * <del>BigDecimal</del> {@code Long} state parameter in order to store and
* store and retrieve the item id. * retrieve the item id.
*
* <strong>
* This class has been edited to work with {@link CcmObject} instead of
* {@code ACSObject}. Most methods etc. are the the same. This should work as
* before. Also variable names etc. have been changed to match the common Java
* styles.
* </strong>
* *
* <p> * <p>
* The <code>getSelectedKey(PageState state)</code> method will return the * The <code>getSelectedKey(PageState state)</code> method will return the
* BigDecimal id of the currently selected object. This method * BigDecimal id of the currently selected object. This method will return the
* will return the id even if the object with this id does not * id even if the object with this id does not actually exist.
* actually exist.
* *
* <p> * <p>
* The <code>getSelectedObject(PageState state)</code> method will return the * The <code>getSelectedObject(PageState state)</code> method will return the
* object whose id is <code>getSelectedKey(PageState state)</code>. If the * object whose id is <code>getSelectedKey(PageState state)</code>. If the
* object does not actually exist, the method will return null * object does not actually exist, the method will return null
* *
* <p> * <p>
* Thus, it is possible to implement the following pattern: * Thus, it is possible to implement the following pattern:
@ -78,227 +85,225 @@ import org.libreccm.core.CcmObjectRepository;
* } * }
*}</code></pre></blockquote> *}</code></pre></blockquote>
* *
* Naturally, the <code>ACSObjectSelectionModel</code> could also be passed * Naturally, the <code>ACSObjectSelectionModel</code> could also be passed in
* in as a parameter in the <code>MyComponent</code> constructor. In this * as a parameter in the <code>MyComponent</code> constructor. In this case, it
* case, it should be up to the parent of <code>MyComponent</code> to * should be up to the parent of <code>MyComponent</code> to register the
* register the model's state parameter. * model's state parameter.
* <p> * <p>
* <b>Advanced Usage</b>: The <code>ACSObjectSelectionModel</code> * <b>Advanced Usage</b>: The <code>ACSObjectSelectionModel</code> is actually
* is actually just a wrapper for a {@link SingleSelectionModel} * just a wrapper for a {@link SingleSelectionModel} which maintains the
* which maintains the currently selected object's ID as a * currently selected object's ID as a {@link BigDecimal}. By default, a new
* {@link BigDecimal}. By default, a new * {@link ParameterSingleSelectionModel} is wrapped in this way; however, any
* {@link ParameterSingleSelectionModel} is wrapped in this way; * {@link SingleSelectionModel} may be wrapped. Thus, it becomes possible to use
* however, any {@link SingleSelectionModel} may be wrapped. * the <code>ACSObjectSelectionModel</code> even if the currently selected ID is
* Thus, it becomes possible to use the <code>ACSObjectSelectionModel</code> * not stored in a state parameter.
* even if the currently selected ID is not stored in a state parameter.
* <p> * <p>
* <b>Persistence Details:</b> The default constructor of * <b>Persistence Details:</b> The default constructor of
* <code>ACSObjectSelectionModel</code> will attempt to use the * <code>ACSObjectSelectionModel</code> will attempt to use the
* {@link DomainObjectFactory} to automatically instantiate the correct Java * {@link DomainObjectFactory} to automatically instantiate the correct Java
* subclass of {@link ACSObject}. However, it is also possible to use an * subclass of {@link ACSObject}. However, it is also possible to use an
* alternate constructor in order to force the <code>ACSObjectSelectionModel</code> * alternate constructor in order to force the
* to manually instantiate the objects: * <code>ACSObjectSelectionModel</code> to manually instantiate the objects:
* *
* <blockquote><pre><code> * <blockquote><pre><code>
* ACSObjectSelectionModel model = * ACSObjectSelectionModel model =
* new ACSObjectSelectionModel("com.arsdigita.cms.Article", * new ACSObjectSelectionModel("com.arsdigita.cms.Article",
* "com.arsdigita.cms.Article", "item_id"); * "com.arsdigita.cms.Article", "item_id");
* </code></pre></blockquote> * </code></pre></blockquote>
* *
* In this case, the model will attempt to use reflection to instantiate the * In this case, the model will attempt to use reflection to instantiate the
* correct subclass of <code>ACSObject</code>. In addition, the supplementary * correct subclass of <code>ACSObject</code>. In addition, the supplementary
* constructor makes it possible to create new objects in the database * constructor makes it possible to create new objects in the database using the
* using the {@link #createACSObject(BigDecimal)} method. * {@link #createACSObject(BigDecimal)} method.
* *
* @see com.arsdigita.bebop.SingleSelectionModel * @see com.arsdigita.bebop.SingleSelectionModel
* @see com.arsdigita.bebop.ParameterSingleSelectionModel * @see com.arsdigita.bebop.ParameterSingleSelectionModel
* *
* @author Stanislav Freidin * @author Stanislav Freidin
* @version $Id$ * @author Jens Pelzetter
*/ */
public class ACSObjectSelectionModel implements SingleSelectionModel { public class ACSObjectSelectionModel implements SingleSelectionModel {
private static final Logger s_log = private RequestLocal loaded;
Logger.getLogger(ACSObjectSelectionModel.class); private Class javaClassName;
// private Constructor constructor;
private RequestLocal m_loaded; private String objectType;
private Class m_javaClass; private SingleSelectionModel selectionModel;
private Constructor m_constructor;
private String m_objectType;
private SingleSelectionModel m_model;
/** /**
* Construct a new <code>ACSObjectSelectionModel</code>. * Construct a new <code>ACSObjectSelectionModel</code>. This model will
* This model will produce instances of <code>ACSObject</code> * produce instances of <code>ACSObject</code> by automatically
* by automatically instantiating the correct Java subclass using * instantiating the correct Java subclass using the
* the {@link DomainObjectFactory}. * {@link DomainObjectFactory}.
* *
* @param parameter The state parameter which should be used to store * @param parameter The state parameter which should be used to store the
* the object ID * object ID
*/ */
public ACSObjectSelectionModel(BigDecimalParameter parameter) { public ACSObjectSelectionModel(final LongParameter parameter) {
this(null, null, parameter); this(null, null, parameter);
} }
/** /**
* Construct a new <code>ACSObjectSelectionModel</code>. * Construct a new <code>ACSObjectSelectionModel</code>. This model will
* This model will produce instances of <code>ACSObject</code> * produce instances of <code>ACSObject</code> by automatically
* by automatically instantiating the correct Java subclass using * instantiating the correct Java subclass using the
* the {@link DomainObjectFactory}. * {@link DomainObjectFactory}.
* *
* @param parameterName The name of the state parameter which will * @param parameterName The name of the state parameter which will be used
* be used to store the object ID. * to store the object ID.
*/ */
public ACSObjectSelectionModel(String parameterName) { public ACSObjectSelectionModel(final String parameterName) {
this(null, null, new BigDecimalParameter(parameterName)); this(null, null, new LongParameter(parameterName));
} }
/** /**
* Construct a new <code>ACSObjectSelectionModel</code>. * Construct a new <code>ACSObjectSelectionModel</code>. This model will
* This model will produce instances of <code>ACSObject</code> * produce instances of <code>ACSObject</code> by automatically
* by automatically instantiating the correct Java subclass using * instantiating the correct Java subclass using the
* the {@link DomainObjectFactory}. * {@link DomainObjectFactory}.
* *
* @param model The {@link SingleSelectionModel} which will supply * @param model The {@link SingleSelectionModel} which will supply a
* a {@link BigDecimal} ID of the currently selected object * {@link BigDecimal} ID of the currently selected object
*/ */
public ACSObjectSelectionModel(SingleSelectionModel model) { public ACSObjectSelectionModel(final SingleSelectionModel model) {
this(null, null, model); this(null, null, model);
} }
/** /**
* Construct a new <code>ACSObjectSelectionModel</code> * Construct a new <code>ACSObjectSelectionModel</code>
* *
* @param javaClass The name of the Java class which represents * @param javaClass The name of the Java class which represents the object.
* the object. Must be a subclass of {@link ACSObject}. In * Must be a subclass of {@link ACSObject}. In addition, the class must have
* addition, the class must have a constructor with a single * a constructor with a single {@link OID} parameter.
* {@link OID} parameter. * @param objectType The name of the persistence metadata object type which
* @param objectType The name of the persistence metadata object type * represents the ACS object. In practice, will often be the same as the
* which represents the ACS object. In practice, will often be * javaClass.
* the same as the javaClass. * @param parameterName The name of the state parameter which will be used
* @param parameterName The name of the state parameter which will * to store the object ID.
* be used to store the object ID.
*/ */
public ACSObjectSelectionModel( String javaClass, public ACSObjectSelectionModel(final String javaClass,
String objectType, final String objectType,
String parameterName ) { final String parameterName) {
this(javaClass, objectType, new BigDecimalParameter(parameterName)); this(javaClass, objectType, new LongParameter(parameterName));
} }
/** /**
* Construct a new <code>ACSObjectSelectionModel</code> * Construct a new <code>ACSObjectSelectionModel</code>
* *
* @param javaClass The name of the Java class which represents * @param javaClass The name of the Java class which represents the object.
* the object. Must be a subclass of {@link ACSObject}. In * Must be a subclass of {@link ACSObject}. In addition, the class must have
* addition, the class must have a constructor with a single * a constructor with a single {@link OID} parameter.
* {@link OID} parameter. * @param objectType The name of the persistence metadata object type which
* @param objectType The name of the persistence metadata object type * represents the ACS object. In practice, will often be the same as the
* which represents the ACS object. In practice, will often be * javaClass.
* the same as the javaClass. * @param parameter The state parameter which should be used to store the
* @param parameter The state parameter which should be used to store * object ID
* the object ID
*/ */
public ACSObjectSelectionModel( String javaClass, public ACSObjectSelectionModel(final String javaClass,
String objectType, final String objectType,
BigDecimalParameter parameter ) { final LongParameter parameter) {
this(javaClass, objectType, this(javaClass,
objectType,
new ParameterSingleSelectionModel(parameter)); new ParameterSingleSelectionModel(parameter));
} }
/** /**
* Construct a new <code>ACSObjectSelectionModel</code> * Construct a new <code>ACSObjectSelectionModel</code>
* *
* @param javaClass The name of the Java class which represents * @param javaClass The name of the Java class which represents the object.
* the object. Must be a subclass of {@link ACSObject}. In * Must be a subclass of {@link ACSObject}. In addition, the class must have
* addition, the class must have a constructor with a single * a constructor with a single {@link OID} parameter.
* {@link OID} parameter. * @param objectType The name of the persistence metadata object type which
* @param objectType The name of the persistence metadata object type * represents the ACS object. In practice, will often be the same as the
* which represents the ACS object. In practice, will often be * javaClass.
* the same as the javaClass. * @param model The {@link SingleSelectionModel} which will supply a
* @param model The {@link SingleSelectionModel} which will supply * {@link BigDecimal} ID of the currently selected object
* a {@link BigDecimal} ID of the currently selected object
*/ */
public ACSObjectSelectionModel( String javaClass, public ACSObjectSelectionModel(final String javaClass,
String objectType, final String objectType,
SingleSelectionModel model ) { final SingleSelectionModel model) {
m_loaded = new RequestLocal() { loaded = new RequestLocal() {
protected Object initialValue(PageState state) { @Override
return Boolean.FALSE; protected Object initialValue(final PageState state) {
} return Boolean.FALSE;
}; }
};
if (javaClass != null) { if (javaClass != null) {
// Cache the Class object and the constructor for further use // Cache the Class object and the constructor for further use
try { try {
m_javaClass = Class.forName(javaClass); this.javaClassName = Class.forName(javaClass);
m_constructor = m_javaClass.getConstructor(); // this.constructor = javaClassName.getConstructor();
} catch (Exception e) { } catch (ClassNotFoundException | SecurityException ex) {
throw new UncheckedWrapperException( "Problem loading class " throw new UncheckedWrapperException(String.format(
+ javaClass, e ); "Problem loading class %s", javaClass),
ex);
} }
} }
m_objectType = objectType; this.objectType = objectType;
m_model = model; this.selectionModel = model;
} }
/** /**
* Set the ID of the current object. The next time * Set the ID of the current object. The next time
* {@link #getSelectedObject(PageState)} is called, the object * {@link #getSelectedObject(PageState)} is called, the object with the
* with the specified ID will be loaded from the database. * specified ID will be loaded from the database.
* *
* @param state The page state * @param state The page state
* @param key A {@link BigDecimal} primary key for the object, * @param key A {@link BigDecimal} primary key for the object, or a String
* or a String representation of a BigDecimal, such as "42". * representation of a BigDecimal, such as "42".
*/ */
public void setSelectedKey(PageState state, Object key) { @Override
public void setSelectedKey(final PageState state, final Object key) {
//BigDecimal newKey = convertToBigDecimal(key); //BigDecimal newKey = convertToBigDecimal(key);
m_loaded.set(state, Boolean.FALSE); loaded.set(state, Boolean.FALSE);
m_model.setSelectedKey(state, key); selectionModel.setSelectedKey(state, key);
} }
/** /**
* Return the object which was selected and loaded from the database, * Return the object which was selected and loaded from the database, using
* using the values supplied in the page state. May return <code>null</code> * the values supplied in the page state. May return <code>null</code> if
* if <code>isSelected(state) == false</code>, or if the object was not found. * <code>isSelected(state) == false</code>, or if the object was not found.
* *
* @param state The page state * @param state The page state
* @return The currently selected domain object, or null if no object is * @return The currently selected domain object, or null if no object is
* selected. * selected.
*/ */
public CcmObject getSelectedObject(PageState state) { public CcmObject getSelectedObject(final PageState state) {
Long id = convertToLong(getSelectedKey(state)); Long id = convertToLong(getSelectedKey(state));
if (id == null) { if (id == null) {
return null; return null;
} }
return loadACSObject(state, id); return loadACSObject(state, id);
} }
/** /**
* Load the selected object for the first time. Child classes * Load the selected object for the first time. Child classes may choose to
* may choose to override this method in order to load the object * override this method in order to load the object in nonstandard ways. The
* in nonstandard ways. The default implementation merely * default implementation merely instantiates an {@link ACSObject} whose ID
* instantiates an {@link ACSObject} whose ID is the passed-in key. * is the passed-in key.
* *
* @param state the current page state * @param state the current page state
* @param key the currently selected key; guaranteed to be non-null * @param key the currently selected key; guaranteed to be non-null
* @return the object identified by the specified key * @return the object identified by the specified key
* @pre key != null
*/ */
protected CcmObject loadACSObject(PageState state, Object key) { protected CcmObject loadACSObject(final PageState state, final Object key) {
CcmObject item = null;
// Cheesy back-and-forth conversion to ensure that // Cheesy back-and-forth conversion to ensure that
// the result will be a BigDecimal, not a String or // the result will be a BigDecimal, not a String or
// something else. Should go away when ListModel.getKey is // something else. Should go away when ListModel.getKey is
// changed to return an Object. // changed to return an Object.
Long id = convertToLong(key); final Long objectId = convertToLong(key);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final CcmObjectRepository repository = cdiUtil.findBean(
CcmObjectRepository.class);
return repository.findById(objectId);
return CdiUtil.createCdiUtil().findBean(CcmObjectRepository.class).findById(id);
} }
/** /**
@ -307,127 +312,121 @@ public class ACSObjectSelectionModel implements SingleSelectionModel {
* @param state The page state * @param state The page state
* @param object The content item to set * @param object The content item to set
*/ */
public void setSelectedObject(PageState state, CcmObject object) { public void setSelectedObject(final PageState state,
final CcmObject object) {
CcmObject item = object; CcmObject item = object;
if (item == null) { if (item == null) {
m_loaded.set(state, Boolean.FALSE); loaded.set(state, Boolean.FALSE);
m_model.setSelectedKey(state, null); selectionModel.setSelectedKey(state, null);
} else { } else {
m_loaded.set(state, Boolean.TRUE); loaded.set(state, Boolean.TRUE);
m_model.setSelectedKey(state, item.getObjectId()); selectionModel.setSelectedKey(state, item.getObjectId());
} }
} }
/** /**
* Determine if the attempt to load the selected object has * Determine if the attempt to load the selected object has been made yet.
* been made yet. Child classes may use this method to * Child classes may use this method to perform request-local
* perform request-local initialization. * initialisation.
* *
* @param state the page state * @param state the page state
* @return true if the attempt to load the selected object has * @return true if the attempt to load the selected object has already been
* already been made, false otherwise * made, false otherwise
*/ */
public boolean isInitialized(PageState state) { public boolean isInitialized(final PageState state) {
return ((Boolean)m_loaded.get(state)).booleanValue(); return ((Boolean) loaded.get(state));
} }
/** /**
* A utility function which creates a new object with the given ID. * A utility function which creates a new object with the given ID. Uses
* Uses reflection to create the instance of the class supplied * reflection to create the instance of the class supplied in the
* in the constructor to this <code>ACSObjectSelectionModel</code>. * constructor to this <code>ACSObjectSelectionModel</code>. If no class
* If no classname was supplied in the constructor, an assertion * name was supplied in the constructor, an assertion failure will occur.
* failure will occur.
* *
* @param id The id of the new item - this is ignored and the object * @param id The id of the new item - this is ignored and the object will
* will have a different id * have a different id
* @return The newly created item * @return The newly created item
* @throws javax.servlet.ServletException
* @post return != null * @post return != null
* @deprecated This ignores the ID since ACSObject.setID is a no-op * @deprecated This ignores the ID since ACSObject.setID is a no-op
*/ */
public CcmObject createACSObject(Long id) throws ServletException { public CcmObject createACSObject(final Long id) throws ServletException {
return createACSObject(); return createACSObject();
} }
/** /**
* A utility function which creates a new object with the given ID. * A utility function which creates a new object with the given ID. Uses
* Uses reflection to create the instance of the class supplied * reflection to create the instance of the class supplied in the
* in the constructor to this <code>ACSObjectSelectionModel</code>. * constructor to this <code>ACSObjectSelectionModel</code>. If no class
* If no classname was supplied in the constructor, an assertion * name was supplied in the constructor, an assertion failure will occur.
* failure will occur.
* *
* @param id The id of the new item
* @return The newly created item * @return The newly created item
* @throws javax.servlet.ServletException
* @post return != null * @post return != null
*/ */
public CcmObject createACSObject() throws ServletException { public CcmObject createACSObject() throws ServletException {
Assert.exists(m_javaClass, Class.class); Assert.exists(javaClassName, Class.class);
try { try {
CcmObject item = (CcmObject)m_javaClass.newInstance(); final CcmObject object = (CcmObject) javaClassName.newInstance();
return item; return object;
} catch (InstantiationException e) { } catch (InstantiationException | IllegalAccessException ex) {
throw new ServletException(e); throw new ServletException(ex);
} catch (IllegalAccessException e) {
throw new ServletException(e);
} }
} }
/** /**
* @return the Class of the content items which are produced * @return the Class of the content items which are produced by this model
* by this model
*/ */
public Class getJavaClass() { public Class getJavaClass() {
return m_javaClass; return javaClassName;
} }
/** /**
* @return The name of the object type of the * @return The name of the object type of the content items which are
* content items which are produced by this model * produced by this model
*/ */
public String getObjectType() { public String getObjectType() {
return m_objectType; return objectType;
} }
/** /**
* @return the underlying {@link SingleSelectionModel} which * @return the underlying {@link SingleSelectionModel} which maintains the
* maintains the ID of the selected object * ID of the selected object
*/ */
public SingleSelectionModel getSingleSelectionModel() { public SingleSelectionModel getSingleSelectionModel() {
return m_model; return selectionModel;
} }
//////////////////////// ////////////////////////
// //
// Passthrough methods // Passthrough methods
/** /**
* Return <code>true</code> if there is a selected object. * Return <code>true</code> if there is a selected object.
* *
* @param state represents the state of the current request * @param state represents the state of the current request
* @return <code>true</code> if there is a selected component. * @return <code>true</code> if there is a selected component.
*/ */
public boolean isSelected(PageState state) { @Override
return m_model.isSelected(state); public boolean isSelected(final PageState state) {
return selectionModel.isSelected(state);
} }
/** /**
* Return the key that identifies the selected object. * Return the key that identifies the selected object.
* *
* @param state the current page state * @param state the current page state
* @return the {@link BigDecimal} ID of the currently selected * @return the <del>{@link BigDecimal}</del> {@link Long} ID of the
* object, or null if no object is selected. * currently selected object, or null if no object is selected.
* @post return instanceof BigDecimal
* *
*/ */
public Object getSelectedKey(PageState state) { @Override
Object key = m_model.getSelectedKey(state); public Object getSelectedKey(final PageState state) {
Object key = selectionModel.getSelectedKey(state);
return key; return key;
} }
/** /**
* Clear the selection. * Clear the selection.
* *
@ -435,50 +434,54 @@ public class ACSObjectSelectionModel implements SingleSelectionModel {
* @post ! isSelected(state) * @post ! isSelected(state)
* @post ! isInitialized(state) * @post ! isInitialized(state)
*/ */
public void clearSelection(PageState state) { @Override
m_model.clearSelection(state); public void clearSelection(final PageState state) {
m_loaded.set(state, Boolean.FALSE); selectionModel.clearSelection(state);
loaded.set(state, Boolean.FALSE);
} }
/** /**
* Add a change listener to the model. The listener's * Add a change listener to the model. The listener's
* <code>stateChanged</code> is called whenever the selected key changes. * <code>stateChanged</code> is called whenever the selected key changes.
* *
* @param l a listener to notify when the selected key changes * @param listener a listener to notify when the selected key changes
*/ */
public void addChangeListener(ChangeListener l) { @Override
m_model.addChangeListener(l); public void addChangeListener(final ChangeListener listener) {
selectionModel.addChangeListener(listener);
} }
/** /**
* Remove a change listener from the model. * Remove a change listener from the model.
* *
* @param l the listener to remove. * @param listener the listener to remove.
*/ */
public void removeChangeListener(ChangeListener l) { @Override
m_model.removeChangeListener(l); public void removeChangeListener(final ChangeListener listener) {
selectionModel.removeChangeListener(listener);
} }
/** /**
* Return the state parameter which will be used to keep track * Return the state parameter which will be used to keep track of the
* of the currently selected key. Most likely, the parameter will * currently selected key. Most likely, the parameter will be a
* be a {@link BigDecimalParameter}. * {@link BigDecimalParameter}.
* *
* @return The state parameter which should be used to keep * @return The state parameter which should be used to keep track of the ID
* track of the ID of the currently selected object, or null * of the currently selected object, or null if the ID is computed in some
* if the ID is computed in some other way * other way
* @see SingleSelectionModel#getStateParameter() * @see SingleSelectionModel#getStateParameter()
*/ */
@Override
public ParameterModel getStateParameter() { public ParameterModel getStateParameter() {
return m_model.getStateParameter(); return selectionModel.getStateParameter();
} }
private static Long convertToLong(Object value) { private static Long convertToLong(final Object value) {
Long newValue = null; Long newValue = null;
if ( value instanceof Long ) { if (value instanceof Long) {
newValue = (Long) value; newValue = (Long) value;
} else if ( value != null ) { } else if (value != null) {
newValue = Long.parseLong(value.toString()); newValue = Long.parseLong(value.toString());
} }

View File

@ -0,0 +1,107 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.toolbox.ui;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.PageState;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.security.Party;
import org.libreccm.security.PermissionChecker;
/**
* <p>
* Wrapper class that registers access checks (actions) to a Bebop
* component.</p>
*
* @author Michael Pih
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ComponentAccess {
private Component component;
private List<String> accessCheckList;
/**
* @param component The component
*/
public ComponentAccess(final Component component) {
accessCheckList = new ArrayList();
this.component = component;
}
/**
* @param component The component
* @param check An access check
*/
public ComponentAccess(final Component component, final String check) {
this(component);
accessCheckList.add(check);
}
/**
* Add an access check to this component.
*
* @param check The access check
*/
public void addAccessCheck(final String check) {
accessCheckList.add(check);
}
/**
* Get the access checks.
*
* @return The list of access checks
*/
public List<String> getAccessCheckList() {
return accessCheckList;
}
/**
* Get the component.
*
* @return The component
*/
public Component getComponent() {
return component;
}
/**
* Do all the access checks registered to the component pass?
*
* @return true if all the access checks pass, false otherwise
*/
public boolean canAccess() {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionChecker permissionChecker = cdiUtil.findBean(
PermissionChecker.class);
final Optional<Boolean> canAccess = accessCheckList.stream()
.map(accessCheck -> permissionChecker.isPermitted(accessCheck))
.reduce((result1, result2) -> result1 && result2);
return canAccess.orElse(false);
}
}