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-94f89814c4dfpull/2/head
parent
45c8296282
commit
f63434ae80
|
|
@ -23,7 +23,6 @@ import com.arsdigita.bebop.SingleSelectionModel;
|
|||
import com.arsdigita.bebop.parameters.LongParameter;
|
||||
import com.arsdigita.ui.CcmObjectSelectionModel;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.librecms.contentsection.ContentItem;
|
||||
import org.librecms.contentsection.ContentType;
|
||||
|
|
@ -53,6 +52,14 @@ public class ItemSelectionModel extends CcmObjectSelectionModel<ContentItem> {
|
|||
|
||||
private Long typeId;
|
||||
|
||||
public ItemSelectionModel(final LongParameter parameter) {
|
||||
super(parameter);
|
||||
}
|
||||
|
||||
public ItemSelectionModel(final String parameterName) {
|
||||
super(parameterName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new <code>ItemSelectionModel</code>
|
||||
*
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ public class CMSForm extends Form implements Cancellable {
|
|||
* @param state The page state
|
||||
* @return true if the form is cancelled, false otherwise
|
||||
*/
|
||||
public boolean isCancelled(PageState state) {
|
||||
@Override
|
||||
public boolean isCancelled(final PageState state) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <jross@redhat.com>
|
||||
* @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();
|
||||
}
|
||||
}
|
||||
|
|
@ -24,8 +24,10 @@ import com.arsdigita.bebop.FormProcessException;
|
|||
import com.arsdigita.bebop.Label;
|
||||
import com.arsdigita.bebop.Link;
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.ParameterSingleSelectionModel;
|
||||
import com.arsdigita.bebop.Resettable;
|
||||
import com.arsdigita.bebop.SimpleContainer;
|
||||
import com.arsdigita.bebop.SingleSelectionModel;
|
||||
import com.arsdigita.bebop.TabbedPane;
|
||||
import com.arsdigita.bebop.event.ActionEvent;
|
||||
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.PrintEvent;
|
||||
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.StringParameter;
|
||||
import com.arsdigita.cms.CMS;
|
||||
import com.arsdigita.cms.ItemSelectionModel;
|
||||
import com.arsdigita.cms.PageLocations;
|
||||
import com.arsdigita.cms.ui.item.CustomizedPreviewLink;
|
||||
import com.arsdigita.cms.dispatcher.CMSDispatcher;
|
||||
import com.arsdigita.cms.dispatcher.CMSPage;
|
||||
|
|
@ -49,31 +54,43 @@ import com.arsdigita.cms.ui.revision.ItemRevisionAdminPane;
|
|||
import com.arsdigita.cms.ui.templates.ItemTemplates;
|
||||
import com.arsdigita.cms.ui.workflow.ItemWorkflowAdminPane;
|
||||
import com.arsdigita.globalization.GlobalizedMessage;
|
||||
import com.arsdigita.kernel.KernelConfig;
|
||||
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
||||
import com.arsdigita.util.Assert;
|
||||
import com.arsdigita.util.UncheckedWrapperException;
|
||||
import com.arsdigita.xml.Document;
|
||||
import com.arsdigita.xml.Element;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Optional;
|
||||
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.
|
||||
*
|
||||
* @author Michael Pih
|
||||
* @author Stanislav Freidin <sfreidin@redhat.com>
|
||||
* @author <a href="mailto:sfreidin@redhat.com">Stanislav Freidin</a>
|
||||
* @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 {
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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";
|
||||
/**
|
||||
* 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";
|
||||
/**
|
||||
* 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";
|
||||
/**
|
||||
|
|
@ -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_ACTIVE = "active";
|
||||
public static final String STREAMLINED_CREATION_INACTIVE = "active";
|
||||
private static int s_tabOrder = 0;
|
||||
/**
|
||||
* 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
|
||||
* the item the user wishes to create. or edit.</p>
|
||||
* <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
|
||||
* the content type.</p>
|
||||
* <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 int AUTHORING_TAB = s_tabOrder++;
|
||||
public static final int LANGUAGE_TAB = s_tabOrder++;
|
||||
public static final int WORKFLOW_TAB = s_tabOrder++;
|
||||
public static final int PUBLISHING_TAB = s_tabOrder++;
|
||||
public static final int HISTORY_TAB = s_tabOrder++;
|
||||
public static final int TEMPLATES_TAB = s_tabOrder++;
|
||||
private final TabbedPane m_tabbedPane;
|
||||
private StringParameter m_returnURL;
|
||||
private ItemSelectionModel m_itemModel;
|
||||
private ACSObjectSelectionModel m_typeModel;
|
||||
private ContentItemRequestLocal m_item;
|
||||
private Summary m_summaryPane;
|
||||
private ItemWorkflowAdminPane m_workflowPane;
|
||||
private ItemLifecycleAdminPane m_lifecyclePane;
|
||||
private WizardSelector m_wizardPane;
|
||||
private ItemLanguages m_languagesPane;
|
||||
private ItemRevisionAdminPane m_revisionsPane;
|
||||
private ItemTemplates m_templatesPane;
|
||||
private Link m_previewLink;
|
||||
private GlobalNavigation m_globalNavigation;
|
||||
private ContentItemContextBar m_contextBar;
|
||||
public static final int AUTHORING_TAB = 1;
|
||||
public static final int LANGUAGE_TAB = 2;
|
||||
public static final int WORKFLOW_TAB = 3;
|
||||
public static final int PUBLISHING_TAB = 4;
|
||||
public static final int HISTORY_TAB = 5;
|
||||
public static final int TEMPLATES_TAB = 6;
|
||||
|
||||
private final TabbedPane tabbedPane;
|
||||
private final StringParameter returnUrlParameter;
|
||||
private final ItemSelectionModel itemModel;
|
||||
private final SingleSelectionModel<String> selectedLanguageModel;
|
||||
private final ACSObjectSelectionModel typeModel;
|
||||
private final ContentItemRequestLocal itemRequestLocal;
|
||||
private final Summary summaryPane;
|
||||
private final ItemWorkflowAdminPane workflowPane;
|
||||
private final ItemLifecycleAdminPane lifecyclePane;
|
||||
private final WizardSelector wizardPane;
|
||||
private final ItemLanguages languagesPane;
|
||||
private final ItemRevisionAdminPane revisionsPane;
|
||||
private final ItemTemplates templatesPane;
|
||||
private final Link m_previewLink;
|
||||
private final GlobalNavigation m_globalNavigation;
|
||||
private final ContentItemContextBar m_contextBar;
|
||||
|
||||
private class ItemRequestLocal extends ContentItemRequestLocal {
|
||||
|
||||
@Override
|
||||
protected final Object initialValue(final PageState state) {
|
||||
return CMS.getContext().getContentItem();
|
||||
}
|
||||
|
|
@ -140,9 +165,11 @@ public class ContentItemPage extends CMSPage implements ActionListener {
|
|||
|
||||
private class TitlePrinter implements PrintListener {
|
||||
|
||||
public final void prepare(final PrintEvent e) {
|
||||
final Label label = (Label) e.getTarget();
|
||||
final ContentItem item = m_item.getContentItem(e.getPageState());
|
||||
@Override
|
||||
public final void prepare(final PrintEvent event) {
|
||||
final Label label = (Label) event.getTarget();
|
||||
final ContentItem item = itemRequestLocal.getContentItem(event.
|
||||
getPageState());
|
||||
|
||||
label.setLabel(item.getDisplayName());
|
||||
}
|
||||
|
|
@ -154,80 +181,88 @@ public class ContentItemPage extends CMSPage implements ActionListener {
|
|||
public ContentItemPage() {
|
||||
super("", new SimpleContainer());
|
||||
|
||||
m_item = new ItemRequestLocal();
|
||||
itemRequestLocal = new ItemRequestLocal();
|
||||
|
||||
setClassAttr("cms-admin");
|
||||
setTitle(new Label(new TitlePrinter()));
|
||||
|
||||
// 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));
|
||||
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
|
||||
BigDecimalParameter contentType = new BigDecimalParameter(CONTENT_TYPE);
|
||||
final LongParameter contentType = new LongParameter(CONTENT_TYPE);
|
||||
addGlobalStateParam(contentType);
|
||||
|
||||
// Add the streamlined creation global state parameter
|
||||
StringParameter streamlinedCreation = new StringParameter(
|
||||
final StringParameter streamlinedCreation = new StringParameter(
|
||||
STREAMLINED_CREATION);
|
||||
addGlobalStateParam(streamlinedCreation);
|
||||
|
||||
m_typeModel = new ACSObjectSelectionModel(ContentType.class.getName(),
|
||||
ContentType.BASE_DATA_OBJECT_TYPE,
|
||||
contentType);
|
||||
typeModel = new ACSObjectSelectionModel(ContentType.class.getName(),
|
||||
ContentType.class.getName(),
|
||||
contentType);
|
||||
|
||||
// Validate the item ID parameter (caches the validation).
|
||||
getStateModel().addValidationListener(new FormValidationListener() {
|
||||
public void validate(FormSectionEvent event)
|
||||
throws FormProcessException {
|
||||
validateItemID(event.getPageState());
|
||||
}
|
||||
});
|
||||
getStateModel().addValidationListener(
|
||||
event -> validateItemID(event.getPageState()));
|
||||
|
||||
// Add the return url global state parameter
|
||||
m_returnURL = new StringParameter(RETURN_URL);
|
||||
addGlobalStateParam(m_returnURL);
|
||||
returnUrlParameter = new StringParameter(RETURN_URL);
|
||||
addGlobalStateParam(returnUrlParameter);
|
||||
|
||||
m_globalNavigation = new GlobalNavigation();
|
||||
add(m_globalNavigation);
|
||||
|
||||
m_contextBar = new ContentItemContextBar(m_itemModel);
|
||||
m_contextBar = new ContentItemContextBar(itemModel);
|
||||
add(m_contextBar);
|
||||
|
||||
// Create panels.
|
||||
m_summaryPane = new Summary(m_itemModel);
|
||||
m_wizardPane = new WizardSelector(m_itemModel, m_typeModel);
|
||||
m_languagesPane = new ItemLanguages(m_itemModel);
|
||||
m_workflowPane = new ItemWorkflowAdminPane(itemId); // Make this use m_item XXX
|
||||
m_lifecyclePane = new ItemLifecycleAdminPane(m_item);
|
||||
m_revisionsPane = new ItemRevisionAdminPane(m_item);
|
||||
m_templatesPane = new ItemTemplates(m_itemModel);
|
||||
summaryPane = new Summary(itemModel);
|
||||
wizardPane = new WizardSelector(itemModel, typeModel);
|
||||
languagesPane = new ItemLanguages(itemModel, selectedLanguageModel);
|
||||
workflowPane = new ItemWorkflowAdminPane(itemId); // Make this use m_item XXX
|
||||
lifecyclePane = new ItemLifecycleAdminPane(itemRequestLocal);
|
||||
revisionsPane = new ItemRevisionAdminPane(itemRequestLocal);
|
||||
templatesPane = new ItemTemplates(itemModel);
|
||||
|
||||
// Create tabbed pane.
|
||||
m_tabbedPane = new TabbedPane();
|
||||
add(m_tabbedPane);
|
||||
tabbedPane = new TabbedPane();
|
||||
add(tabbedPane);
|
||||
|
||||
m_tabbedPane.setIdAttr("page-body");
|
||||
tabbedPane.setIdAttr("page-body");
|
||||
|
||||
m_tabbedPane.addTab(new Label(gz("cms.ui.item.summary")), m_summaryPane);
|
||||
m_tabbedPane.addTab(new Label(gz("cms.ui.item.authoring")), m_wizardPane);
|
||||
m_tabbedPane.addTab(new Label(gz("cms.ui.item.languages")),
|
||||
m_languagesPane);
|
||||
m_tabbedPane.addTab(new Label(gz("cms.ui.item.workflow")),
|
||||
m_workflowPane);
|
||||
m_tabbedPane.addTab(new Label(gz("cms.ui.item.lifecycles")),
|
||||
m_lifecyclePane);
|
||||
m_tabbedPane.addTab(new Label(gz("cms.ui.item.history")),
|
||||
m_revisionsPane);
|
||||
m_tabbedPane.addTab(new Label(gz("cms.ui.item.templates")),
|
||||
m_templatesPane);
|
||||
tabbedPane.addTab(new Label(gz("cms.ui.item.summary")), summaryPane);
|
||||
tabbedPane.
|
||||
addTab(new Label(gz("cms.ui.item.authoring")), wizardPane);
|
||||
tabbedPane.addTab(new Label(gz("cms.ui.item.languages")),
|
||||
languagesPane);
|
||||
tabbedPane.addTab(new Label(gz("cms.ui.item.workflow")),
|
||||
workflowPane);
|
||||
tabbedPane.addTab(new Label(gz("cms.ui.item.lifecycles")),
|
||||
lifecyclePane);
|
||||
tabbedPane.addTab(new Label(gz("cms.ui.item.history")),
|
||||
revisionsPane);
|
||||
tabbedPane.addTab(new Label(gz("cms.ui.item.templates")),
|
||||
templatesPane);
|
||||
|
||||
m_tabbedPane.addActionListener(new ActionListener() {
|
||||
public final void actionPerformed(final ActionEvent e) {
|
||||
final PageState state = e.getPageState();
|
||||
final Component pane = m_tabbedPane.getCurrentPane(state);
|
||||
tabbedPane.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public final void actionPerformed(final ActionEvent event) {
|
||||
|
||||
final PageState state = event.getPageState();
|
||||
final Component pane = tabbedPane.getCurrentPane(state);
|
||||
|
||||
if (pane instanceof Resettable) {
|
||||
((Resettable) pane).reset(state);
|
||||
|
|
@ -237,13 +272,15 @@ public class ContentItemPage extends CMSPage implements ActionListener {
|
|||
|
||||
// Build the preview link.
|
||||
m_previewLink = new Link(new Label(gz("cms.ui.preview")),
|
||||
new PrintListener() {
|
||||
public final void prepare(final PrintEvent e) {
|
||||
final Link link = (Link) e.getTarget();
|
||||
link.setTarget(getPreviewURL(e.getPageState()));
|
||||
link.setTargetFrame(Link.NEW_FRAME);
|
||||
}
|
||||
});
|
||||
new PrintListener() {
|
||||
@Override
|
||||
public final void prepare(final PrintEvent event) {
|
||||
final Link link = (Link) event.getTarget();
|
||||
link.setTarget(getPreviewURL(event.
|
||||
getPageState()));
|
||||
link.setTargetFrame(Link.NEW_FRAME);
|
||||
}
|
||||
});
|
||||
m_previewLink.setIdAttr("preview_link");
|
||||
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
|
||||
getStateModel().addValidationListener(new FormValidationListener() {
|
||||
public void validate(FormSectionEvent e) throws FormProcessException {
|
||||
PageState s = e.getPageState();
|
||||
FormData data = e.getFormData();
|
||||
final ContentItem item = m_item.getContentItem(s);
|
||||
if (item != null && ContentItem.LIVE.equals(item.getVersion())) {
|
||||
s_log.error(String.format(
|
||||
"The item %d is live and cannot be edited.", item.getID()));
|
||||
// data.addError(err);
|
||||
throw new FormProcessException(GlobalizationUtil.globalize(
|
||||
"cms.ui.live_item_not_editable"));
|
||||
|
||||
@Override
|
||||
public void validate(final FormSectionEvent event)
|
||||
throws FormProcessException {
|
||||
|
||||
PageState s = event.getPageState();
|
||||
FormData data = event.getFormData();
|
||||
final ContentItem item = itemRequestLocal.getContentItem(s);
|
||||
if (item != null
|
||||
&& 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
|
||||
* @exception FormProcessException if the item_id is not valid
|
||||
*/
|
||||
protected void validateItemID(PageState state) throws FormProcessException {
|
||||
final ContentItem item = m_item.getContentItem(state);
|
||||
protected void validateItemID(final PageState state) throws
|
||||
FormProcessException {
|
||||
final ContentItem item = itemRequestLocal.getContentItem(state);
|
||||
|
||||
if (item == null) {
|
||||
throw new FormProcessException(GlobalizationUtil.globalize(
|
||||
"cms.ui.invalid_item_id"));
|
||||
throw new FormProcessException(new GlobalizedMessage(
|
||||
"cms.ui.invalid_item_id", CmsConstants.CMS_BUNDLE));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -294,7 +336,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
|
|||
* @return The current content section
|
||||
*/
|
||||
@Override
|
||||
public ContentSection getContentSection(HttpServletRequest request) {
|
||||
public ContentSection getContentSection(final HttpServletRequest request) {
|
||||
// Resets all content sections associations.
|
||||
ContentSection section = super.getContentSection(request);
|
||||
Assert.exists(section);
|
||||
|
|
@ -310,54 +352,49 @@ public class ContentItemPage extends CMSPage implements ActionListener {
|
|||
* @return The current content item, null if there is none
|
||||
*/
|
||||
@Override
|
||||
public ContentItem getContentItem(PageState state) {
|
||||
return (ContentItem) m_itemModel.getSelectedObject(state);
|
||||
public ContentItem getContentItem(final PageState state) {
|
||||
return (ContentItem) itemModel.getSelectedObject(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 String setTab = state.getRequest().getParameter(SET_TAB);
|
||||
|
||||
// Hide the templates tab, the workflow tab, and the preview
|
||||
// link if the current item is a template.
|
||||
final ContentItem item = m_item.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);
|
||||
}
|
||||
}
|
||||
final ContentItem item = itemRequestLocal.getContentItem(state);
|
||||
|
||||
// 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
|
||||
if (setTab != null) {
|
||||
Integer tab = null;
|
||||
Integer tab;
|
||||
|
||||
try {
|
||||
tab = Integer.valueOf(setTab);
|
||||
} catch (NumberFormatException e) {
|
||||
} catch (NumberFormatException ex) {
|
||||
// Stop processing set_tab parameter.
|
||||
LOGGER.warn("Stopping processing of set_tab parameter.", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tab.intValue() < m_tabbedPane.size()) {
|
||||
m_tabbedPane.setSelectedIndex(state, tab.intValue());
|
||||
if (tab < tabbedPane.size()) {
|
||||
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 itemId The id of the item to display
|
||||
* @param tab The index of the tab to display
|
||||
* @return
|
||||
*/
|
||||
public static String getItemURL(String nodeURL,
|
||||
BigDecimal itemId,
|
||||
int tab) {
|
||||
public static String getItemURL(final String nodeURL,
|
||||
final Long itemId,
|
||||
final int tab) {
|
||||
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 tab The index of the tab to display
|
||||
* @param streamlinedCreation Whether to activate Streamlined item authoring
|
||||
* @return
|
||||
*/
|
||||
public static String getItemURL(String nodeURL,
|
||||
BigDecimal itemId,
|
||||
int tab,
|
||||
boolean streamlinedCreation) {
|
||||
StringBuffer url = new StringBuffer();
|
||||
public static String getItemURL(final String nodeURL,
|
||||
final Long itemId,
|
||||
final int tab,
|
||||
final boolean streamlinedCreation) {
|
||||
final StringBuilder urlBuilder = new StringBuilder();
|
||||
|
||||
url.append(nodeURL).append(PageLocations.ITEM_PAGE).append("?").append(
|
||||
ITEM_ID).append("=").append(itemId.toString()).append("&").
|
||||
append(SET_TAB).append("=").append(tab);
|
||||
urlBuilder
|
||||
.append(nodeURL)
|
||||
.append(PageLocations.ITEM_PAGE)
|
||||
.append("?")
|
||||
.append(ITEM_ID)
|
||||
.append("=")
|
||||
.append(itemId.toString())
|
||||
.append("&")
|
||||
.append(SET_TAB)
|
||||
.append("=")
|
||||
.append(tab);
|
||||
|
||||
if (streamlinedCreation && ContentSection.getConfig().
|
||||
getUseStreamlinedCreation()) {
|
||||
url.append("&").append(STREAMLINED_CREATION).append("=").append(
|
||||
STREAMLINED_CREATION_ACTIVE);
|
||||
if (streamlinedCreation
|
||||
&& CMSConfig.getConfig().isUseStreamlinedCreation()) {
|
||||
|
||||
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
|
||||
*/
|
||||
public static String getRelativeItemURL(BigDecimal itemId, int tab) {
|
||||
StringBuffer url = new StringBuffer();
|
||||
url.append(PageLocations.ITEM_PAGE).append("?").append(ITEM_ID).append("=").append(itemId.
|
||||
toString()).append("&").append(SET_TAB).append("=").append(tab);
|
||||
public static String getRelativeItemURL(final Long itemId, final int tab) {
|
||||
final StringBuilder url = new StringBuilder();
|
||||
url
|
||||
.append(PageLocations.ITEM_PAGE)
|
||||
.append("?")
|
||||
.append(ITEM_ID)
|
||||
.append("=")
|
||||
.append(itemId.toString())
|
||||
.append("&")
|
||||
.append(SET_TAB)
|
||||
.append("=")
|
||||
.append(tab);
|
||||
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
|
|
@ -417,16 +480,18 @@ public class ContentItemPage extends CMSPage implements ActionListener {
|
|||
*
|
||||
* @param item the ContentItem object to display
|
||||
* @param tab The index of the tab to display
|
||||
* @return
|
||||
*/
|
||||
public static String getItemURL(ContentItem item, int tab) {
|
||||
final ContentSection section = item.getContentSection();
|
||||
public static String getItemURL(final ContentItem item,
|
||||
final int tab) {
|
||||
final ContentSection section = item.getContentType().getContentSection();
|
||||
|
||||
if (section == null) {
|
||||
return null;
|
||||
} 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 tab The index of the tab to display
|
||||
* @return
|
||||
*/
|
||||
public static String getItemURL(long itemId, int tab) {
|
||||
final ContentItem item =
|
||||
(ContentItem) DomainObjectFactory.newInstance(new OID(
|
||||
ContentItem.BASE_DATA_OBJECT_TYPE, itemId));
|
||||
public static String getItemURL(final long itemId,
|
||||
final int tab) {
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final ContentItemRepository itemRepo = cdiUtil.findBean(
|
||||
ContentItemRepository.class);
|
||||
|
||||
if (item == null) {
|
||||
return null;
|
||||
final Optional<ContentItem> item = itemRepo.findById(itemId);
|
||||
|
||||
if (item.isPresent()) {
|
||||
return getItemURL(item.get(), tab);
|
||||
} else {
|
||||
return getItemURL(item, tab);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -454,12 +523,12 @@ public class ContentItemPage extends CMSPage implements ActionListener {
|
|||
*
|
||||
* @param state The current page state
|
||||
*/
|
||||
public void redirectBack(PageState state) {
|
||||
public void redirectBack(final PageState state) {
|
||||
try {
|
||||
String returnURL = (String) state.getValue(m_returnURL);
|
||||
state.getResponse().sendRedirect(returnURL);
|
||||
} catch (IOException e) {
|
||||
s_log.error("IO Error redirecting back", e);
|
||||
final String returnUrl = (String) state.getValue(returnUrlParameter);
|
||||
state.getResponse().sendRedirect(returnUrl);
|
||||
} catch (IOException ex) {
|
||||
LOGGER.error("IO Error redirecting back", ex);
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
|
@ -467,13 +536,13 @@ public class ContentItemPage extends CMSPage implements ActionListener {
|
|||
/**
|
||||
* Fetch the preview URL.
|
||||
*/
|
||||
private String getPreviewURL(PageState state) {
|
||||
final ContentItem item = m_item.getContentItem(state);
|
||||
private String getPreviewURL(final PageState state) {
|
||||
final ContentItem item = itemRequestLocal.getContentItem(state);
|
||||
|
||||
if (item instanceof CustomizedPreviewLink) {
|
||||
final String previewLink = ((CustomizedPreviewLink) item).
|
||||
getPreviewUrl(
|
||||
state);
|
||||
state);
|
||||
if ((previewLink == null) || previewLink.isEmpty()) {
|
||||
return getDefaultPreviewLink(state, item);
|
||||
} else {
|
||||
|
|
@ -491,49 +560,66 @@ public class ContentItemPage extends CMSPage implements ActionListener {
|
|||
* @return
|
||||
*/
|
||||
private String getDefaultPreviewLink(final PageState state,
|
||||
final ContentItem item) {
|
||||
final ContentItem item) {
|
||||
final ContentSection section = CMS.getContext().getContentSection();
|
||||
//ContentSection section = getContentSection(state);
|
||||
final ItemResolver itemResolver = section.getItemResolver();
|
||||
final ItemResolver itemResolver;
|
||||
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
|
||||
return itemResolver.generateItemURL(state, item, section,
|
||||
CMSDispatcher.PREVIEW);
|
||||
return itemResolver.generateItemURL(state,
|
||||
item,
|
||||
section,
|
||||
CMSDispatcher.PREVIEW);
|
||||
}
|
||||
|
||||
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) {
|
||||
return (String) gz(key).localize();
|
||||
}
|
||||
|
||||
public static boolean isStreamlinedCreationActive(PageState state) {
|
||||
return ContentSection.getConfig().getUseStreamlinedCreation()
|
||||
&& STREAMLINED_CREATION_ACTIVE.equals(state.getRequest().
|
||||
getParameter(STREAMLINED_CREATION));
|
||||
public static boolean isStreamlinedCreationActive(final PageState state) {
|
||||
return CMSConfig.getConfig().isUseStreamlinedCreation()
|
||||
&& STREAMLINED_CREATION_ACTIVE.equals(state.getRequest().
|
||||
getParameter(STREAMLINED_CREATION));
|
||||
}
|
||||
|
||||
protected TabbedPane getTabbedPane() {
|
||||
return m_tabbedPane;
|
||||
return tabbedPane;
|
||||
}
|
||||
|
||||
protected WizardSelector getWizardPane() {
|
||||
return m_wizardPane;
|
||||
return wizardPane;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the content type to the output.
|
||||
*
|
||||
*
|
||||
* @param state PageState
|
||||
* @param parent Parent document
|
||||
* @return page
|
||||
*/
|
||||
protected Element generateXMLHelper(PageState state, Document parent) {
|
||||
Element page = super.generateXMLHelper(state, parent);
|
||||
Element contenttype = page.newChildElement("bebop:contentType", BEBOP_XML_NS);
|
||||
contenttype.setText(m_item.getContentItem(state).getContentType().getName());
|
||||
@Override
|
||||
protected Element generateXMLHelper(final PageState state,
|
||||
final Document parent) {
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -43,6 +43,7 @@ import com.arsdigita.cms.ui.authoring.LanguageWidget;
|
|||
import org.librecms.util.LanguageUtil;
|
||||
|
||||
import com.arsdigita.globalization.GlobalizedMessage;
|
||||
import com.arsdigita.kernel.KernelConfig;
|
||||
import com.arsdigita.toolbox.ui.ActionGroup;
|
||||
import com.arsdigita.toolbox.ui.LayoutPanel;
|
||||
import com.arsdigita.toolbox.ui.Section;
|
||||
|
|
@ -60,8 +61,11 @@ import org.librecms.contentsection.ContentItemL10NManager;
|
|||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.TooManyListenersException;
|
||||
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
|
||||
|
|
@ -81,10 +85,10 @@ public class ItemLanguages extends LayoutPanel {
|
|||
/**
|
||||
* Constructs a new <code>ItemLanguages</code>.
|
||||
*
|
||||
* @param selectionModel the {@link ItemSelectionModel} which will supply
|
||||
* the current item
|
||||
* @param selectionModel the {@link ItemSelectionModel} which will supply
|
||||
* the current item
|
||||
* @param selectedLanguage {@link SingleSelectionModel} for the selected
|
||||
* language.
|
||||
* language.
|
||||
*/
|
||||
public ItemLanguages(final ItemSelectionModel selectionModel,
|
||||
final SingleSelectionModel<String> selectedLanguage) {
|
||||
|
|
@ -141,22 +145,22 @@ public class ItemLanguages extends LayoutPanel {
|
|||
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final LanguageUtil languageUtil = cdiUtil.findBean(
|
||||
LanguageUtil.class);
|
||||
LanguageUtil.class);
|
||||
final ContentItemL10NManager l10NManager = cdiUtil.findBean(
|
||||
ContentItemL10NManager.class);
|
||||
ContentItemL10NManager.class);
|
||||
|
||||
final List<String> creatableLangs = l10NManager.creatableLocales(
|
||||
item).stream()
|
||||
.map(locale -> locale.toString())
|
||||
.collect(Collectors.toList());
|
||||
item).stream()
|
||||
.map(locale -> locale.toString())
|
||||
.collect(Collectors.toList());
|
||||
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 GlobalizedMessage langName
|
||||
= (GlobalizedMessage) pair
|
||||
.getValue();
|
||||
= (GlobalizedMessage) pair
|
||||
.getValue();
|
||||
optionGroup.addOption(new Option(langCode, new Label(langName)));
|
||||
}
|
||||
}
|
||||
|
|
@ -170,64 +174,46 @@ public class ItemLanguages extends LayoutPanel {
|
|||
|
||||
@Override
|
||||
public final void process(final FormSectionEvent event)
|
||||
throws FormProcessException {
|
||||
PageState state = event.getPageState();
|
||||
String lang = (String) languageWidget.getValue(state);
|
||||
ContentPage item = (ContentPage) selectionModel.getSelectedItem(
|
||||
state);
|
||||
ContentBundle bundle = item.getContentBundle();
|
||||
String name = bundle.getName();
|
||||
throws FormProcessException {
|
||||
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
|
||||
final PageState state = event.getPageState();
|
||||
final String lang = (String) languageWidget.getValue(state);
|
||||
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)) {
|
||||
ContentSection section = item.getContentSection();
|
||||
final ContentSection section = item.getContentType().
|
||||
getContentSection();
|
||||
|
||||
Assert.exists(section, ContentSection.class);
|
||||
|
||||
ContentType type = item.getContentType();
|
||||
|
||||
item = (ContentPage) item.copy(lang);
|
||||
item.setLanguage(lang);
|
||||
item.setName(name);
|
||||
|
||||
// Apply default workflow
|
||||
WorkflowTemplate template
|
||||
= ContentTypeWorkflowTemplate
|
||||
.getWorkflowTemplate(section, type);
|
||||
if (template != null) {
|
||||
Workflow w = template.instantiateNewWorkflow();
|
||||
w.setObjectID(item.getID());
|
||||
w.start(Kernel.getContext().getUser());
|
||||
w.save();
|
||||
}
|
||||
|
||||
selectionModel.setSelectedObject(state, item);
|
||||
final ContentItemL10NManager l10NManager = cdiUtil.findBean(
|
||||
ContentItemL10NManager.class);
|
||||
l10NManager.addLanguage(item, new Locale(lang));
|
||||
|
||||
// redirect to ContentItemPage.AUTHORING_TAB of the new instance
|
||||
final String target = URL.getDispatcherPath() + ContentItemPage.
|
||||
getItemURL(item,
|
||||
ContentItemPage.AUTHORING_TAB);
|
||||
|
||||
final String target = String.join(
|
||||
"", URL.getDispatcherPath(),
|
||||
ContentItemPage.getItemURL(item,
|
||||
ContentItemPage.AUTHORING_TAB));
|
||||
|
||||
throw new RedirectSignal(target, true);
|
||||
} else if (changeSubmit.isSelected(state)) {
|
||||
String oldLang = item.getLanguage();
|
||||
item.setLanguage(lang);
|
||||
// propagate language change to the Name attribute
|
||||
item.setName(name);
|
||||
item.save();
|
||||
|
||||
// if the item being changed is the default, update the bundle
|
||||
// to keep this item as the default
|
||||
if (bundle.getDefaultLanguage().equals(oldLang)) {
|
||||
bundle.setDefaultLanguage(lang);
|
||||
bundle.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static final GlobalizedMessage gz(final String key) {
|
||||
return GlobalizationUtil.globalize(key);
|
||||
return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE);
|
||||
}
|
||||
|
||||
protected static final String lz(final String key) {
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ public class ItemLanguagesTable extends Table {
|
|||
final ContentItemL10NManager l10nManager = cdiUtil.findBean(
|
||||
ContentItemL10NManager.class);
|
||||
|
||||
l10nManager.removeLangauge(item, new Locale(selectedLang));
|
||||
l10nManager.removeLanguage(item, new Locale(selectedLang));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -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(" -> ",
|
||||
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(" -> ", 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 <jross@redhat.com>
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -40,8 +40,6 @@ import org.libreccm.security.User;
|
|||
import com.arsdigita.toolbox.ui.ActionGroup;
|
||||
import com.arsdigita.toolbox.ui.PropertyList;
|
||||
import com.arsdigita.toolbox.ui.Section;
|
||||
import com.arsdigita.util.UncheckedWrapperException;
|
||||
import com.arsdigita.web.Web;
|
||||
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.libreccm.security.Shiro;
|
||||
|
|
@ -49,48 +47,45 @@ import org.libreccm.workflow.Task;
|
|||
import org.libreccm.workflow.TaskManager;
|
||||
import org.libreccm.workflow.TaskRepository;
|
||||
import org.libreccm.workflow.Workflow;
|
||||
import org.libreccm.workflow.WorkflowManager;
|
||||
import org.librecms.CmsConstants;
|
||||
import org.librecms.contentsection.privileges.AdminPrivileges;
|
||||
import org.librecms.workflow.CmsTaskType;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
abstract class BaseWorkflowItemPane extends BaseItemPane {
|
||||
|
||||
final WorkflowRequestLocal m_workflow;
|
||||
final TaskRequestLocal m_task;
|
||||
final WorkflowRequestLocal workflowRequestLocal;
|
||||
final TaskRequestLocal taskRequestLocal;
|
||||
|
||||
ActionGroup m_actionGroup;
|
||||
final TaskTable m_tasks;
|
||||
ActionGroup actionGroup;
|
||||
final TaskTable taskTable;
|
||||
|
||||
final SimpleContainer m_detailPane;
|
||||
final TaskItemPane m_taskPane;
|
||||
final SummarySection m_summarySection;
|
||||
final SimpleContainer detailPane;
|
||||
final TaskItemPane taskItemPane;
|
||||
final SummarySection summarySection;
|
||||
|
||||
public BaseWorkflowItemPane(final WorkflowRequestLocal workflow,
|
||||
final ActionLink editLink,
|
||||
final ActionLink deleteLink) {
|
||||
m_workflow = workflow;
|
||||
workflowRequestLocal = workflow;
|
||||
|
||||
m_tasks = new TaskTable();
|
||||
m_task = new TaskSelectionRequestLocal();
|
||||
taskTable = new TaskTable();
|
||||
taskRequestLocal = new TaskSelectionRequestLocal();
|
||||
|
||||
m_detailPane = new SimpleContainer();
|
||||
detailPane = new SimpleContainer();
|
||||
|
||||
// Tasks
|
||||
final FinishLink taskFinishLink = new FinishLink();
|
||||
|
||||
final ActionLink taskAddLink = new ActionLink(new Label(gz(
|
||||
"cms.ui.workflow.task.add")));
|
||||
final TaskAddForm taskAddForm = new TaskAddForm(m_workflow, m_tasks
|
||||
final TaskAddForm taskAddForm = new TaskAddForm(workflowRequestLocal, taskTable
|
||||
.getRowSelectionModel());
|
||||
|
||||
final ActionLink taskEditLink = new ActionLink(new Label(gz(
|
||||
"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(
|
||||
"cms.ui.workflow.task.delete")));
|
||||
|
|
@ -100,31 +95,31 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
|
|||
"cms.ui.workflow.task.return")));
|
||||
backLink.addActionListener(new ResetListener());
|
||||
|
||||
m_taskPane = new TaskItemPane(m_workflow, m_task,
|
||||
taskItemPane = new TaskItemPane(workflowRequestLocal, taskRequestLocal,
|
||||
taskFinishLink, taskEditLink,
|
||||
taskDeleteLink, backLink);
|
||||
|
||||
m_summarySection = new SummarySection(editLink, deleteLink);
|
||||
m_detailPane.add(m_summarySection);
|
||||
m_detailPane.add(new TaskSection(taskAddLink));
|
||||
summarySection = new SummarySection(editLink, deleteLink);
|
||||
detailPane.add(summarySection);
|
||||
detailPane.add(new TaskSection(taskAddLink));
|
||||
|
||||
add(m_detailPane);
|
||||
setDefault(m_detailPane);
|
||||
add(m_taskPane);
|
||||
add(detailPane);
|
||||
setDefault(detailPane);
|
||||
add(taskItemPane);
|
||||
add(taskAddForm);
|
||||
add(taskEditForm);
|
||||
add(taskDeleteForm);
|
||||
|
||||
connect(m_tasks, 0, m_taskPane);
|
||||
connect(taskTable, 0, taskItemPane);
|
||||
|
||||
connect(taskAddLink, taskAddForm);
|
||||
connect(taskAddForm, m_taskPane);
|
||||
connect(taskAddForm, taskItemPane);
|
||||
|
||||
connect(taskEditLink, taskEditForm);
|
||||
connect(taskEditForm);
|
||||
|
||||
connect(taskDeleteLink, taskDeleteForm);
|
||||
connect(taskDeleteForm, m_detailPane);
|
||||
connect(taskDeleteForm, detailPane);
|
||||
}
|
||||
|
||||
protected class AdminVisible extends VisibilityComponent {
|
||||
|
|
@ -146,7 +141,7 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
|
|||
|
||||
@Override
|
||||
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 CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final Shiro shiro = cdiUtil.findBean(Shiro.class);
|
||||
|
|
@ -165,7 +160,7 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
|
|||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final TaskManager taskManager = cdiUtil.findBean(TaskManager.class);
|
||||
|
||||
final Task task = m_task.getTask(state);
|
||||
final Task task = taskRequestLocal.getTask(state);
|
||||
taskManager.finish(task);
|
||||
}
|
||||
|
||||
|
|
@ -177,7 +172,7 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
|
|||
public void reset(final PageState state) {
|
||||
super.reset(state);
|
||||
|
||||
m_tasks.getRowSelectionModel().clearSelection(state);
|
||||
taskTable.getRowSelectionModel().clearSelection(state);
|
||||
}
|
||||
|
||||
private class TaskDeleteForm extends BaseDeleteForm {
|
||||
|
|
@ -197,10 +192,10 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
|
|||
final TaskRepository taskRepo = cdiUtil.findBean(
|
||||
TaskRepository.class);
|
||||
|
||||
final Task task = m_task.getTask(state);
|
||||
final Task task = taskRequestLocal.getTask(state);
|
||||
taskRepo.delete(task);
|
||||
|
||||
m_tasks.getRowSelectionModel().clearSelection(state);
|
||||
taskTable.getRowSelectionModel().clearSelection(state);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -209,7 +204,7 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
|
|||
|
||||
@Override
|
||||
protected final Object initialValue(final PageState state) {
|
||||
final String key = m_tasks.getRowSelectionModel().getSelectedKey(
|
||||
final String key = taskTable.getRowSelectionModel().getSelectedKey(
|
||||
state).toString();
|
||||
|
||||
return CmsTaskType.valueOf(key);
|
||||
|
|
@ -223,13 +218,13 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
|
|||
final ActionLink deleteLink) {
|
||||
setHeading(new Label(gz("cms.ui.workflow.details")));
|
||||
|
||||
m_actionGroup = new ActionGroup();
|
||||
setBody(m_actionGroup);
|
||||
actionGroup = new ActionGroup();
|
||||
setBody(actionGroup);
|
||||
|
||||
m_actionGroup.setSubject(new Properties());
|
||||
m_actionGroup.addAction(new AdminVisible(editLink),
|
||||
actionGroup.setSubject(new Properties());
|
||||
actionGroup.addAction(new AdminVisible(editLink),
|
||||
ActionGroup.EDIT);
|
||||
m_actionGroup.addAction(new AdminVisible(deleteLink),
|
||||
actionGroup.addAction(new AdminVisible(deleteLink),
|
||||
ActionGroup.DELETE);
|
||||
}
|
||||
|
||||
|
|
@ -239,7 +234,7 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
|
|||
protected final List<Property> properties(final PageState state) {
|
||||
@SuppressWarnings("unchecked")
|
||||
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 Locale defaultLocale = kernelConfig.getDefaultLocale();
|
||||
|
|
@ -269,7 +264,7 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
|
|||
final ActionGroup group = new ActionGroup();
|
||||
setBody(group);
|
||||
|
||||
group.setSubject(m_tasks);
|
||||
group.setSubject(taskTable);
|
||||
group.addAction(new AdminVisible(taskAddLink), ActionGroup.ADD);
|
||||
}
|
||||
|
||||
|
|
@ -286,7 +281,7 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
|
|||
private class TaskTable extends Table {
|
||||
|
||||
public TaskTable() {
|
||||
super(new TaskTableModelBuilder(m_workflow), s_columns);
|
||||
super(new TaskTableModelBuilder(workflowRequestLocal), s_columns);
|
||||
|
||||
setEmptyView(new Label(gz("cms.ui.workflow.task.none")));
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <jross@redhat.com>
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -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 <jross@redhat.com>
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -179,7 +179,6 @@ public final class TaskFinishForm extends CommentAddForm {
|
|||
final TaskManager taskManager = cdiUtil.findBean(TaskManager.class);
|
||||
final AssignableTaskManager assignableTaskManager = cdiUtil
|
||||
.findBean(AssignableTaskManager.class);
|
||||
final Shiro shiro = cdiUtil.findBean(Shiro.class);
|
||||
final ConfigurationManager confManager = cdiUtil.findBean(
|
||||
ConfigurationManager.class);
|
||||
final KernelConfig kernelConfig = confManager.findConfiguration(
|
||||
|
|
@ -221,7 +220,6 @@ public final class TaskFinishForm extends CommentAddForm {
|
|||
final TaskFinishFormController controller = cdiUtil.findBean(
|
||||
TaskFinishFormController.class);
|
||||
final Workflow workflow = task.getWorkflow();
|
||||
final User user = shiro.getUser();
|
||||
final List<AssignableTask> tasks = controller.findEnabledTasks(
|
||||
workflow);
|
||||
for (final AssignableTask currentTask : tasks) {
|
||||
|
|
@ -243,7 +241,7 @@ public final class TaskFinishForm extends CommentAddForm {
|
|||
throw new RedirectSignal(
|
||||
URL.there(state.getRequest(),
|
||||
ContentItemPage.getItemURL(
|
||||
item,
|
||||
item.get(),
|
||||
ContentItemPage.PUBLISHING_TAB)),
|
||||
true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <jross@redhat.com>
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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())));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -308,7 +308,7 @@ public class ContentItemL10NManager {
|
|||
*/
|
||||
@AuthorizationRequired
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public void removeLangauge(
|
||||
public void removeLanguage(
|
||||
@RequiresPrivilege(ItemPrivileges.EDIT)
|
||||
final ContentItem item,
|
||||
final Locale locale) {
|
||||
|
|
@ -330,7 +330,7 @@ public class ContentItemL10NManager {
|
|||
}
|
||||
|
||||
findLocalizedStringProperties(item)
|
||||
.forEach(property -> removeLanguage(item, locale, property));
|
||||
.forEach(property -> ContentItemL10NManager.this.removeLanguage(item, locale, property));
|
||||
|
||||
itemRepo.save(item);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ public class ContentItemL10NManagerTest {
|
|||
|
||||
/**
|
||||
* 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
|
||||
@InSequence(70)
|
||||
|
|
@ -313,12 +313,12 @@ public class ContentItemL10NManagerTest {
|
|||
final Optional<ContentItem> item = itemRepo.findById(-10100L);
|
||||
assertThat(item.isPresent(), is(true));
|
||||
|
||||
l10nManager.removeLangauge(item.get(), Locale.FRENCH);
|
||||
l10nManager.removeLanguage(item.get(), Locale.FRENCH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@Test
|
||||
|
|
@ -332,12 +332,12 @@ public class ContentItemL10NManagerTest {
|
|||
final Optional<ContentItem> item = itemRepo.findById(-10100L);
|
||||
assertThat(item.isPresent(), is(true));
|
||||
|
||||
l10nManager.removeLangauge(item.get(), Locale.GERMAN);
|
||||
l10nManager.removeLanguage(item.get(), Locale.GERMAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}
|
||||
* for the item.
|
||||
*/
|
||||
|
|
@ -352,12 +352,12 @@ public class ContentItemL10NManagerTest {
|
|||
public void removeLanguageItemIsNull() {
|
||||
final ContentItem item = null;
|
||||
|
||||
l10nManager.removeLangauge(item, Locale.GERMAN);
|
||||
l10nManager.removeLanguage(item, Locale.GERMAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}
|
||||
* for the language.
|
||||
*/
|
||||
|
|
@ -373,7 +373,7 @@ public class ContentItemL10NManagerTest {
|
|||
final Optional<ContentItem> item = itemRepo.findById(-10100L);
|
||||
assertThat(item.isPresent(), is(true));
|
||||
|
||||
l10nManager.removeLangauge(item.get(), null);
|
||||
l10nManager.removeLanguage(item.get(), null);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(); }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@ import com.arsdigita.bebop.PageState;
|
|||
import com.arsdigita.bebop.parameters.ParameterModel;
|
||||
import com.arsdigita.bebop.parameters.BigDecimalParameter;
|
||||
import com.arsdigita.bebop.event.ChangeListener;
|
||||
import com.arsdigita.bebop.parameters.LongParameter;
|
||||
|
||||
import com.arsdigita.util.Assert;
|
||||
import com.arsdigita.util.UncheckedWrapperException;
|
||||
|
|
@ -40,20 +41,26 @@ import org.libreccm.core.CcmObject;
|
|||
import org.libreccm.core.CcmObjectRepository;
|
||||
|
||||
/**
|
||||
* Loads a subclass of an ACSObject from the database.
|
||||
* By default, uses a BigDecimal state parameter in order to
|
||||
* store and retrieve the item id.
|
||||
* Loads a subclass of an ACSObject from the database. By default, uses a
|
||||
* <del>BigDecimal</del> {@code Long} state parameter in order to store and
|
||||
* 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>
|
||||
* The <code>getSelectedKey(PageState state)</code> method will return the
|
||||
* BigDecimal id of the currently selected object. This method
|
||||
* will return the id even if the object with this id does not
|
||||
* actually exist.
|
||||
* BigDecimal id of the currently selected object. This method will return the
|
||||
* id even if the object with this id does not actually exist.
|
||||
*
|
||||
* <p>
|
||||
* The <code>getSelectedObject(PageState state)</code> method will return the
|
||||
* object whose id is <code>getSelectedKey(PageState state)</code>. If the
|
||||
* object does not actually exist, the method will return null
|
||||
* object whose id is <code>getSelectedKey(PageState state)</code>. If the
|
||||
* object does not actually exist, the method will return null
|
||||
*
|
||||
* <p>
|
||||
* Thus, it is possible to implement the following pattern:
|
||||
|
|
@ -78,227 +85,225 @@ import org.libreccm.core.CcmObjectRepository;
|
|||
* }
|
||||
*}</code></pre></blockquote>
|
||||
*
|
||||
* Naturally, the <code>ACSObjectSelectionModel</code> could also be passed
|
||||
* in as a parameter in the <code>MyComponent</code> constructor. In this
|
||||
* case, it should be up to the parent of <code>MyComponent</code> to
|
||||
* register the model's state parameter.
|
||||
* Naturally, the <code>ACSObjectSelectionModel</code> could also be passed in
|
||||
* as a parameter in the <code>MyComponent</code> constructor. In this case, it
|
||||
* should be up to the parent of <code>MyComponent</code> to register the
|
||||
* model's state parameter.
|
||||
* <p>
|
||||
* <b>Advanced Usage</b>: The <code>ACSObjectSelectionModel</code>
|
||||
* is actually just a wrapper for a {@link SingleSelectionModel}
|
||||
* which maintains the currently selected object's ID as a
|
||||
* {@link BigDecimal}. By default, a new
|
||||
* {@link ParameterSingleSelectionModel} is wrapped in this way;
|
||||
* however, any {@link SingleSelectionModel} may be wrapped.
|
||||
* Thus, it becomes possible to use the <code>ACSObjectSelectionModel</code>
|
||||
* even if the currently selected ID is not stored in a state parameter.
|
||||
* <b>Advanced Usage</b>: The <code>ACSObjectSelectionModel</code> is actually
|
||||
* just a wrapper for a {@link SingleSelectionModel} which maintains the
|
||||
* currently selected object's ID as a {@link BigDecimal}. By default, a new
|
||||
* {@link ParameterSingleSelectionModel} is wrapped in this way; however, any
|
||||
* {@link SingleSelectionModel} may be wrapped. Thus, it becomes possible to use
|
||||
* the <code>ACSObjectSelectionModel</code> even if the currently selected ID is
|
||||
* not stored in a state parameter.
|
||||
* <p>
|
||||
* <b>Persistence Details:</b> The default constructor of
|
||||
* <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
|
||||
* alternate constructor in order to force the <code>ACSObjectSelectionModel</code>
|
||||
* to manually instantiate the objects:
|
||||
* alternate constructor in order to force the
|
||||
* <code>ACSObjectSelectionModel</code> to manually instantiate the objects:
|
||||
*
|
||||
* <blockquote><pre><code>
|
||||
* ACSObjectSelectionModel model =
|
||||
* new ACSObjectSelectionModel("com.arsdigita.cms.Article",
|
||||
* ACSObjectSelectionModel model =
|
||||
* new ACSObjectSelectionModel("com.arsdigita.cms.Article",
|
||||
* "com.arsdigita.cms.Article", "item_id");
|
||||
* </code></pre></blockquote>
|
||||
*
|
||||
* In this case, the model will attempt to use reflection to instantiate the
|
||||
* correct subclass of <code>ACSObject</code>. In addition, the supplementary
|
||||
* constructor makes it possible to create new objects in the database
|
||||
* using the {@link #createACSObject(BigDecimal)} method.
|
||||
* constructor makes it possible to create new objects in the database using the
|
||||
* {@link #createACSObject(BigDecimal)} method.
|
||||
*
|
||||
* @see com.arsdigita.bebop.SingleSelectionModel
|
||||
* @see com.arsdigita.bebop.ParameterSingleSelectionModel
|
||||
*
|
||||
* @author Stanislav Freidin
|
||||
* @version $Id$
|
||||
* @author Jens Pelzetter
|
||||
*/
|
||||
public class ACSObjectSelectionModel implements SingleSelectionModel {
|
||||
|
||||
private static final Logger s_log =
|
||||
Logger.getLogger(ACSObjectSelectionModel.class);
|
||||
|
||||
private RequestLocal m_loaded;
|
||||
private Class m_javaClass;
|
||||
private Constructor m_constructor;
|
||||
private String m_objectType;
|
||||
private SingleSelectionModel m_model;
|
||||
private RequestLocal loaded;
|
||||
private Class javaClassName;
|
||||
// private Constructor constructor;
|
||||
private String objectType;
|
||||
private SingleSelectionModel selectionModel;
|
||||
|
||||
/**
|
||||
* Construct a new <code>ACSObjectSelectionModel</code>.
|
||||
* This model will produce instances of <code>ACSObject</code>
|
||||
* by automatically instantiating the correct Java subclass using
|
||||
* the {@link DomainObjectFactory}.
|
||||
* Construct a new <code>ACSObjectSelectionModel</code>. This model will
|
||||
* produce instances of <code>ACSObject</code> by automatically
|
||||
* instantiating the correct Java subclass using the
|
||||
* {@link DomainObjectFactory}.
|
||||
*
|
||||
* @param parameter The state parameter which should be used to store
|
||||
* the object ID
|
||||
* @param parameter The state parameter which should be used to store the
|
||||
* object ID
|
||||
*/
|
||||
public ACSObjectSelectionModel(BigDecimalParameter parameter) {
|
||||
public ACSObjectSelectionModel(final LongParameter parameter) {
|
||||
this(null, null, parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new <code>ACSObjectSelectionModel</code>.
|
||||
* This model will produce instances of <code>ACSObject</code>
|
||||
* by automatically instantiating the correct Java subclass using
|
||||
* the {@link DomainObjectFactory}.
|
||||
* Construct a new <code>ACSObjectSelectionModel</code>. This model will
|
||||
* produce instances of <code>ACSObject</code> by automatically
|
||||
* instantiating the correct Java subclass using the
|
||||
* {@link DomainObjectFactory}.
|
||||
*
|
||||
* @param parameterName The name of the state parameter which will
|
||||
* be used to store the object ID.
|
||||
* @param parameterName The name of the state parameter which will be used
|
||||
* to store the object ID.
|
||||
*/
|
||||
public ACSObjectSelectionModel(String parameterName) {
|
||||
this(null, null, new BigDecimalParameter(parameterName));
|
||||
public ACSObjectSelectionModel(final String parameterName) {
|
||||
this(null, null, new LongParameter(parameterName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new <code>ACSObjectSelectionModel</code>.
|
||||
* This model will produce instances of <code>ACSObject</code>
|
||||
* by automatically instantiating the correct Java subclass using
|
||||
* the {@link DomainObjectFactory}.
|
||||
* Construct a new <code>ACSObjectSelectionModel</code>. This model will
|
||||
* produce instances of <code>ACSObject</code> by automatically
|
||||
* instantiating the correct Java subclass using the
|
||||
* {@link DomainObjectFactory}.
|
||||
*
|
||||
* @param model The {@link SingleSelectionModel} which will supply
|
||||
* a {@link BigDecimal} ID of the currently selected object
|
||||
* @param model The {@link SingleSelectionModel} which will supply a
|
||||
* {@link BigDecimal} ID of the currently selected object
|
||||
*/
|
||||
public ACSObjectSelectionModel(SingleSelectionModel model) {
|
||||
public ACSObjectSelectionModel(final SingleSelectionModel model) {
|
||||
this(null, null, model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new <code>ACSObjectSelectionModel</code>
|
||||
*
|
||||
* @param javaClass The name of the Java class which represents
|
||||
* the object. Must be a subclass of {@link ACSObject}. In
|
||||
* addition, the class must have a constructor with a single
|
||||
* {@link OID} parameter.
|
||||
* @param objectType The name of the persistence metadata object type
|
||||
* which represents the ACS object. In practice, will often be
|
||||
* the same as the javaClass.
|
||||
* @param parameterName The name of the state parameter which will
|
||||
* be used to store the object ID.
|
||||
* @param javaClass The name of the Java class which represents the object.
|
||||
* Must be a subclass of {@link ACSObject}. In addition, the class must have
|
||||
* a constructor with a single {@link OID} parameter.
|
||||
* @param objectType The name of the persistence metadata object type which
|
||||
* represents the ACS object. In practice, will often be the same as the
|
||||
* javaClass.
|
||||
* @param parameterName The name of the state parameter which will be used
|
||||
* to store the object ID.
|
||||
*/
|
||||
public ACSObjectSelectionModel( String javaClass,
|
||||
String objectType,
|
||||
String parameterName ) {
|
||||
this(javaClass, objectType, new BigDecimalParameter(parameterName));
|
||||
public ACSObjectSelectionModel(final String javaClass,
|
||||
final String objectType,
|
||||
final String parameterName) {
|
||||
this(javaClass, objectType, new LongParameter(parameterName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new <code>ACSObjectSelectionModel</code>
|
||||
*
|
||||
* @param javaClass The name of the Java class which represents
|
||||
* the object. Must be a subclass of {@link ACSObject}. In
|
||||
* addition, the class must have a constructor with a single
|
||||
* {@link OID} parameter.
|
||||
* @param objectType The name of the persistence metadata object type
|
||||
* which represents the ACS object. In practice, will often be
|
||||
* the same as the javaClass.
|
||||
* @param parameter The state parameter which should be used to store
|
||||
* the object ID
|
||||
* @param javaClass The name of the Java class which represents the object.
|
||||
* Must be a subclass of {@link ACSObject}. In addition, the class must have
|
||||
* a constructor with a single {@link OID} parameter.
|
||||
* @param objectType The name of the persistence metadata object type which
|
||||
* represents the ACS object. In practice, will often be the same as the
|
||||
* javaClass.
|
||||
* @param parameter The state parameter which should be used to store the
|
||||
* object ID
|
||||
*/
|
||||
public ACSObjectSelectionModel( String javaClass,
|
||||
String objectType,
|
||||
BigDecimalParameter parameter ) {
|
||||
this(javaClass, objectType,
|
||||
public ACSObjectSelectionModel(final String javaClass,
|
||||
final String objectType,
|
||||
final LongParameter parameter) {
|
||||
this(javaClass,
|
||||
objectType,
|
||||
new ParameterSingleSelectionModel(parameter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new <code>ACSObjectSelectionModel</code>
|
||||
*
|
||||
* @param javaClass The name of the Java class which represents
|
||||
* the object. Must be a subclass of {@link ACSObject}. In
|
||||
* addition, the class must have a constructor with a single
|
||||
* {@link OID} parameter.
|
||||
* @param objectType The name of the persistence metadata object type
|
||||
* which represents the ACS object. In practice, will often be
|
||||
* the same as the javaClass.
|
||||
* @param model The {@link SingleSelectionModel} which will supply
|
||||
* a {@link BigDecimal} ID of the currently selected object
|
||||
* @param javaClass The name of the Java class which represents the object.
|
||||
* Must be a subclass of {@link ACSObject}. In addition, the class must have
|
||||
* a constructor with a single {@link OID} parameter.
|
||||
* @param objectType The name of the persistence metadata object type which
|
||||
* represents the ACS object. In practice, will often be the same as the
|
||||
* javaClass.
|
||||
* @param model The {@link SingleSelectionModel} which will supply a
|
||||
* {@link BigDecimal} ID of the currently selected object
|
||||
*/
|
||||
public ACSObjectSelectionModel( String javaClass,
|
||||
String objectType,
|
||||
SingleSelectionModel model ) {
|
||||
m_loaded = new RequestLocal() {
|
||||
protected Object initialValue(PageState state) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
};
|
||||
public ACSObjectSelectionModel(final String javaClass,
|
||||
final String objectType,
|
||||
final SingleSelectionModel model) {
|
||||
loaded = new RequestLocal() {
|
||||
@Override
|
||||
protected Object initialValue(final PageState state) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
};
|
||||
|
||||
if (javaClass != null) {
|
||||
// Cache the Class object and the constructor for further use
|
||||
try {
|
||||
m_javaClass = Class.forName(javaClass);
|
||||
m_constructor = m_javaClass.getConstructor();
|
||||
} catch (Exception e) {
|
||||
throw new UncheckedWrapperException( "Problem loading class "
|
||||
+ javaClass, e );
|
||||
this.javaClassName = Class.forName(javaClass);
|
||||
// this.constructor = javaClassName.getConstructor();
|
||||
} catch (ClassNotFoundException | SecurityException ex) {
|
||||
throw new UncheckedWrapperException(String.format(
|
||||
"Problem loading class %s", javaClass),
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
m_objectType = objectType;
|
||||
m_model = model;
|
||||
this.objectType = objectType;
|
||||
this.selectionModel = model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ID of the current object. The next time
|
||||
* {@link #getSelectedObject(PageState)} is called, the object
|
||||
* with the specified ID will be loaded from the database.
|
||||
* {@link #getSelectedObject(PageState)} is called, the object with the
|
||||
* specified ID will be loaded from the database.
|
||||
*
|
||||
* @param state The page state
|
||||
* @param key A {@link BigDecimal} primary key for the object,
|
||||
* or a String representation of a BigDecimal, such as "42".
|
||||
* @param key A {@link BigDecimal} primary key for the object, or a String
|
||||
* 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);
|
||||
|
||||
m_loaded.set(state, Boolean.FALSE);
|
||||
m_model.setSelectedKey(state, key);
|
||||
loaded.set(state, Boolean.FALSE);
|
||||
selectionModel.setSelectedKey(state, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the object which was selected and loaded from the database,
|
||||
* using the values supplied in the page state. May return <code>null</code>
|
||||
* if <code>isSelected(state) == false</code>, or if the object was not found.
|
||||
* Return the object which was selected and loaded from the database, using
|
||||
* the values supplied in the page state. May return <code>null</code> if
|
||||
* <code>isSelected(state) == false</code>, or if the object was not found.
|
||||
*
|
||||
* @param state The page state
|
||||
* @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));
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return loadACSObject(state, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the selected object for the first time. Child classes
|
||||
* may choose to override this method in order to load the object
|
||||
* in nonstandard ways. The default implementation merely
|
||||
* instantiates an {@link ACSObject} whose ID is the passed-in key.
|
||||
* Load the selected object for the first time. Child classes may choose to
|
||||
* override this method in order to load the object in nonstandard ways. The
|
||||
* default implementation merely instantiates an {@link ACSObject} whose ID
|
||||
* is the passed-in key.
|
||||
*
|
||||
* @param state the current page state
|
||||
* @param key the currently selected key; guaranteed to be non-null
|
||||
* @return the object identified by the specified key
|
||||
* @pre key != null
|
||||
*/
|
||||
protected CcmObject loadACSObject(PageState state, Object key) {
|
||||
CcmObject item = null;
|
||||
|
||||
protected CcmObject loadACSObject(final PageState state, final Object key) {
|
||||
// Cheesy back-and-forth conversion to ensure that
|
||||
// the result will be a BigDecimal, not a String or
|
||||
// something else. Should go away when ListModel.getKey is
|
||||
// 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 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;
|
||||
|
||||
if (item == null) {
|
||||
m_loaded.set(state, Boolean.FALSE);
|
||||
m_model.setSelectedKey(state, null);
|
||||
loaded.set(state, Boolean.FALSE);
|
||||
selectionModel.setSelectedKey(state, null);
|
||||
} else {
|
||||
m_loaded.set(state, Boolean.TRUE);
|
||||
m_model.setSelectedKey(state, item.getObjectId());
|
||||
loaded.set(state, Boolean.TRUE);
|
||||
selectionModel.setSelectedKey(state, item.getObjectId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the attempt to load the selected object has
|
||||
* been made yet. Child classes may use this method to
|
||||
* perform request-local initialization.
|
||||
* Determine if the attempt to load the selected object has been made yet.
|
||||
* Child classes may use this method to perform request-local
|
||||
* initialisation.
|
||||
*
|
||||
* @param state the page state
|
||||
* @return true if the attempt to load the selected object has
|
||||
* already been made, false otherwise
|
||||
* @return true if the attempt to load the selected object has already been
|
||||
* made, false otherwise
|
||||
*/
|
||||
public boolean isInitialized(PageState state) {
|
||||
return ((Boolean)m_loaded.get(state)).booleanValue();
|
||||
public boolean isInitialized(final PageState state) {
|
||||
return ((Boolean) loaded.get(state));
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility function which creates a new object with the given ID.
|
||||
* Uses reflection to create the instance of the class supplied
|
||||
* in the constructor to this <code>ACSObjectSelectionModel</code>.
|
||||
* If no classname was supplied in the constructor, an assertion
|
||||
* failure will occur.
|
||||
* A utility function which creates a new object with the given ID. Uses
|
||||
* reflection to create the instance of the class supplied in the
|
||||
* constructor to this <code>ACSObjectSelectionModel</code>. If no class
|
||||
* name was supplied in the constructor, an assertion failure will occur.
|
||||
*
|
||||
* @param id The id of the new item - this is ignored and the object
|
||||
* will have a different id
|
||||
* @param id The id of the new item - this is ignored and the object will
|
||||
* have a different id
|
||||
* @return The newly created item
|
||||
* @throws javax.servlet.ServletException
|
||||
* @post return != null
|
||||
* @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();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A utility function which creates a new object with the given ID.
|
||||
* Uses reflection to create the instance of the class supplied
|
||||
* in the constructor to this <code>ACSObjectSelectionModel</code>.
|
||||
* If no classname was supplied in the constructor, an assertion
|
||||
* failure will occur.
|
||||
* A utility function which creates a new object with the given ID. Uses
|
||||
* reflection to create the instance of the class supplied in the
|
||||
* constructor to this <code>ACSObjectSelectionModel</code>. If no class
|
||||
* name was supplied in the constructor, an assertion failure will occur.
|
||||
*
|
||||
* @param id The id of the new item
|
||||
* @return The newly created item
|
||||
* @throws javax.servlet.ServletException
|
||||
* @post return != null
|
||||
*/
|
||||
public CcmObject createACSObject() throws ServletException {
|
||||
Assert.exists(m_javaClass, Class.class);
|
||||
Assert.exists(javaClassName, Class.class);
|
||||
|
||||
try {
|
||||
CcmObject item = (CcmObject)m_javaClass.newInstance();
|
||||
return item;
|
||||
} catch (InstantiationException e) {
|
||||
throw new ServletException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new ServletException(e);
|
||||
final CcmObject object = (CcmObject) javaClassName.newInstance();
|
||||
return object;
|
||||
} catch (InstantiationException | IllegalAccessException ex) {
|
||||
throw new ServletException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the Class of the content items which are produced
|
||||
* by this model
|
||||
* @return the Class of the content items which are produced by this model
|
||||
*/
|
||||
public Class getJavaClass() {
|
||||
return m_javaClass;
|
||||
return javaClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The name of the object type of the
|
||||
* content items which are produced by this model
|
||||
* @return The name of the object type of the content items which are
|
||||
* produced by this model
|
||||
*/
|
||||
public String getObjectType() {
|
||||
return m_objectType;
|
||||
return objectType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the underlying {@link SingleSelectionModel} which
|
||||
* maintains the ID of the selected object
|
||||
* @return the underlying {@link SingleSelectionModel} which maintains the
|
||||
* ID of the selected object
|
||||
*/
|
||||
public SingleSelectionModel getSingleSelectionModel() {
|
||||
return m_model;
|
||||
return selectionModel;
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
//
|
||||
// Passthrough methods
|
||||
|
||||
/**
|
||||
* Return <code>true</code> if there is a selected object.
|
||||
*
|
||||
* @param state represents the state of the current request
|
||||
* @return <code>true</code> if there is a selected component.
|
||||
*/
|
||||
public boolean isSelected(PageState state) {
|
||||
return m_model.isSelected(state);
|
||||
@Override
|
||||
public boolean isSelected(final PageState state) {
|
||||
return selectionModel.isSelected(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the key that identifies the selected object.
|
||||
*
|
||||
* @param state the current page state
|
||||
* @return the {@link BigDecimal} ID of the currently selected
|
||||
* object, or null if no object is selected.
|
||||
* @post return instanceof BigDecimal
|
||||
* @return the <del>{@link BigDecimal}</del> {@link Long} ID of the
|
||||
* currently selected object, or null if no object is selected.
|
||||
*
|
||||
*/
|
||||
public Object getSelectedKey(PageState state) {
|
||||
Object key = m_model.getSelectedKey(state);
|
||||
@Override
|
||||
public Object getSelectedKey(final PageState state) {
|
||||
Object key = selectionModel.getSelectedKey(state);
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear the selection.
|
||||
*
|
||||
|
|
@ -435,50 +434,54 @@ public class ACSObjectSelectionModel implements SingleSelectionModel {
|
|||
* @post ! isSelected(state)
|
||||
* @post ! isInitialized(state)
|
||||
*/
|
||||
public void clearSelection(PageState state) {
|
||||
m_model.clearSelection(state);
|
||||
m_loaded.set(state, Boolean.FALSE);
|
||||
@Override
|
||||
public void clearSelection(final PageState state) {
|
||||
selectionModel.clearSelection(state);
|
||||
loaded.set(state, Boolean.FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a change listener to the model. The listener's
|
||||
* <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) {
|
||||
m_model.addChangeListener(l);
|
||||
@Override
|
||||
public void addChangeListener(final ChangeListener listener) {
|
||||
selectionModel.addChangeListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a change listener from the model.
|
||||
*
|
||||
* @param l the listener to remove.
|
||||
* @param listener the listener to remove.
|
||||
*/
|
||||
public void removeChangeListener(ChangeListener l) {
|
||||
m_model.removeChangeListener(l);
|
||||
@Override
|
||||
public void removeChangeListener(final ChangeListener listener) {
|
||||
selectionModel.removeChangeListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the state parameter which will be used to keep track
|
||||
* of the currently selected key. Most likely, the parameter will
|
||||
* be a {@link BigDecimalParameter}.
|
||||
* Return the state parameter which will be used to keep track of the
|
||||
* currently selected key. Most likely, the parameter will be a
|
||||
* {@link BigDecimalParameter}.
|
||||
*
|
||||
* @return The state parameter which should be used to keep
|
||||
* track of the ID of the currently selected object, or null
|
||||
* if the ID is computed in some other way
|
||||
* @return The state parameter which should be used to keep track of the ID
|
||||
* of the currently selected object, or null if the ID is computed in some
|
||||
* other way
|
||||
* @see SingleSelectionModel#getStateParameter()
|
||||
*/
|
||||
@Override
|
||||
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;
|
||||
|
||||
if ( value instanceof Long ) {
|
||||
if (value instanceof Long) {
|
||||
newValue = (Long) value;
|
||||
} else if ( value != null ) {
|
||||
} else if (value != null) {
|
||||
newValue = Long.parseLong(value.toString());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue