From eb33ac7decdcc543e2155e32e4b8644f5a414ed4 Mon Sep 17 00:00:00 2001 From: jensp Date: Wed, 7 Sep 2016 12:14:43 +0000 Subject: [PATCH] CCM NG: Preperation for migrated some more classes git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4287 8810af33-2d31-482b-a856-94f89814c4df --- .../arsdigita/cms/ui/ContentItemPage.java.off | 544 ++++++++++++++++++ .../authoring/AuthoringKitSelector.java.off | 151 +++++ .../cms/ui/authoring/WizardSelector.java.off | 148 +++++ .../ui/cse/ContentSoonExpiredPane.java.off | 5 +- .../ui/item/CustomizedPreviewLink.java.off | 24 + .../cms/ui/type/ContentTypeAdminPane.java.off | 7 +- .../contentsection/ContentItemManager.java | 204 +++---- 7 files changed, 975 insertions(+), 108 deletions(-) create mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java.off create mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitSelector.java.off create mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/WizardSelector.java.off create mode 100644 ccm-cms/src/main/java/com/arsdigita/cms/ui/item/CustomizedPreviewLink.java.off diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java.off new file mode 100755 index 000000000..c05bed15a --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java.off @@ -0,0 +1,544 @@ +/* + * 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.FormData; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Resettable; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.TabbedPane; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +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.NotNullValidationListener; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.cms.ui.item.CustomizedPreviewLink; +import com.arsdigita.cms.dispatcher.CMSDispatcher; +import com.arsdigita.cms.dispatcher.CMSPage; +import com.arsdigita.cms.dispatcher.ItemResolver; +import com.arsdigita.cms.ui.authoring.WizardSelector; +import com.arsdigita.cms.ui.item.ContentItemRequestLocal; +import com.arsdigita.cms.ui.item.ItemLanguages; +import com.arsdigita.cms.ui.item.Summary; +import com.arsdigita.cms.ui.lifecycle.ItemLifecycleAdminPane; +import com.arsdigita.cms.ui.revision.ItemRevisionAdminPane; +import com.arsdigita.cms.ui.templates.ItemTemplates; +import com.arsdigita.cms.ui.workflow.ItemWorkflowAdminPane; +import com.arsdigita.cms.util.GlobalizationUtil; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.kernel.ui.ACSObjectSelectionModel; +import com.arsdigita.persistence.OID; +import com.arsdigita.ui.DebugPanel; +import com.arsdigita.util.Assert; +import com.arsdigita.xml.Document; +import com.arsdigita.xml.Element; +import java.io.IOException; +import java.math.BigDecimal; +import javax.servlet.http.HttpServletRequest; +import org.apache.log4j.Logger; + +/** + * Page for administering a content item. + * + * @author Michael Pih + * @author Stanislav Freidin <sfreidin@redhat.com> + * @author Jack Chung + * @author Sören Bernstein + * + * @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); + /** + * 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 + * selected with a local state parameter + */ + public static final String SET_TAB = "set_tab"; + /** + * 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 + */ + public static final String RETURN_URL = "return_url"; + /** + * The name of the global state parameter that determines whether or not to + * use the streamlined authoring process (assuming the option is turned on). + * + */ + 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++; + /** + *

The name of the state parameter which indicates the content type of + * the item the user wishes to create. or edit.

+ * + *

The parameter must be a BigDecimalParameter which encodes the id of + * the content type.

+ */ + 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; + + private class ItemRequestLocal extends ContentItemRequestLocal { + + protected final Object initialValue(final PageState state) { + return CMS.getContext().getContentItem(); + } + } + + 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()); + + label.setLabel(item.getDisplayName()); + } + } + + /** + * Constructs a new ContentItemPage. + */ + public ContentItemPage() { + super("", new SimpleContainer()); + + m_item = new ItemRequestLocal(); + + setClassAttr("cms-admin"); + setTitle(new Label(new TitlePrinter())); + + // Add the item id global state parameter + BigDecimalParameter itemId = new BigDecimalParameter(ITEM_ID); + itemId.addParameterListener(new NotNullValidationListener(ITEM_ID)); + addGlobalStateParam(itemId); + m_itemModel = new ItemSelectionModel(itemId); + + // Add the content type global state parameter + BigDecimalParameter contentType = new BigDecimalParameter(CONTENT_TYPE); + addGlobalStateParam(contentType); + + // Add the streamlined creation global state parameter + StringParameter streamlinedCreation = new StringParameter( + STREAMLINED_CREATION); + addGlobalStateParam(streamlinedCreation); + + m_typeModel = new ACSObjectSelectionModel(ContentType.class.getName(), + ContentType.BASE_DATA_OBJECT_TYPE, + contentType); + + // Validate the item ID parameter (caches the validation). + getStateModel().addValidationListener(new FormValidationListener() { + public void validate(FormSectionEvent event) + throws FormProcessException { + validateItemID(event.getPageState()); + } + }); + + // Add the return url global state parameter + m_returnURL = new StringParameter(RETURN_URL); + addGlobalStateParam(m_returnURL); + + m_globalNavigation = new GlobalNavigation(); + add(m_globalNavigation); + + m_contextBar = new ContentItemContextBar(m_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); + + // Create tabbed pane. + m_tabbedPane = new TabbedPane(); + add(m_tabbedPane); + + m_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); + + m_tabbedPane.addActionListener(new ActionListener() { + public final void actionPerformed(final ActionEvent e) { + final PageState state = e.getPageState(); + final Component pane = m_tabbedPane.getCurrentPane(state); + + if (pane instanceof Resettable) { + ((Resettable) pane).reset(state); + } + } + }); + + // 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); + } + }); + m_previewLink.setIdAttr("preview_link"); + add(m_previewLink); + + addActionListener(this); + + // 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")); + } + } + }); + + add(new DebugPanel()); + } + + /** + * Ensures that the item_id parameter references a valid {@link + * com.arsdigita.cms.ContentItem}. + * + * @param state The page state + * @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); + + if (item == null) { + throw new FormProcessException(GlobalizationUtil.globalize( + "cms.ui.invalid_item_id")); + } + } + + /** + * Fetch the request-local content section. + * + * @deprecated use com.arsdigita.cms.CMS.getContext().getContentSection() + * instead + * @param request The HTTP request + * @return The current content section + */ + @Override + public ContentSection getContentSection(HttpServletRequest request) { + // Resets all content sections associations. + ContentSection section = super.getContentSection(request); + Assert.exists(section); + return section; + } + + /** + * Overrides CMSPage.getContentItem(PageState state) to get the current + * content item from the page state. + * + * @deprecated Use the ItemSelectionModel + * @param state The page state + * @return The current content item, null if there is none + */ + @Override + public ContentItem getContentItem(PageState state) { + return (ContentItem) m_itemModel.getSelectedObject(state); + } + + /** + * Set the current tab, if necessary + */ + public void actionPerformed(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 + // 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); + } + } + + // Set the current tab based on parameters + if (setTab != null) { + Integer tab = null; + + try { + tab = Integer.valueOf(setTab); + } catch (NumberFormatException e) { + // Stop processing set_tab parameter. + return; + } + + if (tab.intValue() < m_tabbedPane.size()) { + m_tabbedPane.setSelectedIndex(state, tab.intValue()); + } + } + } + + /** + * Construct a URL for displaying a certain item + * + * @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 + */ + public static String getItemURL(String nodeURL, + BigDecimal itemId, + int tab) { + return getItemURL(nodeURL, itemId, tab, false); + } + + /** + * Construct a URL for displaying a certain item + * + * @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 + * @param streamlinedCreation Whether to activate Streamlined item authoring + */ + public static String getItemURL(String nodeURL, + BigDecimal itemId, + int tab, + boolean streamlinedCreation) { + StringBuffer url = new StringBuffer(); + + url.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); + } + + return url.toString(); + } + + /** + * @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); + return url.toString(); + } + + /** + * Constructs a URL for displaying a certain item. + * + * @param item the ContentItem object to display + * @param tab The index of the tab to display + */ + public static String getItemURL(ContentItem item, int tab) { + final ContentSection section = item.getContentSection(); + + if (section == null) { + return null; + } else { + final String nodeURL = section.getPath() + "/"; + + return getItemURL(nodeURL, item.getID(), tab); + } + } + + /** + * Constructs a URL for displaying a certain item. + * + * @param itemId the id of the ContentItem object to display + * @param tab The index of the tab to display + */ + public static String getItemURL(BigDecimal itemId, int tab) { + final ContentItem item = + (ContentItem) DomainObjectFactory.newInstance(new OID( + ContentItem.BASE_DATA_OBJECT_TYPE, itemId)); + + if (item == null) { + return null; + } else { + return getItemURL(item, tab); + } + } + + /** + * Redirect back to wherever the user came from, using the value of the + * return_url parameter. + * + * @param state The current page state + */ + public void redirectBack(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); + // do nothing + } + } + + /** + * Fetch the preview URL. + */ + private String getPreviewURL(PageState state) { + final ContentItem item = m_item.getContentItem(state); + + if (item instanceof CustomizedPreviewLink) { + final String previewLink = ((CustomizedPreviewLink) item). + getPreviewUrl( + state); + if ((previewLink == null) || previewLink.isEmpty()) { + return getDefaultPreviewLink(state, item); + } else { + return previewLink; + } + } else { + return getDefaultPreviewLink(state, item); + } + } + + /** + * + * @param state + * @param item + * @return + */ + private String getDefaultPreviewLink(final PageState state, + final ContentItem item) { + final ContentSection section = CMS.getContext().getContentSection(); + //ContentSection section = getContentSection(state); + final ItemResolver itemResolver = section.getItemResolver(); + + // Pass in the "Live" context since we need it for the preview + return itemResolver.generateItemURL(state, item, section, + CMSDispatcher.PREVIEW); + } + + protected final static GlobalizedMessage gz(final String key) { + return GlobalizationUtil.globalize(key); + } + + protected final static String lz(final String key) { + return (String) gz(key).localize(); + } + + public static boolean isStreamlinedCreationActive(PageState state) { + return ContentSection.getConfig().getUseStreamlinedCreation() + && STREAMLINED_CREATION_ACTIVE.equals(state.getRequest(). + getParameter(STREAMLINED_CREATION)); + } + + protected TabbedPane getTabbedPane() { + return m_tabbedPane; + } + + protected WizardSelector getWizardPane() { + return m_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()); + + return page; + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitSelector.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitSelector.java.off new file mode 100755 index 000000000..19906bd97 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitSelector.java.off @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.cms.ui.authoring; + +import com.arsdigita.bebop.Component; + +import com.arsdigita.bebop.MapComponentSelectionModel; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.SingleSelectionModel; + +import org.librecms.contentsection.ContentType; + +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.xml.Element; + +import org.apache.logging.log4j.LogManager; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; + +import org.apache.logging.log4j.Logger; + +import java.util.List; + +/** + * Selects a component based on content type. Helper class for {@link + * com.arsdigita.cms.ui.authoring.WizardSelector}. + * + * @author Jens Pelzetter + * @author unknown + */ +public abstract class AuthoringKitSelector extends SimpleContainer { + + private static final Logger LOGGER = LogManager.getLogger( + AuthoringKitSelector.class); + private Map m_comps; + private MapComponentSelectionModel m_sel; + private List m_types; + + /** + * Construct a new AuthoringKitSelector. Load all the possible authoring + * kits from the database and construct components for them. + * + * @param model the {@link ItemSelectionModel} which will supply the + * selector with the id of a content type + * + * @pre itemModel != null + */ + public AuthoringKitSelector(final SingleSelectionModel model) { + super(); + + m_comps = new HashMap(); + m_sel = new MapComponentSelectionModel(model, m_comps); + + m_types = ContentType.getAllContentTypes(); + if (m_types.isEmpty()) { + throw new RuntimeException("No Content Types were found."); + } + } + + // Overloaded add methods + @Override + public void add(Component c) { + throw new UnsupportedOperationException(); + } + + // Overloaded add methods + @Override + public void add(Component c, int constraints) { + throw new UnsupportedOperationException(); + } + + /** + * Instantiate all the authoring kit wizards. The child class should call + * this method after it is done with initialization. + */ + protected void processKit() { + while (m_types.next()) { + ContentType type = m_types.getContentType(); + AuthoringKit kit = type.getAuthoringKit(); + if (kit != null) { + Component c = instantiateKitComponent(kit, type); + if (c != null) { + super.add(c); + m_comps.put(type.getID(), c); + LOGGER.info("Added component " + c + " for " + + type.getAssociatedObjectType()); + } + } + } + } + + /** + * Instantiate an authoring kit component. Child classes should override + * this to do the right thing. It is permissible for this method to return + * null. + * + * @param kit for this kit + * @param type for this type + */ + protected abstract Component instantiateKitComponent( + AuthoringKit kit, ContentType type); + + /** + * @param id The content type id + * + * @return The component the given type id + */ + public Component getComponent(BigDecimal id) { + return (Component) m_comps.get(id); + } + + /** + * @return The selection model used by this wizard + */ + public MapComponentSelectionModel getComponentSelectionModel() { + return m_sel; + } + + // Choose the right component and run it + public void generateXML(PageState state, Element parent) { + if (isVisible(state)) { + Component c = m_sel.getComponent(state); + if (c == null) { + throw new IllegalStateException("No component for " + + m_sel + .getSelectedKey(state)); + } + c.generateXML(state, parent); + } + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/WizardSelector.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/WizardSelector.java.off new file mode 100755 index 000000000..0c6b267c1 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/WizardSelector.java.off @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.cms.ui.authoring; + + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Resettable; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentType; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.toolbox.ui.LayoutPanel; +import com.arsdigita.xml.Element; + +import java.math.BigDecimal; + + +/** + * An invisible component which contains all the possible authoring kits. + * The kits are loaded from the database at construction time. The selector + * chooses which kit to display at page rendering time based on the value + * of the content_type state parameter. + * + * Essentially, this component is a hack which is used to get around + * the fact that we cannot instantiate stateful components dynamically. + * + * @author Jens Pelzetter + * @author unknown + */ +public class WizardSelector extends AuthoringKitSelector + implements Resettable { + + private ItemSelectionModel m_itemSel; + + /** + * Construct a new WizardSelector. Load all the possible authoring kits + * from the database and construct wizards for them. + * + * @param model the {@link ItemSelectionModel} which will + * supply the wizard with its item + * + * @param typeModel the {@link ACSObjectSelectionModel} which will + * supply the default content type + * + * @pre itemModel != null + */ + public WizardSelector(ItemSelectionModel model, + SingleSelectionModel typeModel) { + super(typeModel); + m_itemSel = model; + super.processKit(); + } + + /** + * Get the wizard for the given kit. + */ + public Component instantiateKitComponent(AuthoringKit kit, + ContentType type) { + + ItemSelectionModel itemModel = new + ItemSelectionModel(type, + (BigDecimalParameter)m_itemSel.getStateParameter()); + + AuthoringKitWizard w = new AuthoringKitWizard(type, itemModel); + return w; + } + + /** + * @return The item selection model used by this wizard + */ + public ItemSelectionModel getSelectionModel() { + return m_itemSel; + } + + // Determine the current wizard + private Component getCurrentWizard(PageState state) { + + // Get the current item and extract its content type + if(!m_itemSel.isSelected(state)) + throw new RuntimeException( (String) GlobalizationUtil.globalize( + "cms.ui.authoring.missing_item_id") + .localize()); + + ContentItem item = + (ContentItem)m_itemSel.getSelectedObject(state); + + ContentType type = item.getContentType(); + BigDecimal typeId; + + if(type == null) { + // Try to get the default content type + typeId = (BigDecimal)getComponentSelectionModel().getSelectedKey(state); + if(typeId == null) { + throw new RuntimeException((String) GlobalizationUtil.globalize( + "cms.ui.authoring.missing_content_type") + .localize()); + } + } else { + typeId = type.getID(); + } + + // Return the selected wizard + return (Component)getComponent(typeId); + } + + // Choose the right wizard and run it + public void generateXML(PageState state, Element parent) { + + Component c = getCurrentWizard(state); + + if(c == null) { + throw new RuntimeException( (String) GlobalizationUtil.globalize( + "cms.ui.authoring.no_current_wizard") + .localize()); + } + + c.generateXML(state, parent); + } + + /** + * Reset the state of the current wizard + */ + public void reset(PageState state) { + Resettable r = (Resettable)getCurrentWizard(state); + if(r != null) r.reset(state); + } + + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/cse/ContentSoonExpiredPane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/cse/ContentSoonExpiredPane.java.off index f63223b88..34f1bb2dc 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/cse/ContentSoonExpiredPane.java.off +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/cse/ContentSoonExpiredPane.java.off @@ -23,9 +23,8 @@ import com.arsdigita.bebop.Link; import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.SimpleContainer; import com.arsdigita.cms.CMS; -import com.arsdigita.cms.ContentItem; -import com.arsdigita.cms.ContentSection; -import com.arsdigita.cms.SecurityManager; +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentSection; import com.arsdigita.cms.ui.ContentItemPage; import com.arsdigita.cms.util.GlobalizationUtil; import com.arsdigita.cms.util.SecurityConstants; diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/CustomizedPreviewLink.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/CustomizedPreviewLink.java.off new file mode 100644 index 000000000..a998672e6 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/CustomizedPreviewLink.java.off @@ -0,0 +1,24 @@ +package com.arsdigita.cms.ui.item; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.cms.ui.ContentItemPage; + +/** + *

+ * This interface is implemented by "meta" content items which need to + * customise their preview link. An example is a content item which serves + * as an access point to an application. + *

+ *

+ * An implementation may return {@code null}. In this case + * {@link ContentItemPage} will use the default preview URL. + *

+ * + * @author Jens Pelzetter + * @version $Id$ + */ +public interface CustomizedPreviewLink { + + String getPreviewUrl(PageState state); + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/type/ContentTypeAdminPane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/type/ContentTypeAdminPane.java.off index 97a8aaacd..8f5daf254 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/type/ContentTypeAdminPane.java.off +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/type/ContentTypeAdminPane.java.off @@ -30,10 +30,9 @@ import com.arsdigita.bebop.event.ActionListener; import com.arsdigita.bebop.event.FormProcessListener; import com.arsdigita.bebop.event.FormSubmissionListener; import com.arsdigita.cms.CMS; -import com.arsdigita.cms.ContentSection; -import com.arsdigita.cms.ContentType; -import com.arsdigita.cms.ContentTypeCollection; -import com.arsdigita.cms.SectionTemplateMapping; +import org.librecms.contentsection.ContentSection; +import org.librecms.contentsection.ContentType; +//ToDo import com.arsdigita.cms.SectionTemplateMapping; import com.arsdigita.cms.ui.BaseAdminPane; import com.arsdigita.cms.ui.BaseDeleteForm; import com.arsdigita.cms.ui.ContentSectionPage; diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemManager.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemManager.java index a409c8c06..6c580298b 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemManager.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemManager.java @@ -71,7 +71,7 @@ import javax.transaction.Transactional; public class ContentItemManager { private static final Logger LOGGER = LogManager.getLogger( - ContentItemManager.class); + ContentItemManager.class); @Inject private EntityManager entityManager; @@ -105,29 +105,29 @@ public class ContentItemManager { * {@link ContentSection#rootDocumentsFolder} of the provided content * section. Otherwise an {@link IllegalArgumentException} is thrown. * - * @param The type of the content item. - * @param name The name (URL stub) of the new content item. + * @param The type of the content item. + * @param name The name (URL stub) of the new content item. * @param section The content section in which the item is generated. - * @param folder The folder in which in the item is stored. - * @param type The type of the new content item. + * @param folder The folder in which in the item is stored. + * @param type The type of the new content item. * * @return The new content item. */ @Transactional(Transactional.TxType.REQUIRED) public T createContentItem( - final String name, - final ContentSection section, - final Category folder, - final Class type) { + final String name, + final ContentSection section, + final Category folder, + final Class type) { final Optional contentType = typeRepo - .findByContentSectionAndClass(section, type); + .findByContentSectionAndClass(section, type); if (!contentType.isPresent()) { throw new IllegalArgumentException(String.format( - "ContentSection \"%s\" has no content type for \"%s\".", - section.getLabel(), - type.getName())); + "ContentSection \"%s\" has no content type for \"%s\".", + section.getLabel(), + type.getName())); } return createContentItem(name, @@ -150,53 +150,54 @@ public class ContentItemManager { * {@link WorkflowTemplate} must be defined in the provided content section. * Otherwise an {@link IllegalArgumentException} is thrown. * - * @param The type of the content item. - * @param name The name (URL stub) of the new content item. - * @param section The content section in which the item is generated. - * @param folder The folder in which in the item is stored. + * @param The type of the content item. + * @param name The name (URL stub) of the new content item. + * @param section The content section in which the item is + * generated. + * @param folder The folder in which in the item is stored. * @param workflowTemplate * @param lifecycleDefinition - * @param type The type of the new content item. + * @param type The type of the new content item. * * @return The new content item. */ @Transactional(Transactional.TxType.REQUIRED) public T createContentItem( - final String name, - final ContentSection section, - final Category folder, - final WorkflowTemplate workflowTemplate, - final LifecycleDefinition lifecycleDefinition, - final Class type) { + final String name, + final ContentSection section, + final Category folder, + final WorkflowTemplate workflowTemplate, + final LifecycleDefinition lifecycleDefinition, + final Class type) { final Optional contentType = typeRepo - .findByContentSectionAndClass(section, type); + .findByContentSectionAndClass(section, type); if (!contentType.isPresent()) { throw new IllegalArgumentException(String.format( - "ContentSection \"%s\" has no content type for \"%s\".", - section.getLabel(), - type.getName())); + "ContentSection \"%s\" has no content type for \"%s\".", + section.getLabel(), + type.getName())); } final Lifecycle lifecycle = lifecycleManager.createLifecycle( - lifecycleDefinition); + lifecycleDefinition); final Workflow workflow = workflowManager.createWorkflow( - workflowTemplate); + workflowTemplate); final T item; try { item = type.newInstance(); } catch (InstantiationException | IllegalAccessException ex) { LOGGER.error("Failed to create new content item of type \"{}\" " - + "in content section \"{}\".", + + "in content section \"{}\".", type.getName(), section.getLabel()); throw new RuntimeException(ex); } final KernelConfig kernelConfig = confManager.findConfiguration( - KernelConfig.class); + KernelConfig.class); item.setDisplayName(name); item.getName().addValue(kernelConfig.getDefaultLocale(), @@ -216,7 +217,7 @@ public class ContentItemManager { * only moves the draft version of the item. The live version is moved after * a the item is republished. * - * @param item The item to move. + * @param item The item to move. * @param targetFolder The folder to which the item is moved. */ @Transactional(Transactional.TxType.REQUIRED) @@ -241,23 +242,24 @@ public class ContentItemManager { * Creates an copy of the draft version of the item in the provided * {@code targetFolder}. * - * @param item The item to copy. + * @param item The item to copy. * @param targetFolder The folder in which the copy is created. If the - * target folder is the same folder as the folder of the original item an - * index is appended to the name of the item. + * target folder is the same folder as the folder of the + * original item an index is appended to the name of the + * item. */ @SuppressWarnings("unchecked") public void copy(final ContentItem item, final Category targetFolder) { final Optional contentType = typeRepo - .findByContentSectionAndClass( - item.getContentType().getContentSection(), item. - getClass()); + .findByContentSectionAndClass( + item.getContentType().getContentSection(), item. + getClass()); if (!contentType.isPresent()) { throw new IllegalArgumentException(String.format( - "ContentSection \"%s\" has no content type for \"%s\".", - item.getContentType().getContentSection(), - item.getClass().getName())); + "ContentSection \"%s\" has no content type for \"%s\".", + item.getContentType().getContentSection(), + item.getClass().getName())); } final ContentItem draftItem = getDraftVersion(item, item.getClass()); @@ -272,30 +274,30 @@ public class ContentItemManager { copy.setContentType(contentType.get()); final Lifecycle lifecycle = lifecycleManager.createLifecycle( - contentType.get().getDefaultLifecycle()); + contentType.get().getDefaultLifecycle()); final Workflow workflow = workflowManager.createWorkflow(contentType - .get().getDefaultWorkflow()); + .get().getDefaultWorkflow()); copy.setLifecycle(lifecycle); copy.setWorkflow(workflow); draftItem.getCategories().forEach(categorization -> categoryManager - .addObjectToCategory(copy, categorization.getCategory())); + .addObjectToCategory(copy, categorization.getCategory())); final Optional itemFolder = getItemFolder(draftItem); if (itemFolder.isPresent()) { try { categoryManager.removeObjectFromCategory( - copy, getItemFolder(draftItem).get()); + copy, getItemFolder(draftItem).get()); } catch (ObjectNotAssignedToCategoryException ex) { throw new RuntimeException(ex); } } categoryManager.addObjectToCategory( - copy, - targetFolder, - CmsConstants.CATEGORIZATION_TYPE_FOLDER); + copy, + targetFolder, + CmsConstants.CATEGORIZATION_TYPE_FOLDER); // !!!!!!!!!!!!!!!!!!!!! // ToDo copy Attachments @@ -310,7 +312,7 @@ public class ContentItemManager { } for (final PropertyDescriptor propertyDescriptor : beanInfo - .getPropertyDescriptors()) { + .getPropertyDescriptors()) { if (propertyIsExcluded(propertyDescriptor.getName())) { continue; } @@ -332,10 +334,10 @@ public class ContentItemManager { } source.getAvailableLocales().forEach( - locale -> target.addValue(locale, source. - getValue(locale))); + locale -> target.addValue(locale, + source.getValue(locale))); } else if (propType != null - && propType.isAssignableFrom(ContentItem.class)) { + && propType.isAssignableFrom(ContentItem.class)) { final ContentItem linkedItem; try { @@ -347,7 +349,7 @@ public class ContentItemManager { } final ContentItem linkedDraftItem = getDraftVersion( - linkedItem, linkedItem.getClass()); + linkedItem, linkedItem.getClass()); try { writeMethod.invoke(copy, linkedDraftItem); @@ -357,7 +359,7 @@ public class ContentItemManager { throw new RuntimeException(ex); } } else if (propType != null - && propType.isAssignableFrom(List.class)) { + && propType.isAssignableFrom(List.class)) { final List source; final List target; try { @@ -371,7 +373,7 @@ public class ContentItemManager { target.addAll(source); } else if (propType != null - && propType.isAssignableFrom(Map.class)) { + && propType.isAssignableFrom(Map.class)) { final Map source; final Map target; @@ -386,7 +388,7 @@ public class ContentItemManager { source.forEach((key, value) -> target.put(key, value)); } else if (propType != null - && propType.isAssignableFrom(Set.class)) { + && propType.isAssignableFrom(Set.class)) { final Set source; final Set target; @@ -460,7 +462,7 @@ public class ContentItemManager { liveItem.setWorkflow(draftItem.getWorkflow()); draftItem.getCategories().forEach(categorization -> categoryManager - .addObjectToCategory(item, categorization.getCategory())); + .addObjectToCategory(item, categorization.getCategory())); liveItem.setUuid(draftItem.getUuid()); @@ -477,7 +479,7 @@ public class ContentItemManager { } for (final PropertyDescriptor propertyDescriptor : beanInfo - .getPropertyDescriptors()) { + .getPropertyDescriptors()) { if (propertyIsExcluded(propertyDescriptor.getName())) { continue; @@ -500,10 +502,10 @@ public class ContentItemManager { } source.getAvailableLocales().forEach( - locale -> target.addValue(locale, source. - getValue(locale))); + locale -> target.addValue(locale, source. + getValue(locale))); } else if (propType != null - && propType.isAssignableFrom(ContentItem.class)) { + && propType.isAssignableFrom(ContentItem.class)) { final ContentItem linkedItem; try { linkedItem = (ContentItem) readMethod.invoke(draftItem); @@ -514,13 +516,13 @@ public class ContentItemManager { } final ContentItem linkedDraftItem = getDraftVersion( - linkedItem, linkedItem.getClass()); + linkedItem, linkedItem.getClass()); if (isLive(linkedDraftItem)) { try { final Optional linkedLiveItem - = getLiveVersion( - linkedDraftItem, ContentItem.class); + = getLiveVersion( + linkedDraftItem, ContentItem.class); writeMethod.invoke(liveItem, linkedLiveItem); } catch (IllegalAccessException | IllegalArgumentException | @@ -529,7 +531,7 @@ public class ContentItemManager { } } } else if (propType != null - && propType.isAssignableFrom(List.class)) { + && propType.isAssignableFrom(List.class)) { final List source; final List target; try { @@ -543,7 +545,7 @@ public class ContentItemManager { target.addAll(source); } else if (propType != null - && propType.isAssignableFrom(Map.class)) { + && propType.isAssignableFrom(Map.class)) { final Map source; final Map target; @@ -558,7 +560,7 @@ public class ContentItemManager { source.forEach((key, value) -> target.put(key, value)); } else if (propType != null - && propType.isAssignableFrom(Set.class)) { + && propType.isAssignableFrom(Set.class)) { final Set source; final Set target; @@ -598,7 +600,7 @@ public class ContentItemManager { public void unpublish(final ContentItem item ) { final Optional liveItem = getLiveVersion( - item, ContentItem.class); + item, ContentItem.class); if (liveItem.isPresent()) { entityManager.remove(liveItem); @@ -612,11 +614,11 @@ public class ContentItemManager { * @param item The item * * @return {@code true} if the content item has a live version, - * {@code false} if not. + * {@code false} if not. */ public boolean isLive(final ContentItem item) { final TypedQuery query = entityManager.createNamedQuery( - "ContentItem.hasLiveVersion", Boolean.class); + "ContentItem.hasLiveVersion", Boolean.class); query.setParameter("uuid", item.getUuid()); return query.getSingleResult(); @@ -625,22 +627,22 @@ public class ContentItemManager { /** * Retrieves the live version of the provided content item if any. * - * @param Type of the content item. + * @param Type of the content item. * @param item The item of which the live version should be retrieved. * @param type Type of the content item. * * @return The live version of an item. If the item provided is already the - * live version the provided item is returned, otherwise the live version is - * returned. If there is no live version an empty {@link Optional} is - * returned. + * live version the provided item is returned, otherwise the live + * version is returned. If there is no live version an empty + * {@link Optional} is returned. */ public Optional getLiveVersion( - final ContentItem item, - final Class type) { + final ContentItem item, + final Class type) { if (isLive(item)) { final TypedQuery query = entityManager.createNamedQuery( - "ContentItem.findLiveVersion", type); + "ContentItem.findLiveVersion", type); query.setParameter("uuid", item.getUuid()); return Optional.of(query.getSingleResult()); @@ -652,36 +654,36 @@ public class ContentItemManager { /** * Retrieves the pending versions of an item if there are any. * - * @param Type of the content item to retrieve. + * @param Type of the content item to retrieve. * @param item The item of which the pending versions are retrieved. * @param type Type of the content item to retrieve. * * @return A list of the pending versions of the item. */ public List getPendingVersions( - final ContentItem item, - final Class type) { + final ContentItem item, + final Class type) { throw new UnsupportedOperationException(); } /** * Retrieves the draft version * - * @param Type of the item. + * @param Type of the item. * @param item The item of which the draft version is retrieved. * @param type Type of the item. * * @return The draft version of the provided content item. If the provided - * item is the draft version the provided item is simply returned. Otherwise - * the draft version is retrieved from the database and is returned. Each - * content item has a draft version (otherwise something is seriously wrong - * with the database) this method will + * item is the draft version the provided item is simply returned. + * Otherwise the draft version is retrieved from the database and is + * returned. Each content item has a draft version (otherwise + * something is seriously wrong with the database) this method will * never return {@code null}. */ public T getDraftVersion(final ContentItem item, final Class type) { final TypedQuery query = entityManager.createNamedQuery( - "ContentItem.findDraftVersion", type); + "ContentItem.findDraftVersion", type); query.setParameter("uuid", item.getUuid()); return query.getSingleResult(); @@ -720,9 +722,9 @@ public class ContentItemManager { * {@code info}, the path including the content section would be * {@code info:/research/computer-science/artificial-intelligence/neural-nets}. * - * @param item The item whose path is generated. + * @param item The item whose path is generated. * @param withContentSection Wether to include the content section into the - * path. + * path. * * @return The path of the content item * @@ -731,9 +733,9 @@ public class ContentItemManager { public String getItemPath(final ContentItem item, final boolean withContentSection) { final List result = item.getCategories().stream(). - filter(categorization -> CmsConstants.CATEGORIZATION_TYPE_FOLDER. - equals(categorization.getType())) - .collect(Collectors.toList()); + filter(categorization -> CmsConstants.CATEGORIZATION_TYPE_FOLDER. + equals(categorization.getType())) + .collect(Collectors.toList()); if (result.isEmpty()) { return item.getDisplayName(); @@ -754,9 +756,9 @@ public class ContentItemManager { if (withContentSection) { final String sectionName = item.getContentType(). - getContentSection().getDisplayName(); + getContentSection().getDisplayName(); return String.format( - "%s/%s", sectionName, path); + "%s/%s", sectionName, path); } else { return String.format("/%s", path); } @@ -772,9 +774,9 @@ public class ContentItemManager { */ public List getItemFolders(final ContentItem item) { final List result = item.getCategories().stream(). - filter(categorization -> CmsConstants.CATEGORIZATION_TYPE_FOLDER. - equals(categorization.getType())) - .collect(Collectors.toList()); + filter(categorization -> CmsConstants.CATEGORIZATION_TYPE_FOLDER. + equals(categorization.getType())) + .collect(Collectors.toList()); final List folders = new ArrayList<>(); if (!result.isEmpty()) { @@ -800,13 +802,13 @@ public class ContentItemManager { * @param item The item * * @return An {@link Optional} containing the folder of the item if the item - * is part of a folder. + * is part of a folder. */ public Optional getItemFolder(final ContentItem item) { final List result = item.getCategories().stream(). - filter(categorization -> CmsConstants.CATEGORIZATION_TYPE_FOLDER. - equals(categorization.getType())) - .collect(Collectors.toList()); + filter(categorization -> CmsConstants.CATEGORIZATION_TYPE_FOLDER. + equals(categorization.getType())) + .collect(Collectors.toList()); if (result.size() > 0) { return Optional.of(result.get(0).getCategory());