diff --git a/ccm-bundle-devel-wildfly-web/src/main/resources/log4j2.xml b/ccm-bundle-devel-wildfly-web/src/main/resources/log4j2.xml
index 37684c867..fb01e7b0f 100644
--- a/ccm-bundle-devel-wildfly-web/src/main/resources/log4j2.xml
+++ b/ccm-bundle-devel-wildfly-web/src/main/resources/log4j2.xml
@@ -45,6 +45,9 @@
+ * Loads a subclass of a {@link com.arsdigita.cms.ContentItem} from the + * database. This model should be used as a parameter to the constructor of + * authoring kit components.
+ * + *+ * It is possible to instantiate this model with a {@link + * com.arsdigita.cms.ContentType} as a constructor parameter. In this case, the + * model will only instantiate items that are of the specified content type, or + * one of it subclasses.
+ * + * @author Stanislav Freidin (stas@arsdigita.com) + * @version $Revision$ $DateTime: 2004/08/17 23:15:09 $ + * @see com.arsdigita.kernel.ui.ACSObjectSelectionModel + * @see com.arsdigita.bebop.SingleSelectionModel + */ +public class ItemSelectionModel extends ACSObjectSelectionModel { + + private Long m_typeId; + + private static final Logger s_log = Logger.getLogger( + ItemSelectionModel.class); + + /** + * Construct a newItemSelectionModel. This model will produce
+ * instances of ContentItem by automatically instantiating the
+ * correct Java subclass using the
+ * {@link com.arsdigita.domain.DomainObjectFactory}.
+ *
+ * @param parameter The state parameter which should be used to store the
+ * object ID
+ */
+ public ItemSelectionModel(BigDecimalParameter parameter) {
+ this(null, null, parameter);
+ }
+
+ /**
+ * Construct a new ItemSelectionModel. This model will produce
+ * instances of ContentItem by automatically instantiating the
+ * correct Java subclass using the
+ * {@link com.arsdigita.domain.DomainObjectFactory}.
+ *
+ * @param parameterName The name of the state parameter which will be used
+ * to store the object ID.
+ */
+ public ItemSelectionModel(String parameterName) {
+ this(null, null, new BigDecimalParameter(parameterName));
+ }
+
+ /**
+ * Construct a new ItemSelectionModel. This model will produce
+ * instances of ContentItem by automatically instantiating the
+ * correct Java subclass using the
+ * {@link com.arsdigita.domain.DomainObjectFactory}.
+ *
+ * @param model The {@link SingleSelectionModel} which will supply a
+ * {@link BigDecimal} ID of the currently selected item
+ */
+ public ItemSelectionModel(SingleSelectionModel model) {
+ this(null, null, model);
+ }
+
+ /**
+ * Construct a new ItemSelectionModel
+ *
+ * @param type The content type for the items this model will
+ * generate
+ *
+ * @param parameterName The name of the state parameter which will be used
+ * to store the item.
+ */
+ public ItemSelectionModel(ContentType type, String parameterName) {
+ this(type, new BigDecimalParameter(parameterName));
+ }
+
+ /**
+ * Construct a new ItemSelectionModel
+ *
+ * @param type The content type for the items this model will generate
+ *
+ * @param parameter The state parameter which should be used by this item
+ *
+ */
+ public ItemSelectionModel(ContentType type, BigDecimalParameter parameter) {
+ super(type.getContentItemClass(), type.getContentItemClass(), parameter);
+ m_typeId = type.getObjectId();
+ }
+
+ /**
+ * Construct a new ItemSelectionModel
+ *
+ * @param type The content type for the items this model will generate
+ *
+ * @param model The {@link SingleSelectionModel} which will supply a
+ * {@link BigDecimal} id of the currently selected object
+ *
+ */
+ public ItemSelectionModel(ContentType type, SingleSelectionModel model) {
+ super(type.getContentItemClass(), type.getContentItemClass(), model);
+ m_typeId = type.getObjectId();
+ }
+
+ /**
+ * Construct a new ItemSelectionModel
+ *
+ * @param itemClass The name of the Java class which represents the
+ * content item. Must be a subclass of ContentItem. In
+ * addition, the class must have a constructor with a
+ * single OID parameter.
+ * @param objectType The name of the persistence metadata object type
+ * which represents the content item. In practice, will
+ * often be the same as the itemClass.
+ * @param parameterName The name of the state parameter which will be used
+ * to store the item.
+ */
+ public ItemSelectionModel(String itemClass,
+ String objectType,
+ String parameterName) {
+ super(itemClass, objectType, new BigDecimalParameter(parameterName));
+ }
+
+ /**
+ * Construct a new ItemSelectionModel
+ *
+ * @param itemClass The name of the Java class which represents the content
+ * item. Must be a subclass of ContentItem. In addition,
+ * the class must have a constructor with a single OID
+ * parameter.
+ * @param objectType The name of the persistence metadata object type which
+ * represents the content item. In practice, will often be
+ * the same as the itemClass.
+ * @param parameter The state parameter which should be used by this item
+ */
+ public ItemSelectionModel(String itemClass, String objectType,
+ BigDecimalParameter parameter) {
+ super(itemClass, objectType, parameter);
+ }
+
+ /**
+ * Construct a new ItemSelectionModel
+ *
+ * @param itemClass The name of the Java class which represents the content
+ * item. Must be a subclass of ContentItem. In addition,
+ * the class must have a constructor with a single OID
+ * parameter.
+ * @param objectType The name of the persistence metadata object type which
+ * represents the content item. In practice, will often be
+ * the same as the itemClass.
+ * @param model The {@link SingleSelectionModel} which will supply a
+ * {@link BigDecimal} id of the currently selected object
+ *
+ */
+ public ItemSelectionModel(String itemClass,
+ String objectType,
+ SingleSelectionModel model) {
+ super(itemClass, objectType, model);
+ }
+
+ /**
+ * A utility function which creates a new item with the given ID. Uses
+ * reflection to create the instance of the class supplied in the
+ * constructor to this ItemSelectionModel.
+ *
+ * @param id The id of the new item -- this is now ignored
+ *
+ * @return The newly created item
+ *
+ * @deprecated use createItem() instead
+ */
+ public ContentItem createItem(BigDecimal id) throws ServletException {
+ return (ContentItem) createACSObject();
+ }
+
+ /**
+ * A utility function which creates a new item. Uses reflection to create
+ * the instance of the class supplied in the constructor to this
+ * ItemSelectionModel.
+ *
+ * @return The newly created item
+ */
+ public ContentItem createItem() throws ServletException {
+ return (ContentItem) createACSObject();
+ }
+
+ /**
+ * A convenience method that gets the currently selected object and casts it
+ * to a ContentItem
+ *
+ * @param s the current page state
+ *
+ * @return the currently selected ContentItem, or null if no
+ * item was selected.
+ */
+ public final ContentItem getSelectedItem(PageState s) {
+ return (ContentItem) getSelectedObject(s);
+ }
+
+ /**
+ * A utility function which creates a new item with the given ID. Uses
+ * reflection to create the instance of the class supplied in the
+ * constructor to this ItemSelectionModel.
+ *
+ * @param id The id of the new item -- this is now ignored
+ *
+ * @return The newly created item
+ *
+ * @deprecated Use createACSObject() instead
+ */
+ public CcmObject createACSObject(BigDecimal id) throws ServletException {
+ return createACSObject();
+ }
+
+ /**
+ * A utility function which creates a new item. Uses reflection to create
+ * the instance of the class supplied in the constructor to this
+ * ItemSelectionModel.
+ *
+ * @return The newly created item
+ */
+ public CcmObject createACSObject() throws ServletException {
+ ContentType type = getContentType();
+ ContentItem item = (ContentItem) super.createACSObject();
+
+ if (type != null) {
+ item.setContentType(type);
+ }
+ return item;
+ }
+
+ /**
+ *
+ * @return The content type of the items which are produced by this model,
+ * or null if the content type has not been specified in the
+ * constructor.
+ */
+ public ContentType getContentType() {
+
+ ContentType type = null;
+
+ if (m_typeId != null) {
+ type = CdiUtil.createCdiUtil().findBean(ContentTypeRepository.class).findById(m_typeId);
+ }
+
+ return type;
+ }
+
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/BaseTree.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/BaseTree.java
new file mode 100755
index 000000000..6b7da2d54
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/BaseTree.java
@@ -0,0 +1,67 @@
+/*
+ * 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.bebop.Tree;
+import com.arsdigita.bebop.event.ChangeEvent;
+import com.arsdigita.bebop.event.ChangeListener;
+import com.arsdigita.bebop.event.TreeExpansionEvent;
+import com.arsdigita.bebop.event.TreeExpansionListener;
+import com.arsdigita.bebop.tree.TreeModelBuilder;
+import org.apache.log4j.Logger;
+
+/**
+ * A convenience class for CMS trees.
+ *
+ * @author Justin Ross <jross@redhat.com>
+ * @version $Id$
+ */
+public class BaseTree extends Tree {
+
+ private static final Logger s_log = Logger.getLogger(BaseTree.class);
+
+ public BaseTree(final TreeModelBuilder builder) {
+ super(builder);
+
+ addChangeListener(new Change());
+ addTreeExpansionListener(new TreeExpansion());
+ }
+
+ private class Change implements ChangeListener {
+ public final void stateChanged(final ChangeEvent e) {
+ final PageState state = e.getPageState();
+ final Object key = BaseTree.this.getSelectedKey(state);
+
+ if (key != null) {
+ expand(key.toString(), state);
+ }
+ }
+ }
+
+ private class TreeExpansion implements TreeExpansionListener {
+ public final void treeExpanded(final TreeExpansionEvent e) {
+ //s_log.error("expanded");
+ }
+
+ public final void treeCollapsed(final TreeExpansionEvent e) {
+ //s_log.error("collapsed");
+ }
+ }
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/BrowsePane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/BrowsePane.java.off
new file mode 100755
index 000000000..357e89738
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/BrowsePane.java.off
@@ -0,0 +1,226 @@
+/*
+ * 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.Label;
+import com.arsdigita.bebop.Page;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.Resettable;
+import com.arsdigita.bebop.SegmentedPanel;
+import com.arsdigita.bebop.SingleSelectionModel;
+import com.arsdigita.bebop.event.FormProcessListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.event.FormSubmissionListener;
+import com.arsdigita.bebop.event.ActionEvent;
+import com.arsdigita.bebop.event.ActionListener;
+import com.arsdigita.cms.CMS;
+import com.arsdigita.cms.ui.folder.FolderRequestLocal;
+import com.arsdigita.cms.ui.folder.FolderSelectionModel;
+import com.arsdigita.cms.ui.folder.FolderTreeModelBuilder;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.toolbox.ui.LayoutPanel;
+import com.arsdigita.util.Assert;
+import com.arsdigita.web.Web;
+
+import java.math.BigDecimal;
+
+import org.apache.log4j.Logger;
+import org.libreccm.categorization.Category;
+import org.libreccm.core.CcmObject;
+import org.librecms.CmsConstants;
+
+/**
+ * A pane that contains a folder tree on the left and a folder manipulator on
+ * the right. It is a part of the content section main page and is displayed as
+ * the "Browse" tab.
+ *
+ * @author David LutterKort <dlutter@redhat.com>
+ * @version $Id: BrowsePane.java 1325 2006-09-22 08:11:33Z sskracic $
+ */
+public class BrowsePane extends LayoutPanel implements Resettable {
+
+ private static final Logger s_log = Logger.getLogger(BrowsePane.class);
+
+ private final BaseTree m_tree;
+ private final SingleSelectionModel m_model;
+ private final FolderSelectionModel m_folderModel; // To support legacy UI code
+ private final FolderRequestLocal m_folder;
+ private final FlatItemList m_fil;
+
+ public BrowsePane() {
+
+ /* The folder tree displayed on the left side / left column */
+ m_tree = new BaseTree(new FolderTreeModelBuilder());
+ m_model = m_tree.getSelectionModel();
+ m_folderModel = new FolderSelectionModel(m_model);
+ m_folder = new FolderRequestLocal(m_folderModel);
+
+ final SegmentedPanel left = new SegmentedPanel();
+ setLeft(left);
+
+ final Label heading = new Label(
+ new GlobalizedMessage("cms.ui.folder_browser",
+ CmsConstants.CMS_FOLDER_BUNDLE));
+ left.addSegment(heading, m_tree);
+
+ m_fil = new FlatItemList(m_folder, m_folderModel);
+ setBody(m_fil);
+
+ m_fil.getManipulator().getItemView().addProcessListener(
+ new ProcessListener());
+ m_fil.getManipulator().getTargetSelector().addProcessListener(
+ new ProcessListener());
+ m_fil.getManipulator().getTargetSelector().addSubmissionListener(
+ new SubmissionListener());
+ }
+
+ @Override
+ public final void register(Page page) {
+ super.register(page);
+
+ page.addActionListener(new FolderListener());
+ page.addActionListener(new TreeListener());
+ }
+
+ @Override
+ public final void reset(PageState state) {
+ super.reset(state);
+
+ m_fil.reset(state);
+ }
+
+ // Private classes and methods
+ /**
+ *
+ */
+ private final class ProcessListener implements FormProcessListener {
+
+ /**
+ *
+ * @param e
+ */
+ public final void process(final FormSectionEvent e) {
+ final PageState state = e.getPageState();
+
+ if (e.getSource() == m_fil.getManipulator().getItemView()) {
+ // Hide everything except for the flat item list
+ m_tree.setVisible(state, false);
+ } else if (e.getSource() == m_fil.getManipulator()
+ .getTargetSelector()) {
+ m_tree.setVisible(state, true);
+ }
+ }
+
+ }
+
+ private final class SubmissionListener implements FormSubmissionListener {
+
+ public final void submitted(final FormSectionEvent e) {
+ final PageState s = e.getPageState();
+
+ if (e.getSource() == m_fil.getManipulator().getTargetSelector()) {
+ if (!m_fil.getManipulator().getTargetSelector().isVisible(s)) {
+ m_tree.setVisible(s, true);
+ }
+ }
+ }
+
+ }
+
+ private final class FolderListener implements ActionListener {
+
+ public final void actionPerformed(final ActionEvent e) {
+ final PageState state = e.getPageState();
+
+ if (!m_model.isSelected(state)) {
+ final String folder = state.getRequest().getParameter(
+ ContentSectionPage.SET_FOLDER);
+
+ if (folder == null) {
+ final Category root = CMS.getContext().getContentSection()
+ .getRootDocumentsFolder();
+ Long folderID = root.getObjectId();
+
+ /*
+ ToDo
+ User user = Web.getWebContext().getUser();
+ if (user != null) {
+ Folder homeFolder = Folder.getUserHomeFolder(
+ user, CMS.getContext().getContentSection());
+ if (homeFolder != null) {
+ folderID = homeFolder.getID();
+ }
+
+ }*/
+ m_model.setSelectedKey(state, folderID);
+ } else {
+ m_model.setSelectedKey(state, folder);
+ }
+ }
+ }
+
+ }
+
+ private final class TreeListener implements ActionListener {
+
+ public final void actionPerformed(final ActionEvent e) {
+ final PageState state = e.getPageState();
+
+ if (Assert.isEnabled()) {
+ Assert.isTrue(m_model.isSelected(state));
+ }
+
+ final Category root = CMS.getContext().getContentSection()
+ .getRootDocumentsFolder();
+
+ if (!root.equals(m_folder.getFolder(state))) {
+ // Expand the ancestor nodes of the currently
+ // selected node.
+
+ CcmObject object = m_folder.getFolder(state);
+
+ while (object != null) {
+ if (object instanceof Category) {
+ final Category category = (Category) object;
+
+ if (category.getParent().isPresent()) {
+ final CcmObject result = category.getParent().get();
+
+ if (result instanceof Category) {
+ object = result;
+ m_tree.expand(
+ ((Long) object.getObjectId()).toString(),
+ state);
+ } else {
+ object = null;
+ }
+ } else {
+ object = null;
+ }
+
+ } else {
+ object = null;
+ }
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/CcmObjectRequestLocal.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/CcmObjectRequestLocal.java
new file mode 100755
index 000000000..db03a326c
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/CcmObjectRequestLocal.java
@@ -0,0 +1,40 @@
+/*
+ * 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.bebop.RequestLocal;
+
+import org.apache.log4j.Logger;
+import org.libreccm.core.CcmObject;
+
+
+/**
+ *
+ * @version $Id$
+ */
+public class CcmObjectRequestLocal extends RequestLocal {
+
+ private static final Logger s_log = Logger.getLogger
+ (CcmObjectRequestLocal.class);
+
+ public final CcmObject getACSObject(final PageState state) {
+ return (CcmObject) get(state);
+ }
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionContextBar.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionContextBar.java.off
new file mode 100755
index 000000000..252c6df83
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionContextBar.java.off
@@ -0,0 +1,156 @@
+/*
+ * 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.ContentBundle;
+import com.arsdigita.cms.ContentItem;
+import com.arsdigita.cms.ContentSection;
+import com.arsdigita.cms.ContentType;
+import com.arsdigita.cms.Folder;
+import com.arsdigita.cms.PageLocations;
+import com.arsdigita.cms.Template;
+import com.arsdigita.kernel.ACSObject;
+import com.arsdigita.web.ParameterMap;
+import com.arsdigita.web.URL;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Stack;
+
+import org.apache.log4j.Logger;
+
+/**
+ * The context bar of the content section UI.
+ *
+ * @author Justin Ross <jross@redhat.com>
+ * @version $Id: ContentSectionContextBar.java 287 2005-02-22 00:29:02Z sskracic $
+ */
+// class ContentSectionContextBar extends WorkspaceContextBar {
+public class ContentSectionContextBar extends WorkspaceContextBar {
+
+ private static final Logger s_log = Logger.getLogger
+ (ContentSectionContextBar.class);
+
+ @Override
+ protected List entries(final PageState state) {
+
+ /* Include breadcrumb entries already set by content-center (i.e. the
+ * URL of the content center itself */
+ final List entries = super.entries(state);
+
+ final ContentSection section = CMS.getContext().getContentSection();
+ final Stack folderEntryStack = new Stack();
+ String currentFolderLabel = null;
+ ParameterMap params = new ParameterMap();
+ boolean isTemplate = false;
+ BigDecimal templateID = null;
+
+ if (CMS.getContext().hasContentItem()) {
+ final ContentItem item = CMS.getContext().getContentItem();
+ if (item == null) {
+ s_log.warn("item is null");
+ } else if(item.getContentType() == null) {
+ s_log.warn("item.getContentType() returns null. item.class.getName(): "
+ + item.getClass().getName());
+ }
+ isTemplate =
+ item.getContentType().equals(ContentType
+ .findByAssociatedObjectType(Template.BASE_DATA_OBJECT_TYPE));
+ if (isTemplate) {
+ templateID = item.getID();
+ }
+ ACSObject parent = item.getParent();
+
+ while (!isTemplate && parent != null && parent instanceof ContentItem) {
+ if (currentFolderLabel != null) {
+ final URL folderURL = URL.there
+ (state.getRequest(),
+ section.getPath() + "/" + PageLocations.SECTION_PAGE,
+ params);
+ folderEntryStack.push(new Entry(currentFolderLabel, folderURL));
+ currentFolderLabel = null;
+ params = new ParameterMap();
+ }
+ final ContentItem pitem = (ContentItem) parent;
+
+ if (pitem instanceof Folder) {
+ final Folder folder = (Folder) pitem;
+ parent = folder.getParent();
+
+ currentFolderLabel = folder.getLabel();
+ if (parent != null || folder.equals(section.getRootFolder())) {
+ params.setParameter
+ (ContentSectionPage.SET_FOLDER, folder.getID());
+ }
+ } else if (pitem instanceof ContentBundle) {
+ final ACSObject ppitem = pitem.getParent();
+
+ if (ppitem != null && ppitem instanceof Folder) {
+ final Folder folder = (Folder) ppitem;
+
+ parent = folder.getParent();
+ currentFolderLabel = folder.getLabel();
+ if (parent != null || folder.equals(section
+ .getRootFolder())) {
+ params.setParameter
+ (ContentSectionPage.SET_FOLDER, folder.getID());
+ }
+ } else {
+ parent = null;
+ }
+ } else {
+ parent = null;
+ }
+ }
+
+ }
+
+ if (isTemplate) {
+ params.setParameter
+ ( ContentSectionPage.SET_TAB,
+ new BigDecimal(ContentSectionPage.CONTENTTYPES_TAB) );
+ params.setParameter(ContentSectionPage.SET_TEMPLATE, templateID);
+ }
+ // add section-level entry. if this is for an item page, the URL
+ // will be for the root folder.
+ final URL url = URL.there
+ (state.getRequest(),
+ section.getPath() + "/" + PageLocations.SECTION_PAGE,
+ params);
+
+
+ final String sectionTitle = lz("cms.ui.content_section");
+ final String title = sectionTitle + ": " + section.getName();
+
+ entries.add(new Entry(title, url));
+
+ // add any folders to the path now
+ while (!folderEntryStack.empty()) {
+ entries.add(folderEntryStack.pop());
+ }
+
+ return entries;
+ }
+
+ private static String lz(final String key) {
+ return (String) ContentSectionPage.globalize(key).localize();
+ }
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionPage.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionPage.java.off
new file mode 100755
index 000000000..6b708faf5
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionPage.java.off
@@ -0,0 +1,524 @@
+/*
+ * 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.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.SimpleComponent;
+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.PrintEvent;
+import com.arsdigita.bebop.event.PrintListener;
+import com.arsdigita.cms.CMS;
+
+import org.librecms.contentsection.ContentItem;
+import org.librecms.contentsection.ContentSection;
+
+import com.arsdigita.cms.dispatcher.CMSPage;
+import com.arsdigita.cms.ui.category.CategoryAdminPane;
+import com.arsdigita.cms.ui.cse.ContentSoonExpiredPane;
+import com.arsdigita.cms.ui.folder.FolderAdminPane;
+import com.arsdigita.cms.ui.lifecycle.LifecycleAdminPane;
+import com.arsdigita.cms.ui.role.RoleAdminPane;
+import com.arsdigita.cms.ui.type.ContentTypeAdminPane;
+import com.arsdigita.cms.ui.workflow.WorkflowAdminPane;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.toolbox.ui.LayoutPanel;
+import com.arsdigita.util.Assert;
+import com.arsdigita.web.Web;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.log4j.Logger;
+import org.arsdigita.cms.CMSConfig;
+import org.libreccm.cdi.utils.CdiUtil;
+import org.libreccm.security.PermissionChecker;
+import org.librecms.CmsConstants;
+import org.librecms.contentsection.ContentItemVersion;
+import org.librecms.contentsection.ContentSectionConfig;
+
+/**
+ * Contains the entire admin UI for a content section.
+ *
+ * Developers Note: It is based on the dispatcher model is is going to be
+ * replaced by the newer servlet based model. @see
+ * c.ad.cms.ui.contentsection.MainPage (currently not active).
+ *
+ * @author Jack Chung
+ * @author Michael Pih
+ * @author Xixi D'Moon <xdmoon@redhat.com>
+ * @author Justin Ross <jross@redhat.com>
+ * @version $Id: ContentSectionPage.java 2224 2011-08-01 07:45:23Z pboy $
+ */
+public class ContentSectionPage extends CMSPage implements ActionListener {
+
+ private static final Logger s_log = Logger.getLogger(
+ ContentSectionPage.class);
+ public static final String RESOURCE_BUNDLE
+ = "com.arsdigita.cms.CMSResources";
+ /**
+ * The URL parameter that can be passed in in order to set the current
+ * folder. This is used in getting back to the correct level of folder
+ * expansion from content item page.
+ */
+ public static final String SET_FOLDER = "set_folder";
+ /**
+ * The URL parameter that can be passed in in order to set the current
+ * template (for setting the content type)
+ */
+ public static final String SET_TEMPLATE = "set_template";
+ /**
+ * The URL parameter that can 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";
+ /**
+ * Index of the search tab
+ */
+ public static final int SEARCH_TAB = 0;
+ /**
+ * Index of the browse tab
+ */
+ public static final int BROWSE_TAB = 1;
+ /**
+ * Index of the roles tab
+ */
+ public static final int ROLES_TAB = 2;
+ /**
+ * Index of the workflows tab
+ */
+ public static final int WORKFLOW_TAB = 3;
+ /**
+ * Index of the lifecycles tab
+ */
+ public static final int LIFECYCLES_TAB = 4;
+ /**
+ * Index of the categories tab
+ */
+ public static final int CATEGORIES_TAB = 5;
+ /**
+ * Index of the content types tab
+ */
+ public static final int CONTENTTYPES_TAB = 6;
+ public static final int USER_ADMIN_TAB = 7;
+ private TabbedPane m_tabbedPane;
+ private FolderAdminPane m_folderPane;
+ private BrowsePane m_browsePane;
+ private ItemSearch m_searchPane;
+ private ImagesPane m_imagesPane;
+ private RoleAdminPane m_rolePane;
+ private WorkflowAdminPane m_workflowPane;
+ private LifecycleAdminPane m_lifecyclePane;
+ private CategoryAdminPane m_categoryPane;
+ private ContentTypeAdminPane m_typePane;
+ //private LayoutPanel m_userAdminPane;
+ private LayoutPanel m_csePane;
+ private ReportPane m_reportPane;
+
+ /**
+ * Creates the content section index page containing - a Navigaton bar for
+ * the various tasks (items, search, images, ....) - a breadcrumb - ....
+ * Contains the UI for administering a content section.
+ */
+ public ContentSectionPage() {
+ super(new Label(new TitlePrinter()), new SimpleContainer());
+
+ setClassAttr("cms-admin");
+
+ add(new GlobalNavigation());
+ add(new ContentSectionContextBar());
+
+ // Initialize the individual panes
+ m_folderPane = getFolderAdminPane();
+ m_browsePane = getBrowsePane();
+ m_searchPane = getSearchPane();
+ m_imagesPane = getImagesPane();
+ m_rolePane = getRoleAdminPane();
+ m_workflowPane = getWorkflowAdminPane();
+ m_lifecyclePane = getLifecycleAdminPane();
+ m_categoryPane = getCategoryAdminPane();
+ m_typePane = getContentTypeAdminPane();
+ // userAdminPane removed, used to contain just one item (reset user
+ // folder) which moved to the FolderAdminPane
+ //m_userAdminPane = getUserAdminPane();
+ m_csePane = getCSEPane();
+ m_reportPane = getReportPane();
+
+ // The panes
+ m_tabbedPane = createTabbedPane();
+ m_tabbedPane.setIdAttr("page-body");
+ m_tabbedPane.addActionListener(this);
+ add(m_tabbedPane);
+
+ addActionListener(new ActionListener() {
+
+ @Override
+ public final void actionPerformed(ActionEvent e) {
+ final PageState state = e.getPageState();
+
+ final String tab = state.getRequest().getParameter(SET_TAB);
+
+ if (tab != null) {
+ m_tabbedPane.setSelectedIndex(state, Integer.valueOf(tab)
+ .intValue());
+ }
+
+ final PermissionChecker permissionChecker = CdiUtil
+ .createCdiUtil().findBean(PermissionChecker.class);
+
+ //m_tabbedPane.setTabVisible(state, m_userAdminPane, sm.canAccess(user, SecurityConstants.STAFF_ADMIN));
+ if (CMSConfig.getConfig().isHideAdminTabs()) {
+ m_tabbedPane.setTabVisible(
+ state,
+ m_workflowPane,
+ permissionChecker.isPermitted(
+ CmsConstants.PRIVILEGE_ADMINISTER_WORKFLOW));
+ m_tabbedPane.setTabVisible(
+ state, m_categoryPane,
+ permissionChecker.isPermitted(
+ CmsConstants.PRIVILEGE_ADMINISTER_CATEGORIES));
+ m_tabbedPane.setTabVisible(
+ state,
+ m_lifecyclePane,
+ permissionChecker.isPermitted(
+ CmsConstants.PRIVILEGE_ADMINISTER_LIFECYLES));
+ m_tabbedPane.setTabVisible(
+ state,
+ m_typePane,
+ permissionChecker.isPermitted(
+ CmsConstants.PRIVILEGE_ADMINISTER_CONTENT_TYPES));
+ m_tabbedPane.setTabVisible(
+ state,
+ m_rolePane,
+ permissionChecker.isPermitted(
+ CmsConstants.PRIVILEGE_ADMINISTER_ROLES));
+ // csePane: should check permission
+ m_tabbedPane.setTabVisible(state, m_csePane, true);
+ // TODO Check for reportPane as well
+ }
+ }
+
+ });
+ }
+
+ /**
+ * Creates, and then caches, the browse pane. Overriding this method to
+ * return null will prevent this tab from appearing.
+ * @return
+ */
+ protected FolderAdminPane getFolderAdminPane() {
+ if (m_folderPane == null) {
+ m_folderPane = new FolderAdminPane();
+ }
+ return m_folderPane;
+ }
+
+ /**
+ * Creates, and then caches, the browse pane. Overriding this method to
+ * return null will prevent this tab from appearing.
+ *
+ * @return
+ */
+ protected BrowsePane getBrowsePane() {
+ if (m_browsePane == null) {
+ m_browsePane = new BrowsePane();
+ }
+ return m_browsePane;
+ }
+
+ /**
+ * Creates, and then caches, the search pane. Overriding this method to
+ * return null will prevent this tab from appearing.
+ * @return
+ */
+ protected ItemSearch getSearchPane() {
+ if (m_searchPane == null) {
+ m_searchPane
+ = new ItemSearch(
+ ContentItemVersion.DRAFT.toString(),
+ CMSConfig.getConfig().isLimitItemSearchToContentSection());
+ }
+ return m_searchPane;
+ }
+
+ protected ImagesPane getImagesPane() {
+ if (m_imagesPane == null) {
+ m_imagesPane = new ImagesPane();
+ }
+ return m_imagesPane;
+ }
+
+ protected RoleAdminPane getRoleAdminPane() {
+ if (m_rolePane == null) {
+ m_rolePane = new RoleAdminPane();
+ }
+ return m_rolePane;
+ }
+
+ /**
+ * Creates, and then caches, the workflow administration pane. Overriding
+ * this method to return null will prevent this tab from appearing.
+ */
+ protected WorkflowAdminPane getWorkflowAdminPane() {
+ if (m_workflowPane == null) {
+ m_workflowPane = new WorkflowAdminPane();
+ }
+ return m_workflowPane;
+ }
+
+ /**
+ * Creates, and then caches, the lifecycle administration pane. Overriding
+ * this method to return null will prevent this tab from appearing.
+ */
+ protected LifecycleAdminPane getLifecycleAdminPane() {
+ if (m_lifecyclePane == null) {
+ m_lifecyclePane = new LifecycleAdminPane();
+ }
+ return m_lifecyclePane;
+ }
+
+ /**
+ * Creates, and then caches, the category administration pane. Overriding
+ * this method to return null will prevent this tab from appearing.
+ */
+ protected CategoryAdminPane getCategoryAdminPane() {
+ if (m_categoryPane == null) {
+ m_categoryPane = new CategoryAdminPane();
+ }
+ return m_categoryPane;
+ }
+
+ /**
+ * Creates, and then caches, the content type administration pane.
+ * Overriding this method to return null will prevent this tab from
+ * appearing.
+ */
+ protected ContentTypeAdminPane getContentTypeAdminPane() {
+ if (m_typePane == null) {
+ m_typePane = new ContentTypeAdminPane();
+ }
+ return m_typePane;
+ }
+
+// protected LayoutPanel getUserAdminPane() {
+// if (m_userAdminPane == null) {
+// m_userAdminPane = new LayoutPanel();
+// m_userAdminPane.setLeft(new SimpleComponent());
+// m_userAdminPane.setBody(new UserAdminPane());
+// }
+// return m_userAdminPane;
+// }
+ protected LayoutPanel getCSEPane() {
+ if (m_csePane == null) {
+ m_csePane = new LayoutPanel();
+ m_csePane.setLeft(new SimpleComponent());
+ m_csePane.setBody(new ContentSoonExpiredPane());
+ }
+ return m_csePane;
+ }
+
+ protected ReportPane getReportPane() {
+ if (m_reportPane == null) {
+ m_reportPane = new ReportPane();
+ }
+ return m_reportPane;
+ }
+
+ /**
+ * Adds the specified component, with the specified tab name, to the tabbed
+ * pane only if it is not null.
+ *
+ * @param pane The pane to which to add the tab
+ * @param tabName The name of the tab if it's added
+ * @param comp The component to add to the pane
+ */
+ protected void addToPane(TabbedPane pane, String tabName, Component comp) {
+ if (comp != null) {
+ pane.addTab(new Label(tabName), comp);
+ }
+ }
+
+ private void tab(final TabbedPane pane,
+ final String key,
+ final Component tab) {
+ if (tab != null) {
+ pane.addTab(new Label(gz(key)), tab);
+ }
+ }
+
+ /**
+ * + * Created the TabbedPane to use for this page. Adds the tabs to the pane. + * The default implementation uses a {@link + * com.arsdigita.bebop.TabbedPane}. This implementation also adds browse, + * search, staff admin, viewers admin, workflow admin, category admin, and + * content type panes.
+ * + *+ * Developers can override this method to add only the tabs they want, or to + * add additional tabs after the default CMS tabs are added.
+ * + * @return + */ + protected TabbedPane createTabbedPane() { + final TabbedPane pane = new TabbedPane(); + + //tab(pane, "cms.ui.folders", getFolderAdminPane()); + tab(pane, "cms.ui.browse", getBrowsePane()); + tab(pane, "cms.ui.search", getSearchPane()); + tab(pane, "cms.ui.images", getImagesPane()); + tab(pane, "cms.ui.roles", getRoleAdminPane()); + tab(pane, "cms.ui.workflows", getWorkflowAdminPane()); + tab(pane, "cms.ui.lifecycles", getLifecycleAdminPane()); + tab(pane, "cms.ui.categories", getCategoryAdminPane()); + tab(pane, "cms.ui.content_types", getContentTypeAdminPane()); + // user admin tab removed from tab bar and the only one widget there + // (reset home folder) moved to folder browser + // tab(pane, "cms.ui.user_admin", getUserAdminPane()); + tab(pane, "cms.ui.cse", getCSEPane()); + //if (DbHelper.getDatabase() == DbHelper.DB_ORACLE) { + tab(pane, "cms.ui.reports", getReportPane()); + //} + + return pane; + } + + /** + * Fetch the request-local content section. + * + * @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; + } + + /** + * When a new tab is selected, reset the state of the formerly-selected + * pane. + * + * @param event The event fired by selecting a tab + */ + @Override + public void actionPerformed(ActionEvent event) { + final PageState state = event.getPageState(); + + final Component pane = m_tabbedPane.getCurrentPane(state); + + if (pane == m_searchPane) { + m_searchPane.reset(state); + } else if (pane == m_imagesPane) { + m_imagesPane.reset(state); + } else if (pane == m_folderPane) { + m_folderPane.reset(state); + } else if (pane == m_browsePane) { + m_browsePane.reset(state); + } else if (pane == m_rolePane) { + m_rolePane.reset(state); + } else if (pane == m_workflowPane) { + m_workflowPane.reset(state); + } else if (pane == m_lifecyclePane) { + m_lifecyclePane.reset(state); + } else if (pane == m_categoryPane) { + m_categoryPane.reset(state); + } else if (pane == m_typePane) { + m_typePane.reset(state); +// } else if (pane == m_userAdminPane) { + //m_userAdminPane.reset(state); + } else if (pane == m_csePane) { + //m_csePane.reset(state); + } + } + + /** + * Construct a URL for displaying the tab + * + * @param item The item from which we get the corresponding content section + * @param tab The index of the tab to display + * + * @return + */ + public static String getSectionURL(ContentItem item, int tab) { + // Get the content section associated with the content item. + ContentSection section = ContentSection.getContentSection(item); + + String url = section.getURL() + PageLocations.SECTION_PAGE + + "?" + SET_TAB + "=" + tab; + + return url; + } + + private static GlobalizedMessage gz(final String key) { + return new GlobalizedMessage(key, RESOURCE_BUNDLE); + } + + /** + * Getting the GlobalizedMessage using a CMS Class targetBundle. + * + * @param key The resource key + * + * @return + * + * @pre key != null + */ + public static GlobalizedMessage globalize(final String key) { + return new GlobalizedMessage(key, RESOURCE_BUNDLE); + } + + /** + * + * @param key + * @param args + * + * @return + */ + public static GlobalizedMessage globalize(final String key, + final Object[] args) { + return new GlobalizedMessage(key, RESOURCE_BUNDLE, args); + } + + /** + * Helper class to be able to use a PrintListener to set the titel of the + * page. + */ + private static class TitlePrinter implements PrintListener { + + /** + * + * @param e + */ + @Override + public void prepare(PrintEvent e) { + final Label l = (Label) e.getTarget(); + + l.setLabel(CMS.getContext().getContentSection().getName()); + } + + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/FlatItemList.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/FlatItemList.java.off new file mode 100755 index 000000000..147b504e3 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/FlatItemList.java.off @@ -0,0 +1,604 @@ +/* + * 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.ActionLink; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.ParameterSingleSelectionModel; +import com.arsdigita.bebop.Resettable; +import com.arsdigita.bebop.SegmentedPanel; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.ChangeEvent; +import com.arsdigita.bebop.event.ChangeListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.FormSubmissionListener; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.cms.CMS; +import org.librecms.contentsection.ContentSection; +import com.arsdigita.cms.dispatcher.Utilities; +import com.arsdigita.cms.ui.authoring.CreationSelector; +import com.arsdigita.cms.ui.authoring.NewItemForm; +import com.arsdigita.cms.ui.folder.FolderCreator; +import com.arsdigita.cms.ui.folder.FolderEditor; +import com.arsdigita.cms.ui.folder.FolderManipulator; +import com.arsdigita.cms.ui.folder.FolderRequestLocal; +import com.arsdigita.cms.ui.folder.FolderSelectionModel; +import com.arsdigita.cms.ui.folder.ItemPath; +import com.arsdigita.cms.ui.permissions.CMSPermissionsPane; +import com.arsdigita.cms.util.GlobalizationUtil; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.kernel.ACSObject; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.User; +import com.arsdigita.kernel.permissions.ObjectPermissionCollection; +import com.arsdigita.kernel.permissions.PermissionDescriptor; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.DataQuery; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.toolbox.ui.ActionGroup; +import com.arsdigita.util.Assert; +import com.arsdigita.web.Web; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Encapsulates a {@link FolderManipulator} in order to create a flat item + * listing. Also contains a new item form. + * + * @author Stanislav Freidin + * @version $Id: FlatItemList.java 1538 2007-03-23 16:26:36Z apevec $ + */ +public class FlatItemList extends SegmentedPanel + implements FormProcessListener, ChangeListener, FormSubmissionListener, + Resettable, ActionListener { + + private static final String CONTENT_TYPE_ID = "ct"; + private static final String CMS_PRIVILEGES = "com.arsdigita.cms.getPrivileges"; + private static final String PRIVILEGE = "privilege"; + private static final String PRIVILEGE_NAME = "prettyName"; + // The folder selectors + private final FolderSelectionModel m_folderSel; + private FolderRequestLocal m_folder; + private final NewItemForm m_newItem; + private final SingleSelectionModel m_typeSel; + private final CreationSelector m_selector; + private final FolderManipulator m_folderManip; + private final FolderCreator m_folderCreator; + private final ActionLink m_setHomeFolderAction; + private final ActionLink m_removeHomeFolderAction; + private final ActionLink m_createFolderAction; + private final ActionLink m_togglePrivateAction; + private final Label m_homeFolderLabel; + private final Segment m_browseSeg; + private final Segment m_newItemSeg; + private final Segment m_newFolderSeg; + private final Segment m_editFolderSeg; + private final Segment m_permissionsSeg; + private final CMSPermissionsPane m_permPane; + // Folder edit/rename functionality. + private final ActionLink m_editFolderAction; + private final FolderEditor m_folderEditor; + private final Label m_contentLabel; + private final ItemPath m_itemPath; + private final Label m_chooseLabel; + + /** + * Construct a new item listing pane. The provided folder selection model + * is used to keep track of the currently displayed folder. + * + * @param folder + * @param model maintains the currently displayed folder. + */ + public FlatItemList(final FolderRequestLocal folder, + final FolderSelectionModel model) { + m_folder = folder; + m_folderSel = model; + m_folderSel.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + PageState s = e.getPageState(); + reset(s); + } + + }); + + setIdAttr("flat-item-list"); + + m_newItemSeg = addSegment(); + m_newItemSeg.setIdAttr("folder-new-item"); + + m_newFolderSeg = addSegment(); + m_newFolderSeg.setIdAttr("folder-new-folder"); + + m_editFolderSeg = addSegment(); + m_editFolderSeg.setIdAttr("folder-edit-folder"); + + m_browseSeg = addSegment(); + m_browseSeg.setIdAttr("folder-browse"); + + final ActionGroup browseActions = new ActionGroup(); + m_browseSeg.add(browseActions); + + // The top 'browse' segment + m_contentLabel = new Label(globalize("cms.ui.contents_of"), false); + m_browseSeg.addHeader(m_contentLabel); + m_chooseLabel = new Label(globalize("cms.ui.choose_target_folder"), false); + m_browseSeg.addHeader(m_chooseLabel); + m_itemPath = new ItemPath(m_folderSel); + //m_itemPath = new Label(new PrintListener() { + // public final void prepare(final PrintEvent e) { + // final Folder f = m_folder.getFolder(e.getPageState()); + // ((Label) e.getTarget()).setLabel(f.getDisplayName()); + // } + // }); + + m_browseSeg.addHeader(m_itemPath); + m_folderManip = new FolderManipulator(m_folderSel); + m_folderManip.getItemView().addProcessListener(this); + m_folderManip.getTargetSelector().addProcessListener(this); + m_folderManip.getTargetSelector().addSubmissionListener(this); + + browseActions.setSubject(m_folderManip); + + // The actions + + m_createFolderAction = new ActionLink(new Label(globalize("cms.ui.new_folder"))); + m_createFolderAction.addActionListener(this); + browseActions.addAction(m_createFolderAction); + + m_editFolderAction = new ActionLink(new Label(globalize("cms.ui.edit_folder"))); + m_editFolderAction.addActionListener(this); + browseActions.addAction(m_editFolderAction); + + m_setHomeFolderAction = new ActionLink(new Label(globalize("cms.ui.set_home_folder"))); + m_setHomeFolderAction.addActionListener(this); + browseActions.addAction(m_setHomeFolderAction); + + m_homeFolderLabel = new Label(new PrintListener() { + @Override + public final void prepare(final PrintEvent e) { + Label label = (Label) e.getTarget(); + User user = Web.getWebContext().getUser(); + + Folder folder = Folder.getUserHomeFolder(user, CMS.getContext().getContentSection()); + if (folder != null) { + String url = folder.getContentSection().getURL() + PageLocations.SECTION_PAGE + "?" + + ContentSectionPage.SET_FOLDER + "=" + folder.getID(); + //label.setLabel("Go to home folder: " + folder.getLabel() + ""); + String[] parts = new String[3]; + parts[0] = ""; + parts[1] = url; + parts[2] = folder.getLabel(); + // label.setLabel(String.format("%s: %s", + // (String) globalize("cms.ui.go_to_home_folder").localize(), + // url, + // folder.getLabel())); + label.setLabel( globalize("cms.ui.go_to_home_folder",parts) ); + } else { + //label.setLabel("No home folder selected"); + String[] parts = new String[3]; + parts[0] = ""; + parts[1] = ""; + //label.setLabel(String.format("%s", + // (String)globalize("cms.ui.no_home_folder_selected").localize())); + label.setLabel( globalize("cms.ui.no_home_folder_selected",parts) ); + } + label.setOutputEscaping(false); + } + + }); + browseActions.addAction(m_homeFolderLabel); + + m_removeHomeFolderAction = new ActionLink(new Label(globalize("cms.ui.remove_home_folder"))); + m_removeHomeFolderAction.addActionListener(this); + browseActions.addAction(m_removeHomeFolderAction); + + /* */ + m_newItem = new SectionNewItemForm("newItem"); + m_newItem.addProcessListener(this); + browseActions.addAction(m_newItem); + + /* permission */ + m_permissionsSeg = addSegment(); + m_permissionsSeg.setIdAttr("folder-permissions"); + + final ActionGroup permActions = new ActionGroup(); + m_permissionsSeg.add(permActions); + + // The permissions segment + m_permissionsSeg.addHeader(new Label(GlobalizationUtil.globalize("cms.ui.permissions"))); + + List privs = new ArrayList(); + Map privNameMap = new HashMap(); + DataQuery query = SessionManager.getSession().retrieveQuery(CMS_PRIVILEGES); + query.addFilter("scope != 'section'"); + query.addOrder("sortOrder"); + while (query.next()) { + String privilege = (String) query.get(PRIVILEGE); + String privilegeName = (String) query.get(PRIVILEGE_NAME); + privs.add(PrivilegeDescriptor.get(privilege)); + privNameMap.put(privilege, privilegeName); + } + query.close(); + + m_permPane = + new CMSPermissionsPane((PrivilegeDescriptor[]) privs.toArray(new PrivilegeDescriptor[privs.size()]), + privNameMap, + m_folderSel); + permActions.setSubject(m_permPane); + + // An action + + m_togglePrivateAction = new ActionLink(new Label(new PrintListener() { + public void prepare(PrintEvent e) { + PageState state = e.getPageState(); + Label target = (Label) e.getTarget(); + Folder currentFolder = m_folder.getFolder(state); + // ACSObject parent = currentFolder.getParent(); + DataObject context = PermissionService.getContext(currentFolder); + if (context == null) { + target.setLabel(GlobalizationUtil + .globalize("cms.ui.restore_default_permissions")); + } else { + target.setLabel(GlobalizationUtil + .globalize("cms.ui.use_custom_permissions")); + } + } + + })); + m_togglePrivateAction.addActionListener(this); + permActions.addAction(m_togglePrivateAction); + + // The 'new item' segment + m_newItemSeg.addHeader(new Label(globalize("cms.ui.new_item"))); + m_typeSel = new ParameterSingleSelectionModel(new BigDecimalParameter(CONTENT_TYPE_ID)); + m_typeSel.addChangeListener(this); + + m_selector = new CreationSelector(m_typeSel, m_folderSel); + m_newItemSeg.add(m_selector); + //m_newItemSeg.add(new Label("+ * + * If the creation component wishes to cancel the creation process, + * it should call + * + *+ * // The member variable m_parent points to the CreationSelector + * SomeContentItem item = somehowCreateTheItem(state); + * item.setParent(m_parent.getFolder(state)); + * m_parent.editItem(state, item); + *
+ * + * The component may also call + * + *m_parent.redirectBack(state);
+ * + * in order to get the current content section. + * + * @version $Id: CreationSelector.java 2185 2011-06-20 21:16:02Z pboy $ + */ +public class CreationSelector extends MetaForm { + + private static Logger s_log = Logger.getLogger(CreationSelector.class); + + private final FolderSelectionModel m_folderSel; + private final SingleSelectionModel m_typeSel; + + private static Class[] s_args = new Class[] { + ItemSelectionModel.class, + CreationSelector.class + }; + + private Object[] m_vals; + + private ItemSelectionModel m_itemSel; + private BigDecimalParameter m_itemId; + + private ItemSelectionModel m_bundleSel; + private BigDecimalParameter m_bundleId; + + public static final String ITEM_ID = "iid"; + public static final String BUNDLE_ID = "bid"; + + /** + * Constructs a newm_parent.getContentSection(state);
CreationSelector. Load all the
+ * possible creation components from the database and stick them
+ * in the Map.
+ *
+ * @param typeModel the {@link SingleSelectionModel} which will
+ * supply a BigDecimal ID of the content type to instantiate
+ *
+ * @param folderModel the {@link FolderSelectionModel} containing
+ * the folder in which new items are to be created
+ */
+ public CreationSelector(final SingleSelectionModel typeModel,
+ final FolderSelectionModel folderModel) {
+ super("pageCreate");
+
+ m_typeSel = typeModel;
+
+ m_folderSel = folderModel;
+ m_itemId = new BigDecimalParameter(ITEM_ID);
+ m_bundleId = new BigDecimalParameter(BUNDLE_ID);
+ m_bundleSel = new ItemSelectionModel(ContentBundle.class.getName(),
+ ContentBundle.BASE_DATA_OBJECT_TYPE, m_bundleId);
+ }
+
+
+ /**
+ *
+ * @param state
+ * @return
+ */
+ @Override
+ public Form buildForm(PageState state) {
+ BigDecimal typeID = (BigDecimal)m_typeSel.getSelectedKey(state);
+ Component c = null;
+ Form returnForm = new Form("pageCreate");
+ FormErrorDisplay fed = new FormErrorDisplay(this);
+ fed.setStateParamsAreRegistered(false);
+ returnForm.add(fed , ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);
+ if (typeID != null) {
+ try {
+ ContentType type = new ContentType(typeID);
+ AuthoringKit kit = type.getAuthoringKit();
+ if(kit != null) {
+ c = instantiateKitComponent(kit, type);
+ if(c != null) {
+ returnForm.add(c);
+ returnForm.setMethod(Form.POST);
+ returnForm.setEncType("multipart/form-data");
+ }
+ }
+ } catch (DataObjectNotFoundException e) {
+ // content type not found
+ }
+ }
+ return returnForm;
+ }
+
+ /**
+ * Add the item_id parameter.
+ *
+ * @param p
+ */
+ @Override
+ public void register(Page p) {
+ super.register(p);
+ p.addComponentStateParam(this, m_itemId);
+ p.addComponentStateParam(this, m_bundleId);
+ }
+
+ /**
+ * Get the creation component.
+ *
+ * @param kit
+ * @param type
+ * @return
+ */
+ protected Component instantiateKitComponent
+ (final AuthoringKit kit, final ContentType type) {
+ String creatorName = kit.getCreateComponent();
+ Object[] vals;
+
+ if(creatorName == null) {
+ return null;
+ }
+
+ try {
+ Class createClass = Class.forName(creatorName);
+ ItemSelectionModel itemModel = new ItemSelectionModel(type, m_itemId);
+ vals = new Object[]{itemModel, this};
+ Constructor constr = createClass.getConstructor(s_args);
+ Component c = (Component)constr.newInstance(vals);
+ return c;
+ } catch (Exception e) {
+ s_log.error("Instantiation failure", e);
+ throw new UncheckedWrapperException (
+ "Failed to instantiate creation component " +
+ kit.getCreateComponent() + ": " + e.getMessage(),
+ e);
+ }
+ }
+
+ /**
+ * Return the currently selected folder. Creation components will place
+ * new items in this folder.
+ *
+ * @param s represents the current request
+ * @return the currently selected folder, in which new items should be
+ * placed.
+ */
+ public final Folder getFolder(PageState s) {
+ return (Folder) m_folderSel.getSelectedObject(s);
+ }
+
+ /**
+ * Return the currently selected content section. New items created by
+ * creation components will belong to this section. This is the content
+ * section to which the folder returned by {@link #getFolder getFolder}
+ * belongs.
+ *
+ * @param s represents the current request
+ * @return the currently selected content section.
+ */
+ public final ContentSection getContentSection(PageState s) {
+ final ContentSection section = (ContentSection)
+ getFolder(s).getContentSection();
+
+ return section;
+ }
+
+ /**
+ * Forward to the item editing UI. The creation component of an authoring
+ * kit may call this method to indicate that the creation process is
+ * complete.
+ *
+ * @param s the page state
+ * @param item the newly created item
+ */
+ public void editItem(PageState s, ContentItem item) {
+ ContentSection sec = getContentSection(s);
+
+ String nodeURL = URL.getDispatcherPath() + sec.getPath() + "/";
+ String target = ContentItemPage.getItemURL
+ (nodeURL, item.getID(), ContentItemPage.AUTHORING_TAB,true);
+
+ throw new RedirectSignal(target, true);
+ }
+
+ /**
+ * Cancel item editing and go back to where the user came from
+ *
+ * @param s the page state
+ */
+ public void redirectBack(PageState state) {
+ m_typeSel.clearSelection(state);
+ }
+
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/category/CategoryAdminPane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/category/CategoryAdminPane.java.off
new file mode 100755
index 000000000..01ef79e25
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/category/CategoryAdminPane.java.off
@@ -0,0 +1,334 @@
+/*
+ * 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.category;
+
+import com.arsdigita.bebop.*;
+import com.arsdigita.bebop.event.*;
+import com.arsdigita.bebop.parameters.ParameterModel;
+import com.arsdigita.bebop.parameters.StringParameter;
+import com.arsdigita.categorization.CategorizedCollection;
+import com.arsdigita.categorization.Category;
+import com.arsdigita.categorization.CategoryCollection;
+import com.arsdigita.cms.CMS;
+import com.arsdigita.cms.SecurityManager;
+import com.arsdigita.cms.ui.BaseAdminPane;
+import com.arsdigita.cms.ui.BaseDeleteForm;
+import com.arsdigita.cms.ui.BaseTree;
+import com.arsdigita.cms.ui.VisibilityComponent;
+import com.arsdigita.kernel.Kernel;
+import com.arsdigita.kernel.permissions.PermissionDescriptor;
+import com.arsdigita.kernel.permissions.PermissionService;
+import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
+import com.arsdigita.toolbox.ui.ActionGroup;
+import com.arsdigita.toolbox.ui.Section;
+import com.arsdigita.xml.Element;
+import java.math.BigDecimal;
+import org.apache.log4j.Logger;
+
+/**
+ * A split pane for the Category Administration UI.
+ *
+ * @author Justin Ross <jross@redhat.com>
+ * @version $Id: CategoryAdminPane.java 2090 2010-04-17 08:04:14Z pboy $
+ */
+public final class CategoryAdminPane extends BaseAdminPane {
+
+ public static final String CONTEXT_SELECTED = "sel_context";
+ private static final String DEFAULT_USE_CONTEXT =
+ CategoryUseContextModelBuilder.DEFAULT_USE_CONTEXT;
+ private static final Logger s_log = Logger.getLogger(CategoryAdminPane.class);
+ private final SingleSelectionModel m_contextModel;
+ private final Tree m_categoryTree;
+ private final SingleSelectionModel m_model;
+ private final CategoryRequestLocal m_parent;
+ private final CategoryRequestLocal m_category;
+
+ public CategoryAdminPane() {
+ super();
+
+ m_contextModel = new UseContextSelectionModel(new StringParameter(CONTEXT_SELECTED));
+
+ /* Left column */
+ /* Use context section */
+ List list = new List(new CategoryUseContextModelBuilder());
+ list.setSelectionModel(m_contextModel);
+ list.addChangeListener(new ContextSelectionListener());
+
+ /* Category tree section */
+ m_categoryTree = new BaseTree(new CategoryTreeModelBuilder(m_contextModel));
+ m_categoryTree.addChangeListener(new SelectionListener());
+ m_model = m_categoryTree.getSelectionModel();
+
+ setSelectionModel(m_model);
+ setSelector(m_categoryTree);
+
+ /* setup use context form */
+ final Section contextSection = new Section();
+ contextSection.setHeading(new Label(gz("cms.ui.category.use_contexts")));
+ ActionGroup contextGroup = new ActionGroup();
+ contextSection.setBody(contextGroup);
+ contextGroup.setSubject(list);
+
+ if (CMS.getConfig().getAllowCategoryCreateUseContext()) {
+ ActionLink addContextAction = new ActionLink(new Label(gz(
+ "cms.ui.category.add_use_context")));
+ Form addContextForm = new AddUseContextForm(m_contextModel);
+ getBody().add(addContextForm);
+ getBody().connect(addContextAction, addContextForm);
+ contextGroup.addAction(new VisibilityComponent(addContextAction,
+ SecurityManager.CATEGORY_ADMIN));
+ }
+
+ final Section categorySection = new Section();
+ categorySection.setHeading(new Label(gz("cms.ui.categories")));
+ ActionGroup categoryGroup = new ActionGroup();
+ categorySection.setBody(categoryGroup);
+ categoryGroup.setSubject(m_categoryTree);
+
+ final SimpleContainer leftContainer = new SimpleContainer();
+ leftContainer.add(contextSection);
+ leftContainer.add(categorySection);
+ setLeft(leftContainer);
+
+ m_parent = new ParentRequestLocal();
+ m_category = new SelectionRequestLocal();
+
+ setAdd(gz("cms.ui.category.add"),
+ new CategoryAddForm(m_category, m_model));
+
+ setEdit(gz("cms.ui.category.edit"),
+ new CategoryEditForm(m_parent, m_category));
+
+ setDelete(new DeleteLink(new Label(gz("cms.ui.category.delete"))), new DeleteForm(
+ new SimpleContainer()));
+
+ setIntroPane(new Label(gz("cms.ui.category.intro")));
+ setItemPane(new CategoryItemPane(m_model,
+ m_contextModel,
+ m_category,
+ getAddLink(),
+ getEditLink(),
+ getDeleteLink()));
+
+ //m_contextList = new List(new ContextListModelBuilder());
+ //m_contextList.adChangeListener(new ContextListSelectionListener());
+ //m_contextModel = m_contextList.getSelectionModel();
+
+ }
+
+ @Override
+ public void register(final Page page) {
+ super.register(page);
+
+ page.addActionListener(new RootListener());
+ }
+
+ private final class DeleteLink extends ActionLink {
+
+ private final Label m_alternativeLabel;
+
+ DeleteLink(Label label) {
+ super(label);
+ m_alternativeLabel = new Label(gz("cms.ui.category.undeletable"));
+ }
+
+ @Override
+ public void generateXML(PageState state, Element parent) {
+ if (!isVisible(state)) {
+ return;
+ }
+
+ Category cat = m_category.getCategory(state);
+ String context = getUseContext(state);
+ boolean isDefaultContext =
+ (context == null) || DEFAULT_USE_CONTEXT.equals(context);
+
+ if (cat.isRoot() || !cat.getChildren().isEmpty()) {
+ m_alternativeLabel.generateXML(state, parent);
+ } else {
+ super.generateXML(state, parent);
+ }
+ }
+
+ }
+
+ private final class DeleteForm extends BaseDeleteForm {
+
+ DeleteForm(SimpleContainer prompt) {
+ super(prompt);
+ prompt.add(new Label(gz("cms.ui.category.delete_prompt")));
+ Label catLabel = new Label();
+ catLabel.addPrintListener(new PrintListener() {
+ public void prepare(PrintEvent pe) {
+ Label label = (Label) pe.getTarget();
+ Category cat =
+ m_category.getCategory(pe.getPageState());
+ CategoryCollection descendants = cat.getDescendants();
+ final long nDescendants = descendants.size() - 1;
+ descendants.close();
+ CategorizedCollection descObjects =
+ cat.getDescendantObjects();
+ final long nDescObjects = descObjects.size();
+ descObjects.close();
+ StringBuffer sb = new StringBuffer(" ");
+ if (nDescendants > 0) {
+ sb.append("This category has ");
+ sb.append(nDescendants);
+ sb.append(" descendant category(ies). ");
+ }
+ if (nDescObjects > 0) {
+ sb.append("It has ").append(nDescObjects);
+ sb.append(" descendant object(s). ");
+ }
+ if (nDescendants > 0 || nDescObjects > 0) {
+ sb.append("Descendants will be orphaned, if this category is removed.");
+ }
+ label.setLabel(sb.toString());
+ }
+
+ });
+ prompt.add(catLabel);
+ }
+
+ public final void process(final FormSectionEvent e)
+ throws FormProcessException {
+ final PageState state = e.getPageState();
+ final Category category = m_category.getCategory(state);
+ if (category == null) {
+ return;
+ }
+
+ PermissionService.assertPermission(new PermissionDescriptor(PrivilegeDescriptor.DELETE,
+ category,
+ Kernel.getContext().
+ getParty()));
+
+ if (category.isRoot()) {
+ Category root =
+ Category.getRootForObject(CMS.getContext().getContentSection(),
+ getUseContext(state));
+ if (category.equals(root)) {
+ Category.clearRootForObject(CMS.getContext().getContentSection(),
+ getUseContext(state));
+ }
+ m_contextModel.setSelectedKey(state, DEFAULT_USE_CONTEXT);
+ } else {
+ Category parent = category.getDefaultParentCategory();
+ m_model.setSelectedKey(state, parent.getID());
+ }
+
+ category.deleteCategoryAndOrphan();
+ }
+
+ }
+
+ private final class SelectionRequestLocal extends CategoryRequestLocal {
+
+ @Override
+ protected final Object initialValue(final PageState state) {
+ final String id = m_model.getSelectedKey(state).toString();
+
+ if (id == null) {
+ return null;
+ } else {
+ return new Category(new BigDecimal(id));
+ }
+ }
+
+ }
+
+ private final class ParentRequestLocal extends CategoryRequestLocal {
+
+ @Override
+ protected final Object initialValue(final PageState state) {
+ return m_category.getCategory(state).getDefaultParentCategory();
+ }
+
+ }
+
+ private final class RootListener implements ActionListener {
+
+ public final void actionPerformed(final ActionEvent e) {
+ final PageState state = e.getPageState();
+
+ if (!m_model.isSelected(state)) {
+ final Category root =
+ Category.getRootForObject(CMS.getContext().getContentSection(),
+ getUseContext(state));
+ if (root != null) {
+ m_model.setSelectedKey(state, root.getID());
+ }
+ }
+ }
+
+ }
+
+ private class UseContextSelectionModel extends ParameterSingleSelectionModel {
+
+ public UseContextSelectionModel(ParameterModel m) {
+ super(m);
+ }
+
+ @Override
+ public Object getSelectedKey(PageState state) {
+ Object val = super.getSelectedKey(state);
+ if (val == null || ((String) val).length() == 0) {
+ val = DEFAULT_USE_CONTEXT;
+ state.setValue(getStateParameter(), val);
+ fireStateChanged(state);
+ }
+ return val;
+ }
+
+ }
+
+ public String getUseContext(PageState state) {
+ String selected = (String) m_contextModel.getSelectedKey(state);
+ return (DEFAULT_USE_CONTEXT).equals(selected) ? (String) null : selected;
+ }
+
+ public class ContextSelectionListener implements ChangeListener {
+
+ public final void stateChanged(final ChangeEvent e) {
+ s_log.debug("Selection state changed; I may change " + "the body's visible pane");
+
+ final PageState state = e.getPageState();
+
+ getBody().reset(state);
+
+ if (m_contextModel.isSelected(state)) {
+ final Category root =
+ Category.getRootForObject(CMS.getContext().getContentSection(),
+ getUseContext(state));
+
+ if (root != null) {
+ m_model.setSelectedKey(state, root.getID());
+ //m_categoryTree.reset(state);
+ }
+
+ }
+ if (m_model.isSelected(state)) {
+ s_log.debug("The selection model is selected; displaying " + "the item pane");
+
+ getBody().push(state, getItemPane());
+ }
+ }
+
+ }
+}
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
new file mode 100755
index 000000000..f63223b88
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/cse/ContentSoonExpiredPane.java.off
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2002-2005 Runtime Collective Ltd. 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.cse;
+
+import com.arsdigita.bebop.table.TableCellRenderer;
+import com.arsdigita.bebop.Label;
+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 com.arsdigita.cms.ui.ContentItemPage;
+import com.arsdigita.cms.util.GlobalizationUtil;
+import com.arsdigita.cms.util.SecurityConstants;
+import com.arsdigita.globalization.GlobalizedMessage;
+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.DataQuery;
+import com.arsdigita.persistence.Filter;
+import com.arsdigita.persistence.FilterFactory;
+import com.arsdigita.persistence.OID;
+import com.arsdigita.persistence.Session;
+import com.arsdigita.persistence.SessionManager;
+import com.arsdigita.toolbox.ui.DataQueryBuilder;
+import com.arsdigita.toolbox.ui.DataTable;
+import com.arsdigita.ui.admin.Admin;
+import com.arsdigita.web.Application;
+import com.arsdigita.web.Web;
+import com.arsdigita.xml.Element;
+import com.arsdigita.bebop.Table;
+import com.arsdigita.bebop.Component;
+
+import java.math.BigDecimal;
+import java.util.Calendar;
+import java.util.Iterator;
+
+import org.apache.log4j.Logger;
+
+/**
+ * A pane that contains details to soon to be expired content.
+ *
+ * @version $Id: ContentSoonExpiredPane.java 775 2005-09-12 14:54:17Z fabrice $
+ */
+public class ContentSoonExpiredPane extends SimpleContainer {
+
+ private static final Logger log = Logger.getLogger(ContentSoonExpiredPane.class);
+
+ private DataTable dataTable;
+
+ public ContentSoonExpiredPane() {
+ add(getDataTable());
+ }
+
+ public final void generateXML(final PageState state, final Element parent) {
+ if (!isVisible(state)) {
+ return;
+ }
+
+ SecurityManager sm = CMS.getContext().getSecurityManager();
+ User user = Web.getWebContext().getUser();
+
+ DataTable dt = getDataTable();
+ DataQuery dq = dt.getDataQuery(state);
+ dq.addFilter(getViewFilter(dq, user));
+
+ dt.generateXML(state, parent);
+
+ }
+
+ private static Filter getViewFilter(DataQuery query, User user) {
+ PrivilegeDescriptor privilege = new PrivilegeDescriptor(SecurityConstants.CMS_READ_ITEM);
+ FilterFactory ff = query.getFilterFactory();
+ OID partyOID = user.getOID();
+ return PermissionService.getFilterQuery(ff, "objectId", privilege, partyOID);
+ }
+
+ protected DataTable getDataTable() {
+ if (dataTable == null) {
+ dataTable = new DataTable(new ContentSoonExpiredQueryBuilder());
+ dataTable.addColumn(GlobalizationUtil.globalize("cms.ui.cse.authorName").localize()
+ .toString(),
+ "authorName", true);
+ dataTable.addColumn(GlobalizationUtil.globalize("cms.ui.cse.itemName").localize()
+ .toString(),
+ "objectId", true, new ItemTitleCellRender());
+ dataTable
+ .addColumn(GlobalizationUtil.globalize("cms.ui.cse.view").localize().toString(),
+ "objectId", false, new ItemViewLinkCellRender());
+ dataTable
+ .addColumn(GlobalizationUtil.globalize("cms.ui.cse.edit").localize().toString(),
+ "objectId", false, new ItemEditLinkCellRender());
+ dataTable.addColumn(GlobalizationUtil.globalize("cms.ui.cse.endDateTime").localize()
+ .toString(),
+ "endDateTime", true);
+
+ dataTable.setEmptyView(new Label(GlobalizationUtil.globalize("cms.ui.cse.none")));
+ }
+
+ return dataTable;
+ }
+
+ private static boolean hasSiteWideAdmin(User user) {
+ Application adminApp = Admin.getInstance();
+ if (adminApp == null) {
+ return false;
+ }
+
+ PermissionDescriptor admin = new PermissionDescriptor(PrivilegeDescriptor.ADMIN, adminApp,
+ user);
+ return PermissionService.checkPermission(admin);
+ }
+
+ private static GlobalizedMessage gz(final String key) {
+ return GlobalizationUtil.globalize(key);
+ }
+
+ private static String lz(final String key) {
+ return (String) gz(key).localize();
+ }
+
+ private class ContentSoonExpiredQueryBuilder implements DataQueryBuilder {
+
+ public String getKeyColumn() {
+ return "objectId";
+ }
+
+ public DataQuery makeDataQuery(DataTable t, PageState s) {
+ Session ses = SessionManager.getSession();
+ DataQuery query = ses.retrieveQuery(
+ "com.arsdigita.cms.getContentItemExpiredBeforeInSection");
+
+ int months = ContentSection.getConfig().getSoonExpiredMonths();
+ int days = ContentSection.getConfig().getSoonExpiredDays();
+
+ Calendar now = Calendar.getInstance();
+ now.add(Calendar.DAY_OF_YEAR, days);
+ now.add(Calendar.MONTH, months);
+ query.setParameter("endDateTime", now.getTime());
+
+ ContentSection section = CMS.getContext().getContentSection();
+ query.setParameter("sectionId", section.getID());
+
+ return query;
+ }
+
+ public void lock() {
+ }
+
+ public boolean isLocked() {
+ return false;
+ }
+
+ }
+
+ private class ItemTitleCellRender implements TableCellRenderer {
+
+ private ThreadLocal threadLocal;
+
+ public ItemTitleCellRender() {
+ threadLocal = new ThreadLocal() {
+
+ protected Object initialValue() {
+ return new Label("");
+ }
+
+ };
+ }
+
+ public Component getComponent(Table table, PageState state, Object value,
+ boolean isSelected, Object key,
+ int row, int column) {
+ BigDecimal id = (BigDecimal) key;
+ Label l = (Label) threadLocal.get();
+ l.setLabel(ContentSoonExpiredPane.getItemFromIdString(id.toString()).getDisplayName());
+ return l;
+ }
+
+ }
+
+ private class ItemEditLinkCellRender implements TableCellRenderer {
+
+ private ThreadLocal threadLocal;
+
+ public ItemEditLinkCellRender() {
+ threadLocal = new ThreadLocal() {
+
+ protected Object initialValue() {
+ return new Link(new Label(), "");
+ }
+
+ };
+ }
+
+ public Component getComponent(Table table, PageState state, Object value,
+ boolean isSelected, Object key,
+ int row, int column) {
+ boolean canEdit = false;
+ BigDecimal id = (BigDecimal) key;
+ User user = Web.getWebContext().getUser();
+ ContentItem ci = getItemFromIdString(id.toString());
+ Iterator permissions = PermissionService
+ .getImpliedPrivileges(ci.getOID(), user.getOID());
+ while (permissions.hasNext()) {
+ PrivilegeDescriptor permission = (PrivilegeDescriptor) permissions.next();
+ if (permission.equals(PrivilegeDescriptor.ADMIN) || permission.equals(
+ PrivilegeDescriptor.EDIT)) {
+ canEdit = true;
+ break;
+ }
+ }
+
+ if (!canEdit) {
+ return new Label("");
+ }
+
+ Link l = (Link) threadLocal.get();
+// l.setTarget(ContentItemPage.getRelativeItemURL(ContentSoonExpiredPane.getItemDraft(id.toString()), ContentItemPage.AUTHORING_TAB));
+ l.setTarget(ContentItemPage.getItemURL(ContentSoonExpiredPane.getItemFromIdString(id
+ .toString()), ContentItemPage.AUTHORING_TAB));
+ ((Label) l.getChild()).setLabel(GlobalizationUtil.globalize("cms.ui.cse.editLink"));
+
+ return l;
+ }
+
+ }
+
+ private class ItemViewLinkCellRender implements TableCellRenderer {
+
+ private ThreadLocal threadLocal;
+
+ public ItemViewLinkCellRender() {
+ threadLocal = new ThreadLocal() {
+
+ protected Object initialValue() {
+ return new Link(new Label(), "");
+ }
+
+ };
+ }
+
+ public Component getComponent(Table table, PageState state, Object value,
+ boolean isSelected, Object key,
+ int row, int column) {
+ BigDecimal id = (BigDecimal) key;
+ Link l = (Link) threadLocal.get();
+
+ ContentItem item = getItemFromIdString(id.toString());
+ String url = ".jsp";
+ while (item.getParent() != null) {
+ if (item.getParent() instanceof ContentItem) {
+ item = (ContentItem) item.getParent();
+ if (!"/".equals(item.getName())) {
+ url = "/" + item.getName() + url;
+ } else {
+ break;
+ }
+ }
+ }
+ ContentSection section = CMS.getContext().getContentSection();
+ l.setTarget("/" + section.getName() + url);
+
+ ((Label) l.getChild()).setLabel(GlobalizationUtil.globalize("cms.ui.cse.viewLink"));
+ return l;
+ }
+
+ }
+
+ private static ContentItem getItemFromIdString(String idString) {
+ return new ContentItem(new OID(ContentItem.class.getName(), Integer.parseInt(idString)));
+ }
+
+ private static BigDecimal getItemDraft(String idString) {
+ ContentItem item = getItemFromIdString(idString);
+ return item.getDraftVersion().getID();
+ }
+
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderAdminPane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderAdminPane.java.off
new file mode 100755
index 000000000..15d0e79f3
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderAdminPane.java.off
@@ -0,0 +1,129 @@
+/*
+ * 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.folder;
+
+import com.arsdigita.bebop.ActionLink;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.Page;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.SingleSelectionModel;
+import com.arsdigita.bebop.event.ActionEvent;
+import com.arsdigita.bebop.event.ActionListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.parameters.BigDecimalParameter;
+import com.arsdigita.cms.CMS;
+import com.arsdigita.cms.ContentSection;
+import com.arsdigita.cms.ui.BaseDeleteForm;
+import com.arsdigita.cms.util.GlobalizationUtil;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.toolbox.ui.SelectionPanel;
+import org.apache.log4j.Logger;
+
+import java.math.BigDecimal;
+
+/**
+ * A pane that contains a folder tree on the left and a folder
+ * manipulator on the right.
+ *
+ * @author Justin Ross <jross@redhat.com>
+ * @version $Id: FolderAdminPane.java 1942 2009-05-29 07:53:23Z terry $
+ */
+public class FolderAdminPane extends SelectionPanel {
+
+ private static final Logger s_log = Logger.getLogger
+ (FolderAdminPane.class);
+
+ private final FolderRequestLocal m_folder;
+
+ private final BigDecimalParameter m_param;
+
+ public static final String FOLDER_PARAMETER = "folder";
+
+ public FolderAdminPane() {
+ super(new Label(gz("cms.ui.folder.folders")),
+ new FolderTreeModelBuilder());
+
+ m_folder = new FolderRequestLocal(getSelectionModel());
+ m_param = new BigDecimalParameter(FOLDER_PARAMETER);
+
+ setAdd(new ActionLink(new Label(gz("cms.ui.folder.add"))),
+ new FolderAddForm(getSelectionModel(), m_folder));
+
+ setEdit(new ActionLink(new Label(gz("cms.ui.folder.edit"))),
+ new FolderEditForm(m_folder));
+
+ final BaseDeleteForm delete = new BaseDeleteForm
+ (new Label(gz("cms.ui.folder.delete_prompt"))) {
+ public final void process(final FormSectionEvent e)
+ throws FormProcessException {
+ final PageState state = e.getPageState();
+
+ m_folder.getFolder(state).delete();
+ getSelectionModel().clearSelection(state);
+ }
+ };
+
+ setDelete(new ActionLink(new Label(gz("cms.ui.folder.delete"))),
+ delete);
+
+ setIntroPane(new Label(gz("cms.ui.folder.intro")));
+ setItemPane(new Label("item XXX"));
+
+ addAction(getAddLink());
+ addAction(getEditLink());
+ addAction(getDeleteLink());
+ }
+
+ public void register(final Page page) {
+ super.register(page);
+
+ page.addGlobalStateParam(m_param);
+ page.addActionListener(new PreselectListener());
+ }
+
+ private class PreselectListener implements ActionListener {
+ public final void actionPerformed(final ActionEvent e) {
+ final PageState state = e.getPageState();
+ final SingleSelectionModel model = getSelectionModel();
+
+ if (!model.isSelected(state)) {
+ final BigDecimal value = (BigDecimal) state.getValue(m_param);
+
+ if (value == null) {
+ final ContentSection section =
+ CMS.getContext().getContentSection();
+
+ model.setSelectedKey
+ (state, section.getRootFolder().getID());
+ } else {
+ model.setSelectedKey(state, value);
+ }
+ }
+ }
+ }
+
+ private static GlobalizedMessage gz(final String key) {
+ return GlobalizationUtil.globalize(key);
+ }
+
+ private static String lz(final String key) {
+ return (String) gz(key).localize();
+ }
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderCreator.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderCreator.java.off
new file mode 100755
index 000000000..bfb1ad53b
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderCreator.java.off
@@ -0,0 +1,77 @@
+/*
+ * 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.folder;
+
+import com.arsdigita.bebop.FormData;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.cms.Folder;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.util.GlobalizationUtil;
+import com.arsdigita.db.Sequences;
+import com.arsdigita.domain.DataObjectNotFoundException;
+import com.arsdigita.persistence.OID;
+import com.arsdigita.persistence.SessionManager;
+import org.apache.log4j.Logger;
+
+import java.math.BigDecimal;
+
+public class FolderCreator extends FolderForm {
+
+ private static Logger s_log =
+ Logger.getLogger(FolderCreator.class.getName());
+
+
+ public FolderCreator(String name, FolderSelectionModel parent) {
+ super(name, parent);
+ }
+
+ public void init(FormSectionEvent e) throws FormProcessException {
+ PageState state = e.getPageState();
+ ItemSelectionModel m = getItemSelectionModel();
+
+ // Create a new item_id and set it as the key
+ try {
+ m.setSelectedKey(state, Sequences.getNextValue());
+ } catch (java.sql.SQLException ex) {
+ s_log.error("Error retrieving sequence.nextval", ex);
+ throw new FormProcessException(ex);
+ }
+ }
+
+
+ public void process(FormSectionEvent e) throws FormProcessException {
+ PageState s = e.getPageState();
+ FormData data = e.getFormData();
+ ItemSelectionModel m = getItemSelectionModel();
+ BigDecimal id = (BigDecimal) m.getSelectedKey(s);
+ Folder parent = getCurrentFolder(s);
+
+ Folder child = null;
+ try {
+ child = new Folder(id);
+ } catch (DataObjectNotFoundException ex) {
+ child = new Folder(SessionManager.getSession().create
+ (new OID(Folder.BASE_DATA_OBJECT_TYPE, id)));
+ }
+
+ updateFolder(child, parent, (String)data.get(NAME), (String)data.get(TITLE));
+ }
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderEditor.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderEditor.java.off
new file mode 100755
index 000000000..afdf6aea9
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderEditor.java.off
@@ -0,0 +1,64 @@
+/*
+ * 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.folder;
+
+import com.arsdigita.bebop.FormData;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.cms.Folder;
+
+
+/**
+ * Implements functionality for renaming a folder. Most code taken from FolderCreator. Need to refactor out base
+ * functionality of FolderEditor & Creator.
+ *
+ * @author Jon Orris (jorris@arsdigita.com)
+ *
+ * @version $Revision: #9 $ $DateTime: 2004/08/17 23:15:09 $
+ * @version $Id: FolderEditor.java 287 2005-02-22 00:29:02Z sskracic $
+ */
+
+public class FolderEditor extends FolderForm {
+
+ public FolderEditor(String name, FolderSelectionModel folder) {
+ super(name, folder);
+ }
+
+
+ /**
+ * Initialize the form with name & label of folder being edited.
+ */
+ public void init(FormSectionEvent e) throws FormProcessException {
+ PageState s = e.getPageState();
+ FormData data = e.getFormData();
+ Folder folder = getCurrentFolder(s);
+ data.put(NAME, folder.getName());
+ data.put(TITLE, folder.getLabel());
+ }
+
+
+ public void process(FormSectionEvent e) throws FormProcessException {
+ PageState s = e.getPageState();
+ FormData data = e.getFormData();
+ Folder folder = getCurrentFolder(s);
+
+ updateFolder(folder, (String)data.get(NAME), (String)data.get(TITLE));
+ }
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderManipulator.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderManipulator.java.off
new file mode 100755
index 000000000..896819431
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderManipulator.java.off
@@ -0,0 +1,1087 @@
+/*
+ * 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.folder;
+
+import com.arsdigita.bebop.ActionLink;
+import com.arsdigita.bebop.BoxPanel;
+import com.arsdigita.bebop.Component;
+import com.arsdigita.bebop.Container;
+import com.arsdigita.bebop.ControlLink;
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.FormData;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.GridPanel;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.Page;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.PaginationModelBuilder;
+import com.arsdigita.bebop.Paginator;
+import com.arsdigita.bebop.RequestLocal;
+import com.arsdigita.bebop.Resettable;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.SimpleContainer;
+import com.arsdigita.bebop.Table;
+import com.arsdigita.bebop.Tree;
+import com.arsdigita.bebop.event.ActionEvent;
+import com.arsdigita.bebop.event.ActionListener;
+import com.arsdigita.bebop.event.FormInitListener;
+import com.arsdigita.bebop.event.FormProcessListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.event.FormSubmissionListener;
+import com.arsdigita.bebop.event.FormValidationListener;
+import com.arsdigita.bebop.event.PrintEvent;
+import com.arsdigita.bebop.event.PrintListener;
+import com.arsdigita.bebop.form.CheckboxGroup;
+import com.arsdigita.bebop.form.FormErrorDisplay;
+import com.arsdigita.bebop.form.Option;
+import com.arsdigita.bebop.form.OptionGroup;
+import com.arsdigita.bebop.form.SingleSelect;
+import com.arsdigita.bebop.form.Submit;
+import com.arsdigita.bebop.form.TextField;
+import com.arsdigita.bebop.parameters.ArrayParameter;
+import com.arsdigita.bebop.parameters.BigDecimalParameter;
+import com.arsdigita.bebop.parameters.StringParameter;
+import com.arsdigita.bebop.table.TableCellRenderer;
+import com.arsdigita.bebop.table.TableColumn;
+import com.arsdigita.bebop.tree.TreeCellRenderer;
+import com.arsdigita.cms.CMS;
+import com.arsdigita.cms.CMSConfig;
+import com.arsdigita.cms.ContentBundle;
+import com.arsdigita.cms.ContentItem;
+import com.arsdigita.cms.ContentSection;
+import com.arsdigita.cms.ContentTypeLifecycleDefinition;
+import com.arsdigita.cms.Folder;
+import com.arsdigita.cms.ItemCollection;
+import com.arsdigita.cms.SecurityManager;
+import com.arsdigita.cms.lifecycle.LifecycleDefinition;
+import com.arsdigita.cms.ui.lifecycle.PublishLock;
+import com.arsdigita.cms.util.GlobalizationUtil;
+import com.arsdigita.domain.DataObjectNotFoundException;
+import com.arsdigita.domain.DomainObjectFactory;
+import com.arsdigita.kernel.ACSObject;
+import com.arsdigita.kernel.Party;
+import com.arsdigita.kernel.PartyCollection;
+import com.arsdigita.kernel.User;
+import com.arsdigita.notification.Notification;
+import com.arsdigita.persistence.CompoundFilter;
+import com.arsdigita.persistence.DataCollection;
+import com.arsdigita.persistence.Filter;
+import com.arsdigita.persistence.OID;
+import com.arsdigita.persistence.SessionManager;
+import com.arsdigita.toolbox.GlobalisationUtil;
+import com.arsdigita.toolbox.ui.ActionGroup;
+import com.arsdigita.util.Assert;
+import com.arsdigita.util.UncheckedWrapperException;
+import com.arsdigita.web.Web;
+import com.arsdigita.workflow.simple.TaskException;
+import com.arsdigita.workflow.simple.Workflow;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import org.apache.log4j.Logger;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Browse folders and manipulate them with various actions (move/copy/delete).
+ *
+ * @author David Lutterkort
+ * @version $Id: FolderManipulator.java 1940 2009-05-29 07:15:05Z terry $
+ */
+@SuppressWarnings("PMD.BeanMembersShouldSerialize")
+public class FolderManipulator extends SimpleContainer implements
+ //FormProcessListener,
+ //FormValidationListener,
+ //FormSubmissionListener,
+ Resettable {
+
+ //public static final String RESOURCE_BUNDLE = "com.arsdigita.cms.ui.folder.CMSFolderResources";
+ private final GlobalisationUtil globalizationUtil = new com.arsdigita.toolbox.GlobalisationUtil(
+ "com.arsdigita.cms.ui.folder.CMSFolderResources");
+ private static final Logger LOGGER = Logger.getLogger(FolderManipulator.class);
+ private static final String ATOZ_FILTER_PARAM = "aToZfilter";
+ private static final String ACTION_PARAM = "act";
+ private static final String FILTER_PARAM = "filter";
+
+ private static final String SOURCES_PARAM = "srcs";
+ private static final String MOVE = "Move";
+ private static final String COPY = "Copy";
+ //private static final String PUBLISH = "Publish";
+ //private static final String UNPUBLISH = "UnPublish";
+
+ private final ArrayParameter sourcesParam = new ArrayParameter(
+ new BigDecimalParameter(SOURCES_PARAM));
+ private final StringParameter actionParam = new StringParameter(ACTION_PARAM);
+ ;
+ /**
+ * The folder in which the source items live.
+ */
+ private final FolderSelectionModel sourceFolderModel;
+ private final ItemView itemView;
+ private final TargetSelector targetSelector = new TargetSelector();
+ //private final PublishDialog publishDialog = new PublishDialog();
+
+ private FilterForm filterForm;
+ private final StringParameter atozFilterParam = new StringParameter(ATOZ_FILTER_PARAM);
+ private final StringParameter filterParam = new StringParameter(FILTER_PARAM);
+
+ public FolderManipulator(final FolderSelectionModel folderModel) {
+
+ super();
+
+ sourceFolderModel = folderModel;
+ itemView = new ItemView();
+ itemView.addProcessListener(new ItemViewProcessListener());
+ itemView.addValidationListener(new ItemViewValidationListener());
+ add(itemView);
+
+ targetSelector.addProcessListener(new TargetSelectorProcessListener());
+ targetSelector.addValidationListener(new TargetSelectorValidationListener());
+ targetSelector.addSubmissionListener(new TargetSelectorSubmissionListener());
+ add(targetSelector);
+
+ //publishDialog.addProcessListener(new PublishDialogProcessListener());
+
+ }
+
+ @Override
+ public void register(final Page page) {
+
+ super.register(page);
+ page.setVisibleDefault(targetSelector, false);
+ page.setVisibleDefault(filterForm, true);
+ page.addComponentStateParam(this, sourcesParam);
+ page.addComponentStateParam(this, actionParam);
+ page.addComponentStateParam(this, atozFilterParam);
+ page.addComponentStateParam(this, filterParam);
+
+ }
+
+ public final BigDecimal[] getSources(final PageState state) {
+
+ final BigDecimal[] result = (BigDecimal[]) state.getValue(sourcesParam);
+
+ //Return empty array instead of null.
+ if (result == null) {
+ return new BigDecimal[0];
+ } else {
+ return result;
+ }
+ }
+
+ public final FolderSelectionModel getSourceFolderModel() {
+ return sourceFolderModel;
+ }
+
+ public final Folder getTarget(final PageState state) {
+ return targetSelector.getTarget(state);
+ }
+
+ protected final boolean isMove(final PageState state) {
+ return MOVE.equals(getAction(state));
+ }
+
+ protected final boolean isCopy(final PageState state) {
+ return COPY.equals(getAction(state));
+ }
+
+// protected final boolean isPublish(final PageState state) {
+// return PUBLISH.equals(getAction(state));
+// }
+//
+// protected final boolean isUnPublish(final PageState state) {
+// return UNPUBLISH.equals(getAction(state));
+// }
+
+ private String getAction(final PageState state) {
+ return (String) state.getValue(actionParam);
+ }
+
+ protected void moveItems(final Folder target, final BigDecimal[] itemIds) {
+
+ for (BigDecimal itemId : itemIds) {
+ try {
+ changeItemParent(itemId, target);
+ } catch (DataObjectNotFoundException e) {
+ LOGGER.warn("object not found in content move", e);
+ throw new IllegalStateException(String.format("Item '%s' to move not found.",
+ itemId.toString()));
+
+ }
+ }
+
+ }
+
+ private void changeItemParent(final BigDecimal itemId, final Folder newParent)
+ throws DataObjectNotFoundException {
+
+ final ContentItem item = new ContentItem(itemId);
+ item.setParent(newParent);
+ item.save();
+
+ }
+
+ protected void copyItems(final Folder target,
+ final BigDecimal[] itemIds) {
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Copying items " + Arrays.asList(itemIds) + " to " + target);
+ }
+ for (BigDecimal itemId : itemIds) {
+
+// ContentItem source = (ContentItem) DomainObjectFactory.newInstance(
+// new OID(ContentItem.BASE_DATA_OBJECT_TYPE, itemId));
+// Assert.exists(source, ContentItem.class);
+//
+// final ACSObject parent = source.getParent();
+// if (parent instanceof ContentBundle) {
+// source = (ContentBundle) parent;
+// }
+//
+// if (LOGGER.isDebugEnabled()) {
+// LOGGER.debug("Copying item " + source);
+// }
+ final ContentItem source = retrieveSourceItem(itemId);
+
+ final ContentItem newItem = source.copy(target, true);
+ Assert.isEqual(target, newItem.getParent());
+
+ }
+ }
+
+// protected void publishItems(final BigDecimal[] itemIds) {
+//
+// if (LOGGER.isDebugEnabled()) {
+// LOGGER.debug("(Re-)Publishing items " + Arrays.asList(itemIds));
+// }
+//
+// for (BigDecimal itemId : itemIds) {
+//
+// final ContentItem item = retrieveSourceItem(itemId);
+//
+// if (item.isLive()) {
+// //Republish
+// //Ensure that we have the draft version
+// //final ContentItem draftItem = item.getDraftVersion();
+// republish(itemId);
+// } else {
+// publish(itemId);
+// }
+//
+// final LifecycleDefinition lifecycleDef = ContentTypeLifecycleDefinition
+// .getLifecycleDefinition(item.getContentSection(), item.getContentType());
+//
+// }
+// }
+
+// private void publish(final BigDecimal itemId) {
+//
+// }
+//
+// private void republish(final BigDecimal itemId) {
+//
+// final User user = Web.getWebContext().getUser();
+//
+// final Thread thread = new Thread(new Runnable() {
+//
+// @Override
+// public void run() {
+// final ContentItem item = retrieveSourceItem(itemId);
+//
+// PublishLock.getInstance().lock(item);
+// item.republish(false);
+// Workflow workflow = Workflow.getObjectWorkflow(item);
+// ItemLifecycleSelectForm.finish(workflow, item, user);
+// PublishLock.getInstance().unlock(item);
+// }
+//
+// });
+// thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+//
+// @Override
+// public void uncaughtException(final Thread thread,
+// final Throwable ex) {
+// final StringWriter strWriter = new StringWriter();
+// final PrintWriter writer = new PrintWriter(strWriter);
+// ex.printStackTrace(writer);
+// final ContentItem item = retrieveSourceItem(itemId);
+//
+// PublishLock.getInstance().setError(item, strWriter.toString());
+// LOGGER.error(String.format(
+// "An error occurred while "
+// + "publishing the item '%s': ",
+// item.getOID().toString()),
+// ex);
+//
+// if ((CMSConfig.getInstanceOf().
+// getPublicationFailureSender()
+// == null)
+// && (CMSConfig.getInstanceOf().
+// getPublicationFailureReceiver() == null)) {
+// return;
+// }
+//
+// final PartyCollection receiverParties = Party.retrieveAllParties();
+// Party receiver = null;
+// receiverParties.addEqualsFilter("primaryEmail",
+// CMSConfig.getInstanceOf().
+// getPublicationFailureReceiver());
+// if (receiverParties.next()) {
+// receiver = receiverParties.getParty();
+// }
+// receiverParties.close();
+//
+// final PartyCollection senderParties = Party.retrieveAllParties();
+// Party sender = null;
+// senderParties.addEqualsFilter("primaryEmail",
+// CMSConfig.getInstanceOf().
+// getPublicationFailureReceiver());
+// if (senderParties.next()) {
+// sender = senderParties.getParty();
+// }
+// senderParties.close();
+//
+// if ((sender != null) && (receiver != null)) {
+// final Writer traceWriter = new StringWriter();
+// final PrintWriter printWriter = new PrintWriter(
+// traceWriter);
+// ex.printStackTrace(printWriter);
+//
+// final Notification notification = new Notification(
+// sender,
+// receiver,
+// String.format(
+// "Failed to publish item '%s'",
+// item.getOID().toString()),
+// String.format("Publishing item '%s' failed "
+// + "with error message: %s.\n\n"
+// + "Stacktrace:\n%s",
+// item.getOID().toString(),
+// ex.getMessage(),
+// traceWriter.toString()));
+// notification.save();
+// }
+// }
+//
+// });
+//
+// thread.start();
+// }
+
+ private ContentItem retrieveSourceItem(final BigDecimal itemToCopyId) {
+
+ ContentItem source = (ContentItem) DomainObjectFactory.newInstance(
+ new OID(ContentItem.BASE_DATA_OBJECT_TYPE, itemToCopyId));
+ Assert.exists(source, ContentItem.class);
+
+ final ACSObject parent = source.getParent();
+ if (parent instanceof ContentBundle) {
+ source = (ContentBundle) parent;
+ }
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Copying item " + source);
+ }
+
+ return source;
+ }
+
+ /**
+ * Returns the form that contains the folder browser and the move/copy dropdown.
+ *
+ * @return The form containing the folder browser and dropdown menu
+ */
+ public final Form getItemView() {
+ return itemView;
+ }
+
+ /**
+ * Returns the form to choose the target folder for move/copy
+ *
+ * @return
+ */
+ public final Form getTargetSelector() {
+ return targetSelector;
+ }
+
+ /**
+ * Return the browser contained in the ItemView form
+ *
+ * @return
+ */
+ public final FolderBrowser getBrowser() {
+ return itemView.getBrowser();
+ }
+
+ private class ItemViewProcessListener implements FormProcessListener {
+
+ public ItemViewProcessListener() {
+ //Nothing
+ }
+
+ @Override
+ public void process(final FormSectionEvent event) throws FormProcessException {
+ final PageState state = event.getPageState();
+
+ itemView.setVisible(state, false);
+ targetSelector.setVisible(state, true);
+ targetSelector.expose(state);
+ }
+
+ }
+
+ private class TargetSelectorProcessListener implements FormProcessListener {
+
+ public TargetSelectorProcessListener() {
+ //Nothing
+ }
+
+ @Override
+ public void process(final FormSectionEvent event) throws FormProcessException {
+
+ final PageState state = event.getPageState();
+
+ itemView.setVisible(state, true);
+ targetSelector.setVisible(state, false);
+
+ final Folder folder = targetSelector.getTarget(state);
+ final BigDecimal[] itemIds = getSources(state);
+
+ if (isCopy(state)) {
+ copyItems(folder, itemIds);
+ } else if (isMove(state)) {
+ moveItems(folder, itemIds);
+ }
+
+ reset(state);
+
+ }
+
+ }
+
+// private class PublishDialogProcessListener implements FormProcessListener {
+//
+// public PublishDialogProcessListener() {
+// //Nothing
+// }
+//
+// @Override
+// public void process(final FormSectionEvent event) throws FormProcessException {
+//
+// final PageState state = event.getPageState();
+//
+// itemView.setVisible(state, true);
+// publishDialog.setVisible(state, false);
+//
+// final BigDecimal[] itemIds = getSources(state);
+//
+// if (isPublish(state)) {
+// publishItems(itemIds);
+// } else if (isUnPublish(state)) {
+// unpublishItems(itemIds);
+// }
+//
+// reset(state);
+// }
+//
+// }
+
+ private class ItemViewValidationListener implements FormValidationListener {
+
+ public ItemViewValidationListener() {
+ //Nothing
+ }
+
+ @Override
+ public void validate(final FormSectionEvent event) throws FormProcessException {
+
+ final PageState state = event.getPageState();
+ final FormData data = event.getFormData();
+
+ if (getSources(state).length <= 0) {
+ data.addError(globalizationUtil.globalize("cms.ui.folder.must_select_item"));
+ }
+ }
+
+ }
+
+ private class TargetSelectorValidationListener implements FormValidationListener {
+
+ public TargetSelectorValidationListener() {
+ //Nothing
+ }
+
+ @Override
+ public void validate(final FormSectionEvent event) throws FormProcessException {
+
+ final PageState state = event.getPageState();
+
+ if (getSources(state).length <= 0) {
+ throw new IllegalStateException("No source items specified");
+ }
+
+ final Folder target = targetSelector.getTarget(state);
+ final FormData data = event.getFormData();
+ if (target == null) {
+ data.addError(globalizationUtil.globalize(
+ "cms.ui.folder.need_select_target_folder"));
+ //If the target is null, we can skip the rest of the checks
+ return;
+ }
+
+ if (target.equals(sourceFolderModel.getSelectedObject(state))) {
+ data.addError(globalizationUtil.globalize("cms.ui.folder.not_within_same_folder"));
+ }
+
+ // check create item permission
+ final User user = Web.getWebContext().getUser();
+ final SecurityManager securityManager = CMS.getSecurityManager(state);
+ if (!securityManager.canAccess(user, SecurityManager.NEW_ITEM, target)) {
+ data.addError(globalizationUtil.globalize("cms.ui.folder.no_permission_for_item"));
+ }
+
+ for (BigDecimal source : getSources(state)) {
+ try {
+ validateItem(source, target, state, data);
+ } catch (DataObjectNotFoundException ex) {
+ LOGGER.warn("Object not found in validation", ex);
+ throw new IllegalStateException(String.format(
+ "There is no item with the id '%s'", source.toString()));
+ }
+ }
+
+ }
+
+ private void validateItem(final BigDecimal itemId,
+ final Folder target,
+ final PageState state,
+ final FormData data) {
+
+ final ContentItem item = new ContentItem(itemId);
+ final String name = item.getName();
+
+ final ItemCollection items = target.getItems();
+ items.addNameFilter(name);
+ if (items.next()) {
+ // there is an item in the target folder that already has this name
+ addErrorMessage(data, "cms.ui.folder.item_already_exists", name);
+ }
+ items.close();
+
+ if (item.isLive() && isMove(state)) {
+ addErrorMessage(data, "cms.ui.folder.item_is_live", name);
+ }
+
+ final SecurityManager securityManager = CMS.getSecurityManager(state);
+ final User user = Web.getWebContext().getUser();
+ if ((!securityManager.canAccess(user, SecurityManager.DELETE_ITEM, item))
+ && isMove(state)) {
+ addErrorMessage(data, "cms.ui.folder.no_permission_for_item", name);
+ }
+ }
+
+ }
+
+ private void addErrorMessage(final FormData data, final String message, final String itemName) {
+ data.addError(globalizationUtil.globalize(message, new Object[]{itemName}));
+ }
+
+// @Override
+// public void submitted(final FormSectionEvent event) throws FormProcessException {
+//
+// final PageState state = event.getPageState();
+//
+// if (targetSelector.isCancelled(state)) {
+// reset(state);
+// throw new FormProcessException("cms.ui.folder.cancelled");
+//
+// }
+// }
+ private class TargetSelectorSubmissionListener implements FormSubmissionListener {
+
+ public TargetSelectorSubmissionListener() {
+ //Nothing
+ }
+
+ @Override
+ public void submitted(final FormSectionEvent event) throws FormProcessException {
+
+ final PageState state = event.getPageState();
+
+ if (targetSelector.isCancelled(state)) {
+ reset(state);
+ throw new FormProcessException(GlobalizationUtil.globalize("cms.ui.folder.cancelled"));
+ }
+
+ }
+
+ }
+
+ @Override
+ public void reset(final PageState state) {
+
+ itemView.setVisible(state, true);
+ itemView.reset(state);
+ targetSelector.setVisible(state, false);
+ targetSelector.reset(state);
+ //publishDialog.setVisible(state, false);
+ state.setValue(actionParam, null);
+ state.setValue(sourcesParam, null);
+ //s.setValue(m_aToZfilter, null);
+ state.setValue(filterParam, null);
+
+ }
+
+ // The form containing the tree to select the target folder from
+ private class TargetSelector extends Form implements Resettable {
+
+ private final FolderSelectionModel targetModel;
+ private final FolderTree folderTree;
+ private final Submit cancelButton;
+
+ public TargetSelector() {
+ super("targetSel", new BoxPanel());
+ setMethod(GET);
+ targetModel = new FolderSelectionModel("target");
+ folderTree = new FolderTree(targetModel);
+ folderTree.setCellRenderer(new FolderTreeCellRenderer());
+
+ final Label label = new Label(new PrintListener() {
+
+ @Override
+ public void prepare(final PrintEvent event) {
+ final PageState state = event.getPageState();
+ final Label label = (Label) event.getTarget();
+ final int numberOfItems = getSources(state).length;
+ final Folder folder = (Folder) sourceFolderModel.getSelectedObject(state);
+ if (isMove(state)) {
+ label.setLabel(globalizationUtil.globalize(
+ "cms.ui.folder.move", new Object[]{numberOfItems,
+ folder.getPathNoJsp()}));
+ } else if (isCopy(state)) {
+ label.setLabel(globalizationUtil.globalize(
+ "cms.ui.folder.copy", new Object[]{numberOfItems,
+ folder.getPathNoJsp()}));
+ }
+ }
+
+ });
+
+ label.setOutputEscaping(false);
+ add(label);
+ add(folderTree);
+ add(new FormErrorDisplay(this));
+ final SaveCancelSection saveCancelSection = new SaveCancelSection();
+ cancelButton = saveCancelSection.getCancelButton();
+ add(saveCancelSection);
+ }
+
+ @Override
+ public void register(final Page page) {
+ super.register(page);
+ page.addComponentStateParam(this, targetModel.getStateParameter());
+ }
+
+ // Set things up the first time the selector gets visible
+ public void expose(final PageState state) {
+ final Folder folder = (Folder) sourceFolderModel.getSelectedObject(state);
+ targetModel.clearSelection(state);
+ if (folder != null) {
+ final ItemCollection items = folder.getPathInfo(true);
+ while (items.next()) {
+ folderTree.expand(items.getID().toString(), state);
+ }
+ items.close();
+ }
+ }
+
+ @Override
+ public void reset(final PageState state) {
+ folderTree.clearSelection(state);
+ // FIXME: add a reset method to Tree and call that instead of this
+ // hack
+ state.setValue(folderTree.getSelectionModel().getStateParameter(), null);
+ }
+
+ public Folder getTarget(final PageState state) {
+ return (Folder) targetModel.getSelectedObject(state);
+ }
+
+ public boolean isCancelled(final PageState state) {
+ return cancelButton.isSelected(state);
+ }
+
+ }
+
+ //The form which is show for the publish and unpublish action
+// private class PublishDialog extends Form {
+//
+// public PublishDialog() {
+// super("PublishDialog", new BoxPanel());
+//
+// final Label label = new Label(new PrintListener() {
+//
+// @Override
+// public void prepare(final PrintEvent event) {
+//
+// final PageState state = event.getPageState();
+// final Label target = (Label) event.getTarget();
+// final int numberOfItems = getSources(state).length;
+// final Folder folder = (Folder) sourceFolderModel.getSelectedObject(state);
+//
+// if (isPublish(state)) {
+// target.setLabel(globalizationUtil.globalize(
+// "cms.ui.folder.publish",
+// new Object[]{numberOfItems,
+// folder.getPathNoJsp()}));
+// } else if (isUnPublish(state)) {
+// target.setLabel(globalizationUtil.globalize(
+// "cms.ui.folder.publish",
+// new Object[]{numberOfItems,
+// folder.getPathNoJsp()}));
+// }
+// }
+//
+// });
+//
+// label.setOutputEscaping(false);
+// add(label);
+// add(new FormErrorDisplay(this));
+// add(new SaveCancelSection());
+// }
+//
+// }
+
+ // The form containing the browser and the drop down for selecting an
+ // action
+ private class ItemView extends Form implements Resettable {
+
+ private static final String ITEM_VIEW = "itemView";
+
+ private final FolderBrowser folderBrowser;
+ private final Paginator paginator;
+ private final OptionGroup checkboxGroup;
+ private final SingleSelect actionSelect;
+ private final Submit submit;
+
+ public ItemView() {
+
+ super(ITEM_VIEW, new SimpleContainer());
+ setMethod(GET);
+
+ final ActionGroup group = new ActionGroup();
+ add(group);
+
+ final GridPanel panel = new GridPanel(1);
+ group.setSubject(panel);
+
+ folderBrowser = new FolderBrowser(sourceFolderModel);
+ folderBrowser.setAtoZfilterParameter(atozFilterParam);
+ folderBrowser.setFilterParameter(filterParam);
+ folderBrowser.setFilterForm(filterForm);
+ paginator = new Paginator((PaginationModelBuilder) folderBrowser.getModelBuilder(),
+ ContentSection.getConfig().getFolderBrowseListSize());
+ panel.add(paginator);
+ panel.add(folderBrowser);
+
+ LOGGER.debug("Adding filter form...");
+ filterForm = new FilterForm((FilterFormModelBuilder) folderBrowser.getModelBuilder());
+ FolderManipulator.this.add(filterForm);
+
+ checkboxGroup = new CheckboxGroup(sourcesParam);
+ panel.add(checkboxGroup);
+
+ panel.add(new FormErrorDisplay(this));
+
+ final Container container = new SimpleContainer();
+ group.addAction(container);
+
+ container.add(new Label(globalizationUtil.globalize("cms.ui.folder.edit_selection")));
+ actionSelect = new SingleSelect(actionParam);
+ actionSelect.addOption(new Option(COPY,
+ new Label(globalizationUtil.globalize(
+ "cms.ui.folder.copy.action"))));
+ actionSelect.addOption(new Option(MOVE,
+ new Label(globalizationUtil.globalize(
+ "cms.ui.folder.move.action"))));
+ //Publishing in the folder browser only works if threaded publishing is active
+// if (CMSConfig.getInstanceOf().getThreadedPublishing()) {
+// actionSelect.addOption(new Option(PUBLISH,
+// new Label(globalizationUtil.globalize(
+// "cms.ui.folder.publish.action"))));
+// actionSelect.addOption(new Option(UNPUBLISH,
+// new Label(globalizationUtil.globalize(
+// "cms.ui.folder.unpublish.action"))));
+// }
+ container.add(actionSelect);
+ submit = new Submit("Go", globalizationUtil.globalize("cms.ui.folder.go"));
+ container.add(submit);
+
+ // Add a new first column to the table
+ final TableColumn column = new TableColumn();
+ column.setCellRenderer(new CheckboxRenderer());
+ folderBrowser.getColumnModel().add(0, column);
+ }
+
+ public final FolderBrowser getBrowser() {
+ return folderBrowser;
+ }
+
+ @Override
+ public void reset(final PageState state) {
+
+ checkboxGroup.setValue(state, null);
+ actionSelect.setValue(state, null);
+ paginator.reset(state);
+ //state.setValue(m_aToZfilter, null);
+ state.setValue(filterParam, null);
+ filterForm.getFilterField().setValue(state, null);
+ }
+
+ // The renderer for the first column in the itemView table
+ private class CheckboxRenderer implements TableCellRenderer {
+
+ public CheckboxRenderer() {
+ //Nothing to do
+ }
+
+ @Override
+ public Component getComponent(final Table table,
+ final PageState state,
+ final Object value,
+ final boolean isSelected,
+ final Object key,
+ final int row,
+ final int column) {
+ final BigDecimal n = (BigDecimal) key;
+ Option result = new Option(sourcesParam.marshalElement(n.abs()), "");
+ result.setGroup(checkboxGroup);
+ return result;
+ }
+
+ }
+
+ }
+
+ protected class FilterForm extends Form implements FormProcessListener,
+ FormInitListener,
+ FormSubmissionListener {
+
+ private final SimpleContainer panel;
+ private boolean visible;
+ private final FilterFormModelBuilder modelBuilder;
+ private final TextField filterField;
+
+ public FilterForm(final FilterFormModelBuilder modelBuilder) {
+ super("folderFilterForm");
+
+ LOGGER.debug("Creating filter form...");
+
+ this.modelBuilder = modelBuilder;
+
+ addProcessListener(this);
+ addInitListener(this);
+ addSubmissionListener(this);
+
+ panel = new BoxPanel(BoxPanel.HORIZONTAL);
+
+ final ActionLink allLink = new ActionLink(
+ globalizationUtil.globalize("cms.ui.folder.filter.all"));
+ allLink.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(final ActionEvent event) {
+ //event.getPageState().setValue(m_aToZfilter, "");
+ event.getPageState().setValue(filterParam, "");
+ }
+
+ });
+ panel.add(allLink);
+
+// for (char c = 'A'; c <= 'Z'; c++) {
+// final char lowerCaseChar = Character.toLowerCase(c);
+// final ActionLink link = new ActionLink(Character.toString(c));
+// link.addActionListener(new ActionListener() {
+//
+// @Override
+// public void actionPerformed(final ActionEvent event) {
+// event.getPageState().setValue(m_aToZfilter,
+// Character.toString(lowerCaseChar));
+// }
+// });
+// panel.add(link);
+// }
+ panel.add(new Label(globalizationUtil.globalize("cms.ui.folder.filter")));
+ filterField = new TextField(filterParam);
+ panel.add(filterField);
+ panel.add(new Submit("filterFolderSubmit",
+ globalizationUtil.globalize("cms.ui.folder.filter_do")));
+
+ add(panel);
+
+ }
+
+ public TextField getFilterField() {
+ return filterField;
+ }
+
+ @Override
+ public void process(final FormSectionEvent event) throws FormProcessException {
+ //Nothing
+ }
+
+ @Override
+ public void init(final FormSectionEvent event) throws FormProcessException {
+ //fse.getPageState().setValue(FolderManipulator.this.m_filter, null);
+ //filterField.setValue(fse.getPageState(), null);
+ }
+
+ @Override
+ public void submitted(final FormSectionEvent event) throws FormProcessException {
+ }
+
+ @Override
+ public boolean isVisible(PageState state) {
+ if (super.isVisible(state)
+ && (modelBuilder.getFolderSize(state)
+ >= CMSConfig.getInstanceOf().getFolderAtoZShowLimit())) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ }
+
+ protected interface FilterFormModelBuilder {
+
+ public long getFolderSize(PageState state);
+
+ }
+
+ /**
+ * Getting the GlobalizedMessage using a CMS Class targetBundle.
+ *
+ * @param key The resource key. May not null.
+ *
+ * @return The globalized message
+ */
+// public static GlobalizedMessage globalize(final String key) {
+// return new GlobalizedMessage(key, RESOURCE_BUNDLE);
+// }
+//
+// public static GlobalizedMessage globalize(final String key, final Object[] args) {
+// return new GlobalizedMessage(key, RESOURCE_BUNDLE, args);
+// }
+ private class FolderTreeCellRenderer implements TreeCellRenderer {
+
+ private RequestLocal m_invalidFolders = new RequestLocal();
+
+ /**
+ * Render the folders appropriately. The selected folder is a bold label. Invalid folders
+ * are plain labels. Unselected, valid folders are control links. Invalid folders are: the
+ * parent folder of the sources, any of the sources, and any subfolders of the sources.
+ */
+ @Override
+ public Component getComponent(final Tree tree,
+ final PageState state,
+ final Object value,
+ final boolean isSelected,
+ final boolean isExpanded,
+ final boolean isLeaf,
+ final Object key) {
+
+ // Get the list of invalid folders once per request.
+ ArrayList invalidFolders = (ArrayList) m_invalidFolders.get(state);
+
+ if (invalidFolders == null) {
+ // The list of invalid folders has not been set for this
+ // request. Setting now.
+ invalidFolders = new ArrayList();
+
+ final DataCollection collection = SessionManager.getSession().retrieve(
+ ContentItem.BASE_DATA_OBJECT_TYPE);
+ CompoundFilter filter = collection.getFilterFactory().or();
+ // The sources themselves are not valid.
+ final BigDecimal[] sources = getSources(state);
+
+ for (int i = 0; i < sources.length; i++) {
+ invalidFolders.add(sources[i].toString());
+
+ final Filter temp = filter.addFilter("id = :id" + i);
+ temp.set("id" + i, sources[i]);
+ }
+ collection.addFilter(filter);
+
+ final DataCollection folders = SessionManager.getSession().retrieve(
+ Folder.BASE_DATA_OBJECT_TYPE);
+ folders.addEqualsFilter(Folder.IS_DELETED, Boolean.FALSE);
+
+ filter = collection.getFilterFactory().or();
+ int count = 0;
+ while (collection.next()) {
+ filter.addFilter(Folder.ANCESTORS + " like :ancestors"
+ + count + " || '%'");
+ filter.set("ancestors" + count,
+ collection.get(ContentItem.ANCESTORS));
+ count++;
+ }
+ folders.addFilter(filter);
+
+ while (folders.next()) {
+ invalidFolders.add(folders.get(Folder.ID).toString());
+ }
+
+ // Get all subfolders of the sources. These are also not valid.
+ /*
+ DataQuery dq = SessionManager.getSession().retrieveQuery("com.arsdigita.cms.FoldersAndAllSubFolders");
+ dq.setParameter("item_list", invalidFolders);
+
+ while (dq.next()) {
+ invalidFolders.add (dq.get("folder_id").toString());
+ }
+ */
+ // The folder from which the sources are being moved/copied is
+ // not allowed.
+ invalidFolders.add(sourceFolderModel.getSelectedKey(state).toString());
+
+ // Save the invalid folder list
+ m_invalidFolders.set(state, invalidFolders);
+ }
+
+ final Label label = new Label(value.toString());
+
+ if (invalidFolders.contains(key.toString())) {
+ return label;
+ }
+
+ // Bold if selected
+ if (isSelected) {
+ label.setFontWeight(Label.BOLD);
+ return label;
+ }
+
+ return new ControlLink(label);
+ }
+
+ }
+
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderRequestLocal.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderRequestLocal.java
new file mode 100755
index 000000000..f82279f1c
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderRequestLocal.java
@@ -0,0 +1,62 @@
+/*
+ * 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.folder;
+
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.SingleSelectionModel;
+import com.arsdigita.cms.ui.CcmObjectRequestLocal;
+
+import org.apache.log4j.Logger;
+import org.libreccm.categorization.Category;
+import org.libreccm.categorization.CategoryRepository;
+import org.libreccm.cdi.utils.CdiUtil;
+
+
+public class FolderRequestLocal extends CcmObjectRequestLocal {
+
+ private static final Logger s_log = Logger.getLogger(
+ FolderRequestLocal.class);
+
+ private final SingleSelectionModel m_model;
+
+ public FolderRequestLocal(final SingleSelectionModel model) {
+ m_model = model;
+ }
+
+ public FolderRequestLocal() {
+ m_model = null;
+ }
+
+ @Override
+ protected Object initialValue(final PageState state) {
+ if (m_model == null) {
+ return null;
+ } else {
+ final String id = m_model.getSelectedKey(state).toString();
+
+ return CdiUtil.createCdiUtil().findBean(CategoryRepository.class)
+ .findById(Long.parseLong(id));
+ }
+ }
+
+ public final Category getFolder(final PageState state) {
+ return (Category) get(state);
+ }
+
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderSelectionModel.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderSelectionModel.java
new file mode 100755
index 000000000..3bc6e12ac
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderSelectionModel.java
@@ -0,0 +1,100 @@
+/*
+ * 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.folder;
+
+
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.SingleSelectionModel;
+import com.arsdigita.cms.CMS;
+
+import com.arsdigita.cms.ItemSelectionModel;
+
+import org.apache.log4j.Category;
+import org.librecms.contentsection.ContentSection;
+
+import java.math.BigDecimal;
+
+/**
+ * Keeps track of the selection of an item in a folder. The objects that
+ * are selected by this model are all subclasses of {@link
+ * com.arsdigita.cms.Folder}.
+ *
+ * @author David Lutterkort
+ * @version $Id$
+ */
+public class FolderSelectionModel
+ extends ItemSelectionModel {
+
+ public FolderSelectionModel(String name) {
+ super(Category.class.getName(),
+ Category.class.getName(),
+ name);
+ }
+
+ public FolderSelectionModel(final SingleSelectionModel model) {
+ super(Category.class.getName(),
+ Category.class.getName(),
+ model);
+ }
+
+ public Object getSelectedKey(PageState s) {
+ // FIXME: this code will go away once parameter models support init listeners
+ Object result = super.getSelectedKey(s);
+ if ( result == null ) {
+ result = getRootFolderID(s);
+ setSelectedKey(s, result);
+ }
+ return result;
+ }
+
+ /**
+ * Clear the selection by resetting it to the root folder id.
+ *
+ * @param s represents the curent request.
+ */
+ public void clearSelection(PageState s) {
+ setSelectedKey(s, getRootFolderID(s));
+ }
+
+ /**
+ * Return the ID of the root folder. By default, this is the root folder
+ * of the content section in which the current request is made. If this
+ * model is to be used outside a content section, this method has to be
+ * overriden appropriately.
+ *
+ * @param s represents the current request
+ * @return the ID of the root folder
+ *
+ * @pre s != null
+ * @post return != null
+ */
+ protected Long getRootFolderID(PageState s) {
+ ContentSection sec = CMS.getContext().getContentSection();
+ return sec.getRootDocumentsFolder().getObjectId();
+ }
+
+ /**
+ * Return true, since this selection model will always have
+ * a folder selected in it
+ */
+ public boolean isSelected(PageState s) {
+ return true;
+ }
+
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java.off
new file mode 100755
index 000000000..f0d777d39
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java.off
@@ -0,0 +1,204 @@
+/*
+ * 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.folder;
+
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.Tree;
+import com.arsdigita.bebop.tree.TreeModelBuilder;
+import com.arsdigita.bebop.tree.TreeNode;
+import com.arsdigita.cms.CMS;
+import org.librecms.contentsection.ContentSection;
+import com.arsdigita.util.LockableImpl;
+import java.math.BigDecimal;
+import java.util.Collections;
+import java.util.Iterator;
+import org.apache.log4j.Logger;
+
+/**
+ * A {@link com.arsdigita.bebop.tree.TreeModelBuilder} that produces trees
+ * containing the folder structure underneath a root folder. The root
+ * folder can be changed by overriding {@link #getRoot getRoot}.
+ *
+ * @author Tri Tran
+ * @author David Lutterkort
+ *
+ * @version $Id: FolderTreeModelBuilder.java 2183 2011-06-20 00:57:18Z pboy $
+ */
+public class FolderTreeModelBuilder extends LockableImpl
+ implements TreeModelBuilder {
+
+ private static final Logger s_log = Logger.getLogger(FolderTreeModelBuilder.class);
+
+ /**
+ * Make a tree model that lists the hierarchy of folders underneath the
+ * folder returned by {@link #getRoot getRoot}.
+ *
+ * @param t the tree in which the model is used
+ * @param s represents the current request
+ * @return a tree model that lists the hierarchy of folders underneath the
+ * folder returnedby {@link #getRoot getRoot}.
+ */
+ @Override
+ public com.arsdigita.bebop.tree.TreeModel makeModel(final Tree t,
+ PageState s) {
+ return new DataQueryTreeModel(getRoot(s).getID(),
+ "com.arsdigita.cms.getRootFolder",
+ "com.arsdigita.cms.getSubFolders") {
+
+ @Override
+ public Iterator getChildren(TreeNode node, PageState data) {
+ String nodeKey = node.getKey().toString();
+
+ // Always expand root node
+ if (nodeKey.equals(getRoot(data).getKey().toString()) && t.isCollapsed(nodeKey, data)) {
+ t.expand(nodeKey, data);
+ }
+
+ if (t.isCollapsed(nodeKey, data)) {
+ return Collections.EMPTY_LIST.iterator();
+ }
+ Party party = Kernel.getContext().getParty();
+ OID partyOID = null;
+ if (party == null) {
+ partyOID = new OID(User.BASE_DATA_OBJECT_TYPE,
+ PermissionManager.VIRTUAL_PUBLIC_ID);
+ } else {
+ partyOID = party.getOID();
+ }
+ UniversalPermissionDescriptor universalPermission =
+ new UniversalPermissionDescriptor(SecurityManager.CMS_PREVIEW_ITEM_DESCRIPTOR, partyOID);
+ if (PermissionService.checkPermission(universalPermission)) {
+ // the person is an admin so we just pass in the
+ // standard, non filtered query
+ return getDataQueryTreeIterator(
+ (DataQueryTreeNode) node,
+ "com.arsdigita.cms.getSubFolders");
+ } else {
+ // now we need to set the parameters
+ return new NewFolderBrowserIterator(
+ (DataQueryTreeNode) node,
+ partyOID);
+ }
+ }
+ };
+ }
+
+ /**
+ * Retrn the root folder for the tree model in the current
+ * request.
+ * @param s represents the current request
+ * @return the root folder for the tree
+ * @post return != null
+ */
+ protected Folder getRoot(PageState s)
+ throws IllegalStateException {
+ ContentSection sec = CMS.getContext().getContentSection();
+ return sec.getRootFolder();
+ }
+
+ private class NewFolderBrowserIterator implements Iterator {
+
+ private DataQuery m_nodes;
+
+ public NewFolderBrowserIterator(DataQueryTreeNode node, OID partyOID) {
+
+ BigDecimal userID = (BigDecimal) partyOID.get("id");
+
+ String sql = ""
+ + "\n select f.folder_id as id,"
+ + "\n f.label as name,"
+ + "\n count(sub.item_id) as nchild"
+ + "\n from cms_folders f,"
+ + "\n cms_items i"
+ + "\n left join"
+ + "\n (select i2.item_id, f2.label as name, i2.parent_id"
+ + "\n from cms_folders f2,"
+ + "\n cms_items i2"
+ + "\n where f2.folder_id = i2.item_id) sub"
+ + "\n on (sub.parent_id = i.item_id"
+ + "\n and"
+ + "\n exists (select 1"
+ + "\n from dnm_object_1_granted_context dogc,"
+ + "\n dnm_granted_context dgc,"
+ + "\n dnm_permissions dp,"
+ + "\n dnm_group_membership dgm"
+ + "\n where dogc.pd_object_id = sub.item_id"
+ + "\n and dogc.pd_context_id = dgc.pd_object_id"
+ + "\n and dgc.pd_context_id = dp.pd_object_id"
+ + "\n and dp.pd_grantee_id = dgm.pd_group_id"
+ + "\n and dgm.pd_member_id in (-200," + userID + ",-202)"
+ + "\n and dp." + TREE_DESCRIPTOR.getColumnName() + " = '1'"
+ + "\n ) )"
+ + "\n where i.parent_id = " + node.getID()
+ + "\n and f.folder_id = i.item_id"
+ + "\n and exists ("
+ + "\n select 1 as permission_p"
+ + "\n from dnm_object_1_granted_context dogc,"
+ + "\n dnm_granted_context dgc,"
+ + "\n dnm_permissions dp,"
+ + "\n dnm_group_membership dgm"
+ + "\n where dogc.pd_context_id = dgc.pd_object_id"
+ + "\n and dgc.pd_context_id = dp.pd_object_id"
+ + "\n and dgm.pd_member_id in (-200," + userID + ",-202)"
+ + "\n and dp.pd_grantee_id = dgm.pd_group_id"
+ + "\n and dogc.pd_object_id = f.folder_id"
+ + "\n and dp." + TREE_DESCRIPTOR.getColumnName() + " = '1' )"
+ + "\n group by f.label, f.folder_id"
+ + "\n order by lower(f.label)";
+
+ if (s_log.isDebugEnabled()) {
+ s_log.debug("Custom SQL: \n" + sql);
+ }
+
+ m_nodes = new GenericDataQuery(
+ SessionManager.getSession(),
+ sql,
+ new String[]{"id", "name", "nchild"});
+ }
+
+ @Override
+ public Object next() {
+ BigDecimal id = new BigDecimal(0);
+ try {
+ // this appears to be the only portable way to dig numbers out
+ // of the result set
+ id = new BigDecimal(m_nodes.get("id").toString());
+ } catch (NumberFormatException nfe) {
+ }
+ String name = m_nodes.get("name").toString();
+ BigDecimal count = new BigDecimal(0);
+ try {
+ count = new BigDecimal(m_nodes.get("nchild").toString());
+ } catch (NumberFormatException nfe) {
+ }
+
+ return new DataQueryTreeNode(id, name, count.intValue() > 0);
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("cannot remove nodes via iterator");
+ }
+
+ @Override
+ public boolean hasNext() {
+ return m_nodes.next();
+ }
+ }
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/ItemPath.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/ItemPath.java.off
new file mode 100755
index 000000000..01057a6aa
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/ItemPath.java.off
@@ -0,0 +1,77 @@
+/*
+ * 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.folder;
+
+import com.arsdigita.bebop.List;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.cms.ContentItem;
+import com.arsdigita.cms.ItemCollection;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.util.LockableImpl;
+
+/**
+ * Produce a list of the items starting from the selected item's root down
+ * to the item itself.
+ *
+ * @author David Lutterkort
+ * @version $Id: ItemPath.java 1940 2009-05-29 07:15:05Z terry $
+ */
+public class ItemPath extends List {
+
+ public ItemPath(ItemSelectionModel folderSel) {
+ super(new ListModelBuilder(folderSel));
+ setAttribute("type", "item-path");
+ setSelectionModel(folderSel);
+ }
+
+ public static class ListModel
+ implements com.arsdigita.bebop.list.ListModel {
+ ItemCollection m_coll;
+
+ public ListModel(ContentItem i) {
+ m_coll = i.getPathInfo(true);
+ }
+
+ public boolean next() {
+ return m_coll.next();
+ }
+
+ public Object getElement() {
+ return m_coll.getName();
+ }
+
+ public String getKey() {
+ return m_coll.getID().toString();
+ }
+ }
+
+ public static class ListModelBuilder extends LockableImpl
+ implements com.arsdigita.bebop.list.ListModelBuilder {
+
+ ItemSelectionModel m_itemSel;
+
+ public ListModelBuilder(ItemSelectionModel itemSel) {
+ m_itemSel = itemSel;
+ }
+
+ public com.arsdigita.bebop.list.ListModel makeModel(List l, final PageState s) {
+ return new ListModel((ContentItem) m_itemSel.getSelectedObject(s));
+ }
+ }
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/LifecycleAdminPane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/LifecycleAdminPane.java.off
new file mode 100755
index 000000000..a375e8f39
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/LifecycleAdminPane.java.off
@@ -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.lifecycle;
+
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.SingleSelectionModel;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.cms.CMS;
+import com.arsdigita.cms.ContentSection;
+import com.arsdigita.cms.SecurityManager;
+import com.arsdigita.cms.lifecycle.LifecycleDefinition;
+import com.arsdigita.cms.ui.BaseAdminPane;
+import com.arsdigita.cms.ui.BaseDeleteForm;
+import com.arsdigita.cms.ui.FormSecurityListener;
+import org.apache.log4j.Logger;
+
+import java.math.BigDecimal;
+
+/**
+ * This class contains the split pane for the lifecycle administration + * interface.
+ * + * @author Michael Pih + * @author Jack Chung + * @author Justin Ross <jross@redhat.com> + * @version $Id: LifecycleAdminPane.java 1942 2009-05-29 07:53:23Z terry $ + */ +public class LifecycleAdminPane extends BaseAdminPane { + + private static Logger s_log = Logger.getLogger(LifecycleAdminPane.class); + + private final SingleSelectionModel m_model; + private final LifecycleDefinitionRequestLocal m_definition; + + public LifecycleAdminPane() { + super(new Label(gz("cms.ui.lifecycles")), + new LifecycleListModelBuilder()); + + m_model = getSelectionModel(); + m_definition = new SelectionRequestLocal(); + + // XXX secvis + //add(new LifecycleAdminContainer(m_addLink)); + + setAdd(gz("cms.ui.lifecycle.add"), + new LifecycleAddForm(m_model)); + setEdit(gz("cms.ui.lifecycle.edit"), + new LifecycleEditForm(m_definition)); + setDelete(gz("cms.ui.lifecycle.delete"), new DeleteForm()); + + setIntroPane(new Label(gz("cms.ui.lifecycle.intro"))); + setItemPane(new LifecycleItemPane(m_definition, + getEditLink(), + getDeleteLink())); + + addAction(new LifecycleAdminContainer(getAddLink())); + } + + private class SelectionRequestLocal + extends LifecycleDefinitionRequestLocal { + protected final Object initialValue(final PageState state) { + final String id = m_model.getSelectedKey(state).toString(); + + return new LifecycleDefinition(new BigDecimal(id)); + } + } + + private final class DeleteForm extends BaseDeleteForm { + DeleteForm() { + super(new Label(gz("cms.ui.lifecycle.delete_prompt"))); + + addSubmissionListener + (new FormSecurityListener(SecurityManager.LIFECYCLE_ADMIN)); + } + + public final void process(final FormSectionEvent e) + throws FormProcessException { + final PageState state = e.getPageState(); + final ContentSection section = + CMS.getContext().getContentSection(); + final LifecycleDefinition definition = + m_definition.getLifecycleDefinition(state); + + section.removeLifecycleDefinition(definition); + section.save(); + + definition.delete(); + + m_model.clearSelection(state); + } + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/role/RoleAdminPane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/role/RoleAdminPane.java.off new file mode 100755 index 000000000..a85df6ba5 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/role/RoleAdminPane.java.off @@ -0,0 +1,208 @@ +/* + * 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.role; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.List; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.ParameterSingleSelectionModel; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.bebop.event.ChangeEvent; +import com.arsdigita.bebop.event.ChangeListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.list.ListModel; +import com.arsdigita.bebop.list.ListModelBuilder; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.cms.CMS; +import com.arsdigita.cms.ContentSection; +import com.arsdigita.cms.ui.BaseAdminPane; +import com.arsdigita.cms.ui.BaseDeleteForm; +import com.arsdigita.cms.ui.VisibilityComponent; +import com.arsdigita.kernel.Role; +import com.arsdigita.toolbox.ui.ActionGroup; +import com.arsdigita.toolbox.ui.Section; +import com.arsdigita.util.LockableImpl; +import org.apache.log4j.Logger; + +import java.math.BigDecimal; + +/** + * @author Justin Ross <jross@redhat.com> + * @version $Id: RoleAdminPane.java 287 2005-02-22 00:29:02Z sskracic $ + */ +public class RoleAdminPane extends BaseAdminPane { + + private static final Logger s_log = Logger.getLogger(RoleAdminPane.class); + + private final SingleSelectionModel m_model; + private final RoleRequestLocal m_role; + + private final List m_staff; + private final List m_viewers; + + public RoleAdminPane() { + m_model = new ParameterSingleSelectionModel + (new StringParameter(List.SELECTED)); + setSelectionModel(m_model); + + m_model.addChangeListener(new SelectionListener()); + + m_role = new SelectionRequestLocal(); + + m_staff = new List(new StaffListModelBuilder()); + m_staff.setSelectionModel(m_model); + + m_viewers = new List(new ViewerListModelBuilder()); + m_viewers.setSelectionModel(m_model); + + final SimpleContainer left = new SimpleContainer(); + setLeft(left); + + final StaffSection staff = new StaffSection(); + left.add(staff); + + final ViewerSection viewers = new ViewerSection(); + left.add(viewers); + + // XXX there need to be two edit forms with different boolean + // args. this is broken + setEdit(gz("cms.ui.role.edit"), new RoleEditForm(m_role, false)); + setDelete(gz("cms.ui.role.delete"), new DeleteForm()); + + setIntroPane(new Label(gz("cms.ui.role.intro"))); + setItemPane(new BaseRoleItemPane(m_model, m_role, + getEditLink(), getDeleteLink())); + } + + private class StaffSection extends Section { + StaffSection() { + setHeading(gz("cms.ui.role.staff")); + + final ActionGroup group = new ActionGroup(); + setBody(group); + + group.setSubject(m_staff); + + final ActionLink link = new ActionLink + (new Label(gz("cms.ui.role.staff.add"))); + + group.addAction(new VisibilityComponent(link, STAFF_ADMIN), + ActionGroup.ADD); + + final RoleAddForm form = new RoleAddForm(m_model, false); + getBody().add(form); + getBody().connect(link, form); + } + } + + private class ViewerSection extends Section { + ViewerSection() { + setHeading(gz("cms.ui.role.viewers")); + + final ActionGroup group = new ActionGroup(); + setBody(group); + + group.setSubject(m_viewers); + + final ActionLink link = new ActionLink + (new Label(gz("cms.ui.role.viewer.add"))); + + group.addAction(new VisibilityComponent(link, STAFF_ADMIN), + ActionGroup.ADD); + + final RoleAddForm form = new RoleAddForm(m_model, true); + getBody().add(form); + getBody().connect(link, form); + } + } + + private class SelectionListener implements ChangeListener { + public final void stateChanged(final ChangeEvent e) { + s_log.debug("Selection state changed; I may change " + + "the body's visible pane"); + + final PageState state = e.getPageState(); + + getBody().reset(state); + + if (m_model.isSelected(state)) { + s_log.debug("The selection model is selected; displaying " + + "the item pane"); + + getBody().push(state, getItemPane()); + } + } + } + + private class SelectionRequestLocal extends RoleRequestLocal { + protected final Object initialValue(final PageState state) { + final String id = m_model.getSelectedKey(state).toString(); + + return new Role(new BigDecimal(id)); + } + } + + private static class StaffListModelBuilder extends LockableImpl + implements ListModelBuilder { + public StaffListModelBuilder() { + super(); + } + + public final ListModel makeModel(final List list, + final PageState state) { + final ContentSection section = + CMS.getContext().getContentSection(); + + return new RoleListModel + (section.getStaffGroup().getOrderedRoles()); + } + } + + private static class ViewerListModelBuilder extends LockableImpl + implements ListModelBuilder { + public final ListModel makeModel(final List list, + final PageState state) { + final ContentSection section = + CMS.getContext().getContentSection(); + + return new RoleListModel + (section.getViewersGroup().getOrderedRoles()); + } + } + + private class DeleteForm extends BaseDeleteForm { + DeleteForm() { + super(gz("cms.ui.role.delete_prompt")); + + addSecurityListener(STAFF_ADMIN); + } + + public final void process(final FormSectionEvent e) + throws FormProcessException { + final PageState state = e.getPageState(); + + m_role.getRole(state).delete(); + + m_model.clearSelection(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 new file mode 100755 index 000000000..97a8aaacd --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/type/ContentTypeAdminPane.java.off @@ -0,0 +1,292 @@ +/* + * 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.type; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.GridPanel; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.ActionEvent; +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 com.arsdigita.cms.ui.BaseAdminPane; +import com.arsdigita.cms.ui.BaseDeleteForm; +import com.arsdigita.cms.ui.ContentSectionPage; +import com.arsdigita.cms.util.GlobalizationUtil; +import com.arsdigita.kernel.ACSObject; +import com.arsdigita.domain.DomainCollection; +import com.arsdigita.persistence.DataCollection; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.kernel.ui.ACSObjectSelectionModel; +import com.arsdigita.toolbox.ui.ActionGroup; +import com.arsdigita.toolbox.ui.Section; +import com.arsdigita.toolbox.ui.Cancellable; +import org.apache.log4j.Logger; + +import java.math.BigDecimal; + +/** + * This class contains the split pane for the ContentType + * administration interface. + * + * @author Jack Chung + * @author Michael Pih + * @author Stanislav Freidin + * @author Justin Ross <jross@redhat.com> + * @version $Id: ContentTypeAdminPane.java 1942 2009-05-29 07:53:23Z terry $ + */ +public final class ContentTypeAdminPane extends BaseAdminPane { + + private static final Logger s_log = Logger.getLogger(ContentTypeAdminPane.class); + private final ACSObjectSelectionModel m_model; + private final ContentTypeRequestLocal m_type; + + /** + * Constructs an admin pane. It is containing + * (a) + * a list of available content types in a + * given content section and adds a link to make additional content types + * available (out of a list of installed, but available in a given content + * section). + */ + public ContentTypeAdminPane() { + + // + super(new Label(gz("cms.ui.types")), + new ContentTypeListModelBuilder() ); //list with all Types avail. + + m_model = new ACSObjectSelectionModel(getSelectionModel()); + m_type = new SelectionRequestLocal(); + + ActionLink addTypeLink = new ActionLink(new Label(gz("cms.ui.type.add"))); + + AddTypeContainer addTypeContainer = new AddTypeContainer(); + getBody().add(addTypeContainer); + getBody().connect(addTypeLink, addTypeContainer); + addTypeLink.addActionListener(addTypeContainer); + + setEdit(new ActionLink(new Label(gz("cms.ui.type.edit"))), + new EditType(m_model)); + + setDelete(new ActionLink(new Label(gz("cms.ui.type.delete"))), + new DeleteForm()); + + setIntroPane(new Label(gz("cms.ui.type.intro"))); + setItemPane(new ContentTypeItemPane(m_model, + m_type, + getEditLink(), + getDeleteLink())); + + addAction(new TypeSecurityContainer(addTypeLink), ActionGroup.ADD); + } + + @Override + public void register(Page p) { + super.register(p); + + p.addActionListener(new ActionListener() { + + /** + * + * @param e + */ + @Override + public void actionPerformed(ActionEvent e) { + final PageState state = e.getPageState(); + ContentType contentType = (ContentType) m_model.getSelectedObject(state); + ContentSection section = CMS.getContext().getContentSection(); + if (contentType == null) { + final String template = state.getRequest() + .getParameter(ContentSectionPage + .SET_TEMPLATE); + if (template != null) { + DataCollection da = SessionManager.getSession().retrieve(SectionTemplateMapping.BASE_DATA_OBJECT_TYPE); + DomainCollection c = new DomainCollection(da); + c.addEqualsFilter(SectionTemplateMapping.SECTION + "." + ACSObject.ID, + section.getID()); + c.addEqualsFilter(SectionTemplateMapping.TEMPLATE + "." + ACSObject.ID, + new BigDecimal(template)); + c.addOrder(SectionTemplateMapping.CONTENT_TYPE + "." + ContentType.LABEL); + if (c.next()) { + SectionTemplateMapping mapping = + (SectionTemplateMapping) c.getDomainObject(); + contentType = mapping.getContentType(); + } + c.close(); + } + if (contentType == null) { + ContentTypeCollection contentTypes = section.getContentTypes(); + contentTypes.addOrder("label asc"); + try { + if (contentTypes.next()) { + contentType = contentTypes.getContentType(); + } + } finally { + contentTypes.close(); + } + } + if (contentType != null) { + m_model.setSelectedObject(state, contentType); + getBody().push(state, getItemPane()); + } + + + } + } + }); + } + + /** + * + */ + private class AddTypeContainer extends GridPanel implements ActionListener, + FormProcessListener { + + private Label m_noTypesAvailable = + new Label(gz("cms.ui.type.select.none")); + private SelectType m_selectType; + private CreateType m_createType; + + /** + * + */ + AddTypeContainer() { + super(1); + Section selectSection = new Section(); + selectSection.setHeading(new Label(gz("cms.ui.type.select"))); + add(selectSection); + + GridPanel container = new GridPanel(1); + container.add(m_noTypesAvailable); + m_selectType = new SelectType(); + m_selectType.addSubmissionListener(new CancelListener(m_selectType)); + m_selectType.addProcessListener(this); + container.add(m_selectType); + selectSection.setBody(container); + + Section addSection = new Section() { + + @Override + public final boolean isVisible(final PageState state) { + return super.isVisible(state) + && !ContentSection.getConfig().getHideUDCTUI(); + } + }; + addSection.setHeading(new Label(gz("cms.ui.type.define"))); + m_createType = new CreateType(m_model); + m_createType.addSubmissionListener(new CancelListener(m_createType)); + m_createType.addProcessListener(this); + addSection.setBody(m_createType); + add(addSection); + } + + /** + * + * @param e + */ + @Override + public void actionPerformed(ActionEvent e) { + PageState s = e.getPageState(); + ContentSection section = CMS.getContext().getContentSection(); + ContentTypeCollection contentTypes = + section.getNotAssociatedContentTypes(); + boolean hasAvailableTypes = !contentTypes.isEmpty(); + m_selectType.setVisible(s, hasAvailableTypes); + m_noTypesAvailable.setVisible(s, !hasAvailableTypes); + } + + public final void process(final FormSectionEvent e) + throws FormProcessException { + final PageState state = e.getPageState(); + resetPane(state); + } + } + + /** + * This class is essentially a copy of the CancelListener inside of + * ModalPanel. We could not use the one in ModalPanel because it was + * protected + */ + private final class CancelListener implements FormSubmissionListener { + + Cancellable m_form; + + CancelListener(Cancellable form) { + m_form = form; + } + + @Override + public void submitted(FormSectionEvent event) + throws FormProcessException { + PageState state = event.getPageState(); + if (m_form.isCancelled(state)) { + getBody().pop(state); + throw new FormProcessException(GlobalizationUtil.globalize( + "cms.ui.type.cancelled")); + } + } + } // end private class + + private void resetPane(PageState state) { + getBody().reset(state); + if (getSelectionModel().isSelected(state)) { + s_log.debug("The selection model is selected; displaying " + + "the item pane"); + getBody().push(state, getItemPane()); + } + } + + private class SelectionRequestLocal extends ContentTypeRequestLocal { + + protected final Object initialValue(final PageState state) { + ContentType contentType = (ContentType) m_model.getSelectedObject(state); + return contentType; + } + } + + private class DeleteForm extends BaseDeleteForm { + + DeleteForm() { + super(new Label(gz("cms.ui.type.delete_prompt"))); + + addSubmissionListener(new TypeSecurityListener()); + } + + public final void process(final FormSectionEvent e) + throws FormProcessException { + final PageState state = e.getPageState(); + final ContentSection section = + CMS.getContext().getContentSection(); + + section.removeContentType(m_type.getContentType(state)); + section.save(); + + getSelectionModel().clearSelection(state); + } + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/WorkflowAdminPane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/WorkflowAdminPane.java.off new file mode 100755 index 000000000..cb251c487 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/WorkflowAdminPane.java.off @@ -0,0 +1,89 @@ +/* + * 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.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.cms.SecurityManager; +import com.arsdigita.cms.ui.BaseAdminPane; +import com.arsdigita.cms.ui.BaseDeleteForm; +import com.arsdigita.cms.ui.VisibilityComponent; +import com.arsdigita.workflow.simple.WorkflowTemplate; +import org.apache.log4j.Logger; + +import java.math.BigDecimal; + +/** + * @author Justin Ross <jross@redhat.com> + * @version $Id: WorkflowAdminPane.java 287 2005-02-22 00:29:02Z sskracic $ + */ +public final class WorkflowAdminPane extends BaseAdminPane { + + private static final Logger s_log = Logger.getLogger + (WorkflowAdminPane.class); + + private final WorkflowRequestLocal m_workflow; + + public WorkflowAdminPane() { + super(gz("cms.ui.workflows"), new WorkflowListModelBuilder()); + + m_workflow = new SelectionRequestLocal(); + + setAdd(gz("cms.ui.workflow.add"), + new WorkflowAddForm(getSelectionModel())); + setEdit(gz("cms.ui.workflow.edit"), new WorkflowEditForm(m_workflow)); + setDelete(gz("cms.ui.workflow.delete"), new DeleteForm()); + + setIntroPane(new Label(gz("cms.ui.workflow.intro"))); + setItemPane(new WorkflowItemPane(m_workflow, + getEditLink(), + getDeleteLink())); + + addAction(new VisibilityComponent(getAddLink(), + SecurityManager.WORKFLOW_ADMIN)); + } + + private class DeleteForm extends BaseDeleteForm { + DeleteForm() { + super(gz("cms.ui.workflow.delete_prompt")); + + addSecurityListener(SecurityManager.WORKFLOW_ADMIN); + } + + public final void process(final FormSectionEvent e) + throws FormProcessException { + final PageState state = e.getPageState(); + + m_workflow.getWorkflow(state).delete(); + + getSelectionModel().clearSelection(state); + } + } + + private class SelectionRequestLocal extends WorkflowRequestLocal { + protected final Object initialValue(final PageState state) { + final String id = getSelectionModel().getSelectedKey + (state).toString(); + + return new WorkflowTemplate(new BigDecimal(id)); + } + } +} diff --git a/ccm-cms/src/main/java/org/librecms/CmsConstants.java b/ccm-cms/src/main/java/org/librecms/CmsConstants.java index 75a3397c5..a911fa08e 100644 --- a/ccm-cms/src/main/java/org/librecms/CmsConstants.java +++ b/ccm-cms/src/main/java/org/librecms/CmsConstants.java @@ -29,6 +29,7 @@ public class CmsConstants { public static final String DB_SCHEMA = "CCM_CMS"; public static final String CMS_BUNDLE = "org.librecms.CmsResources"; + public static final String CMS_FOLDER_BUNDLE = "com.arsdigita.cms.ui.folder.CMSFolderResources"; public static final String CONTENT_CENTER_APP_TYPE = "com.arsdigita.cms.ContentCenter"; public static final String CONTENT_CENTER_URL = "/content-center/"; @@ -40,6 +41,9 @@ public class CmsConstants { = "/templates/servlet/content-section/*"; public static final String CONTENT_SECTION_DESC_BUNDLE = "org.librecms.contentsection.ContentSectionResources"; + + public static final String CONTENT_SECTION_PAGE = "/admin"; + public static final String CONTENT_SECTION_ITEM_PAGE = "/item"; public static final String CATEGORIZATION_TYPE_FOLDER = "folder"; diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentTypeRepository.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentTypeRepository.java new file mode 100644 index 000000000..a39638840 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentTypeRepository.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2016 LibreCCM Foundation. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.contentsection; + +import org.libreccm.core.AbstractEntityRepository; + +import javax.enterprise.context.RequestScoped; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +public class ContentTypeRepository + extends AbstractEntityRepository
+ * The getSelectedKey(PageState state) 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.
+ *
+ *
+ * The getSelectedObject(PageState state) method will return the
+ * object whose id is getSelectedKey(PageState state). If the
+ * object does not actually exist, the method will return null
+ *
+ *
+ * Thus, it is possible to implement the following pattern: + *
+ * + * Naturally, theclass MyComponent extends SimpleComponent { + * ACSObjectSelectionModel m_model; + * + * public MyComponent() { + * super(); + * m_model = new ACSObjectSelectionModel("item_id"); + * } + * + * public void register(Page p) { + * super.register(p); + * p.addComponentStateParam(this, p.getStateParameter()); + * } + * + * public void doSomethingUseful(PageState s) { + * if (m_model.isSelected(s)) { + * CusomACSObject obj = (CustomACSObject)m_model.getSelectedObject(state); + * // Do something with obj.. + * } + * } + *}
ACSObjectSelectionModel could also be passed
+ * in as a parameter in the MyComponent constructor. In this
+ * case, it should be up to the parent of MyComponent to
+ * register the model's state parameter.
+ *
+ * Advanced Usage: The ACSObjectSelectionModel
+ * 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 ACSObjectSelectionModel
+ * even if the currently selected ID is not stored in a state parameter.
+ *
+ * Persistence Details: The default constructor of
+ * ACSObjectSelectionModel will attempt to use the
+ * {@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 ACSObjectSelectionModel
+ * to manually instantiate the objects:
+ *
+ *
+ * + * In this case, the model will attempt to use reflection to instantiate the + * correct subclass of+ * ACSObjectSelectionModel model = + * new ACSObjectSelectionModel("com.arsdigita.cms.Article", + * "com.arsdigita.cms.Article", "item_id"); + *
ACSObject. In addition, the supplementary
+ * 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$
+ */
+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;
+
+ /**
+ * Construct a new ACSObjectSelectionModel.
+ * This model will produce instances of ACSObject
+ * 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
+ */
+ public ACSObjectSelectionModel(BigDecimalParameter parameter) {
+ this(null, null, parameter);
+ }
+
+ /**
+ * Construct a new ACSObjectSelectionModel.
+ * This model will produce instances of ACSObject
+ * 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.
+ */
+ public ACSObjectSelectionModel(String parameterName) {
+ this(null, null, new BigDecimalParameter(parameterName));
+ }
+
+ /**
+ * Construct a new ACSObjectSelectionModel.
+ * This model will produce instances of ACSObject
+ * 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
+ */
+ public ACSObjectSelectionModel(SingleSelectionModel model) {
+ this(null, null, model);
+ }
+
+ /**
+ * Construct a new ACSObjectSelectionModel
+ *
+ * @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));
+ }
+
+ /**
+ * Construct a new ACSObjectSelectionModel
+ *
+ * @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,
+ new ParameterSingleSelectionModel(parameter));
+ }
+
+ /**
+ * Construct a new ACSObjectSelectionModel
+ *
+ * @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;
+ }
+ };
+
+ 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 );
+ }
+ }
+
+ m_objectType = objectType;
+ m_model = 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.
+ *
+ * @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".
+ */
+ public void setSelectedKey(PageState state, Object key) {
+ //BigDecimal newKey = convertToBigDecimal(key);
+
+ m_loaded.set(state, Boolean.FALSE);
+ m_model.setSelectedKey(state, key);
+ }
+
+ /**
+ * Return the object which was selected and loaded from the database,
+ * using the values supplied in the page state. May return null
+ * if isSelected(state) == false, 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.
+ */
+ public CcmObject getSelectedObject(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.
+ *
+ * @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;
+
+ // 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);
+
+ return CdiUtil.createCdiUtil().findBean(CcmObjectRepository.class).findById(id);
+
+ }
+
+ /**
+ * Select the specified object.
+ *
+ * @param state The page state
+ * @param object The content item to set
+ */
+ public void setSelectedObject(PageState state, CcmObject object) {
+ CcmObject item = object;
+
+ if (item == null) {
+ m_loaded.set(state, Boolean.FALSE);
+ m_model.setSelectedKey(state, null);
+ } else {
+ m_loaded.set(state, Boolean.TRUE);
+ m_model.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.
+ *
+ * @param state the page state
+ * @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();
+ }
+
+ /**
+ * 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 ACSObjectSelectionModel.
+ * If no classname 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
+ * @return The newly created item
+ * @post return != null
+ * @deprecated This ignores the ID since ACSObject.setID is a no-op
+ */
+ public CcmObject createACSObject(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 ACSObjectSelectionModel.
+ * If no classname was supplied in the constructor, an assertion
+ * failure will occur.
+ *
+ * @param id The id of the new item
+ * @return The newly created item
+ * @post return != null
+ */
+ public CcmObject createACSObject() throws ServletException {
+ Assert.exists(m_javaClass, 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);
+ }
+ }
+
+
+ /**
+ * @return the Class of the content items which are produced
+ * by this model
+ */
+ public Class getJavaClass() {
+ return m_javaClass;
+ }
+
+ /**
+ * @return The name of the object type of the
+ * content items which are produced by this model
+ */
+ public String getObjectType() {
+ return m_objectType;
+ }
+
+ /**
+ * @return the underlying {@link SingleSelectionModel} which
+ * maintains the ID of the selected object
+ */
+ public SingleSelectionModel getSingleSelectionModel() {
+ return m_model;
+ }
+
+ ////////////////////////
+ //
+ // Passthrough methods
+
+ /**
+ * Return true if there is a selected object.
+ *
+ * @param state represents the state of the current request
+ * @return true if there is a selected component.
+ */
+ public boolean isSelected(PageState state) {
+ return m_model.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
+ *
+ */
+ public Object getSelectedKey(PageState state) {
+ Object key = m_model.getSelectedKey(state);
+ return key;
+ }
+
+
+ /**
+ * Clear the selection.
+ *
+ * @param state the current page state.
+ * @post ! isSelected(state)
+ * @post ! isInitialized(state)
+ */
+ public void clearSelection(PageState state) {
+ m_model.clearSelection(state);
+ m_loaded.set(state, Boolean.FALSE);
+ }
+
+ /**
+ * Add a change listener to the model. The listener's
+ * stateChanged is called whenever the selected key changes.
+ *
+ * @param l a listener to notify when the selected key changes
+ */
+ public void addChangeListener(ChangeListener l) {
+ m_model.addChangeListener(l);
+ }
+
+ /**
+ * Remove a change listener from the model.
+ *
+ * @param l the listener to remove.
+ */
+ public void removeChangeListener(ChangeListener l) {
+ m_model.removeChangeListener(l);
+ }
+
+ /**
+ * 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
+ * @see SingleSelectionModel#getStateParameter()
+ */
+ public ParameterModel getStateParameter() {
+ return m_model.getStateParameter();
+ }
+
+ private static Long convertToLong(Object value) {
+ Long newValue = null;
+
+ if ( value instanceof Long ) {
+ newValue = (Long) value;
+ } else if ( value != null ) {
+ newValue = Long.parseLong(value.toString());
+ }
+
+ return newValue;
+ }
+}
diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/UserContextController.java b/ccm-core/src/main/java/org/libreccm/ui/admin/UserContextController.java
index 8627e84ee..6de01bce1 100644
--- a/ccm-core/src/main/java/org/libreccm/ui/admin/UserContextController.java
+++ b/ccm-core/src/main/java/org/libreccm/ui/admin/UserContextController.java
@@ -21,17 +21,23 @@ package org.libreccm.ui.admin;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
+
import org.apache.shiro.subject.Subject;
import org.libreccm.security.Shiro;
import org.libreccm.security.User;
+import java.io.Serializable;
+
+
/**
*
* @author Jens Pelzetter
*/
-@RequestScoped
@Named
-public class UserContextController {
+@RequestScoped
+public class UserContextController implements Serializable {
+
+ private static final long serialVersionUID = 2046117182808198398L;
@Inject
private Shiro shiro;
@@ -42,14 +48,14 @@ public class UserContextController {
public boolean isLoggedIn() {
return subject.isAuthenticated();
}
-
+
public String getCurrentUserName() {
final User user = shiro.getUser();
if (user == null) {
return "";
} else {
- return String.format("%s %s",
+ return String.format("%s %s",
user.getGivenName(),
user.getFamilyName());
}
diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/usersgroupsroles/RolesController.java b/ccm-core/src/main/java/org/libreccm/ui/admin/usersgroupsroles/RolesController.java
index 2cb5961b1..5e494dea4 100644
--- a/ccm-core/src/main/java/org/libreccm/ui/admin/usersgroupsroles/RolesController.java
+++ b/ccm-core/src/main/java/org/libreccm/ui/admin/usersgroupsroles/RolesController.java
@@ -18,55 +18,105 @@
*/
package org.libreccm.ui.admin.usersgroupsroles;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.libreccm.security.Permission;
import org.libreccm.security.Role;
+import org.libreccm.security.RoleMembership;
import org.libreccm.security.RoleRepository;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;
+import java.io.Serializable;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import javax.enterprise.context.RequestScoped;
+import java.util.Set;
+
+import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
+import javax.transaction.Transactional;
/**
*
* @author Jens Pelzetter
*/
-@RequestScoped
@Named
-public class RolesController {
+@ViewScoped
+public class RolesController implements Serializable {
+ private static final long serialVersionUID = 9092665507680111584L;
+ private static final Logger LOGGER = LogManager.getLogger(
+ RolesController.class);
+
@Inject
private RoleRepository roleRepo;
private final LazyDataModel