562 lines
21 KiB
Java
Executable File
562 lines
21 KiB
Java
Executable File
/*
|
|
* 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.contentcenter;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
import com.arsdigita.bebop.Component;
|
|
import com.arsdigita.bebop.FormProcessException;
|
|
import com.arsdigita.bebop.Label;
|
|
import com.arsdigita.bebop.Link;
|
|
import com.arsdigita.bebop.Page;
|
|
import com.arsdigita.bebop.PageState;
|
|
import com.arsdigita.bebop.SingleSelectionModel;
|
|
import com.arsdigita.bebop.Table;
|
|
import com.arsdigita.bebop.event.FormProcessListener;
|
|
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
import com.arsdigita.bebop.event.FormSubmissionListener;
|
|
import com.arsdigita.bebop.form.Hidden;
|
|
import com.arsdigita.bebop.parameters.BigDecimalParameter;
|
|
import com.arsdigita.bebop.table.TableCellRenderer;
|
|
import com.arsdigita.bebop.table.TableColumn;
|
|
import com.arsdigita.bebop.table.TableColumnModel;
|
|
import com.arsdigita.bebop.table.TableModel;
|
|
import com.arsdigita.bebop.table.TableModelBuilder;
|
|
import com.arsdigita.cms.ContentSection;
|
|
import com.arsdigita.cms.ContentSectionCollection;
|
|
import com.arsdigita.cms.Folder;
|
|
import com.arsdigita.cms.PageLocations;
|
|
import com.arsdigita.cms.SecurityManager;
|
|
import com.arsdigita.cms.ui.CMSContainer;
|
|
import com.arsdigita.cms.ui.authoring.NewItemForm;
|
|
import com.arsdigita.cms.util.GlobalizationUtil;
|
|
import com.arsdigita.domain.DataObjectNotFoundException;
|
|
import com.arsdigita.kernel.Kernel;
|
|
import com.arsdigita.kernel.User;
|
|
import com.arsdigita.kernel.permissions.PermissionService;
|
|
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
|
import com.arsdigita.util.Assert;
|
|
import com.arsdigita.util.LockableImpl;
|
|
import com.arsdigita.web.Web;
|
|
|
|
/**
|
|
* Displays all the content sections in table, with links to the admin
|
|
* (and in legacy mode to legacy public pages as well). Also displays a form for
|
|
* each content section to create an object of a given type. The list of
|
|
* available types retrieved for each content section.
|
|
*
|
|
* <p>
|
|
* This class is a container for two other components: a form and a
|
|
* table. The form represents the drop down list of the content types
|
|
* available in a particular content section. It is an extension of
|
|
* the {@link com.arsdigita.cms.ui.authoring.NewItemForm}. The table
|
|
* displays each content section in one row, along with the specified
|
|
* form. The same form is reused in every row of the table.
|
|
*
|
|
* @author <a href="mailto:mbryzek@arsdigita.com">Michael Bryzek</a>
|
|
* @version $Id: ContentSectionContainer.java 287 2005-02-22 00:29:02Z sskracic $
|
|
*/
|
|
public class ContentSectionContainer extends CMSContainer {
|
|
|
|
private ContentSectionTable m_table;
|
|
private FormContainer m_formContainer;
|
|
|
|
private SingleSelectionModel m_typeSel;
|
|
private SingleSelectionModel m_sectionSel;
|
|
|
|
/**
|
|
* Constructs a new ContentSectionContainer which containts:
|
|
*
|
|
* <ul>
|
|
* <li> SimpleContainer (to contain the form)
|
|
* <ul>
|
|
* <li> Form (for creating a new content item in each section)
|
|
* </ul>
|
|
* <li> Table (Displays all content sections)
|
|
* </ul>
|
|
*
|
|
* @param typeSel passthrough to {@link NewItemForm}
|
|
* @param sectionSel passthrough to {@link NewItemForm}
|
|
**/
|
|
public ContentSectionContainer(SingleSelectionModel typeSel,
|
|
SingleSelectionModel sectionSel) {
|
|
super();
|
|
|
|
m_typeSel = typeSel;
|
|
m_sectionSel = sectionSel;
|
|
|
|
m_formContainer = new FormContainer();
|
|
add(m_formContainer);
|
|
m_table = new ContentSectionTable();
|
|
add(m_table);
|
|
}
|
|
|
|
@Override
|
|
public void register(Page p) {
|
|
super.register(p);
|
|
p.setVisibleDefault(m_formContainer, false);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
private class FormContainer extends CMSContainer {
|
|
|
|
private StaticNewItemForm m_form;
|
|
private BigDecimalParameter m_sectionIdParam;
|
|
|
|
private FormContainer() {
|
|
super();
|
|
m_sectionIdParam = new BigDecimalParameter("sectionId");
|
|
m_form = new StaticNewItemForm(m_sectionIdParam);
|
|
|
|
m_form.addSubmissionListener(new FormSubmissionListener() {
|
|
/**
|
|
* Cancels the form if the user lacks the "create new items" privilege.
|
|
*/
|
|
public void submitted(FormSectionEvent event)
|
|
throws FormProcessException {
|
|
PageState state = event.getPageState();
|
|
StaticNewItemForm form = (StaticNewItemForm) event.getSource();
|
|
|
|
ContentSection section = form.getContentSection(state);
|
|
SecurityManager sm = new SecurityManager(section);
|
|
Folder folder = null;
|
|
User user = Web.getContext().getUser();
|
|
if ( user != null ) {
|
|
folder = Folder.getUserHomeFolder(user,section);
|
|
}
|
|
if ( folder == null ) {
|
|
folder = section.getRootFolder();
|
|
}
|
|
|
|
if (! sm.canAccess(state.getRequest(),
|
|
SecurityManager.NEW_ITEM, folder)) {
|
|
throw new FormProcessException(
|
|
(String) GlobalizationUtil.globalize(
|
|
"cms.ui.insufficient_privileges").localize());
|
|
}
|
|
}
|
|
});
|
|
|
|
m_form.addProcessListener(new FormProcessListener() {
|
|
/**
|
|
* Process listener: redirects to the authoring kit to create a new item.
|
|
*/
|
|
public void process(FormSectionEvent e) throws FormProcessException {
|
|
StaticNewItemForm form = (StaticNewItemForm) e.getSource();
|
|
PageState state = e.getPageState();
|
|
|
|
BigDecimal typeId = form.getTypeID(state);
|
|
if( typeId != null ) {
|
|
BigDecimal sectionId = form.getContentSectionID(state);
|
|
m_sectionSel.setSelectedKey(state, sectionId);
|
|
m_typeSel.setSelectedKey(state, typeId);
|
|
}
|
|
}
|
|
});
|
|
|
|
add(m_form);
|
|
}
|
|
|
|
@Override
|
|
public void register(Page p) {
|
|
super.register(p);
|
|
p.addComponentStateParam(this, m_sectionIdParam);
|
|
}
|
|
|
|
public StaticNewItemForm getNewItemForm() {
|
|
return m_form;
|
|
}
|
|
}
|
|
|
|
private static class StaticNewItemForm extends NewItemForm {
|
|
|
|
private Hidden m_sectionIDParamWidget;
|
|
|
|
public StaticNewItemForm(BigDecimalParameter sectionParam) {
|
|
super("StaticNewItemForm");
|
|
m_sectionIDParamWidget = new Hidden(sectionParam);
|
|
add(m_sectionIDParamWidget);
|
|
setProcessInvisible(true);
|
|
}
|
|
|
|
|
|
/**
|
|
* Sets the id of the content section in this form. This ID is
|
|
* used to generate a list of available content types in the
|
|
* section.
|
|
*
|
|
* @param state The current page state.
|
|
* @param id The id of the ContentSection for which this form
|
|
* should display a list of content types
|
|
*
|
|
* @pre ( state != null && id != null )
|
|
**/
|
|
public void setSectionId(PageState state, BigDecimal id) {
|
|
Assert.exists(id);
|
|
m_sectionIDParamWidget.setValue(state, id);
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieves the content section for this form given the specified
|
|
* page state. This method will return null if there is no content
|
|
* section.
|
|
*
|
|
* @param state The current page state.
|
|
* @return The current content section or null if the section does
|
|
* not exist
|
|
*
|
|
* @pre ( state != null )
|
|
**/
|
|
public ContentSection getContentSection(PageState state) {
|
|
BigDecimal id = getContentSectionID(state);
|
|
Assert.exists(id);
|
|
ContentSection section;
|
|
try {
|
|
section = new ContentSection(id);
|
|
} catch (DataObjectNotFoundException ex) {
|
|
section = null;
|
|
}
|
|
return section;
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieves the ID of the content section for this form given the
|
|
* specified page state. This method will return null if no
|
|
* content section id has been set.
|
|
*
|
|
* @param state The current page state.
|
|
* @return The id of the content section or null if it has not
|
|
* been set.
|
|
*
|
|
* @pre ( state != null )
|
|
**/
|
|
private BigDecimal getContentSectionID(PageState state) {
|
|
return (BigDecimal) m_sectionIDParamWidget.getValue(state);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* A table that displays all content sections, with links to their
|
|
* locations and admin pages and a {@link NewItemForm} next to each
|
|
* section.
|
|
*
|
|
* @author <a href="mailto:mbryzek@arsdigita.com">Michael Bryzek</a>
|
|
* @version $Revision: #13 $ $DateTime: 2004/08/17 23:15:09 $
|
|
**/
|
|
private class ContentSectionTable extends Table {
|
|
|
|
private static final String COLUMN_SECTION = "Section";
|
|
private static final String COLUMN_LOCATION = "Public Site";
|
|
private static final String COLUMN_ACTION = "Action";
|
|
|
|
/**
|
|
* Constructs a new ContentSectionTable, using a default table
|
|
* model builder.
|
|
**/
|
|
private ContentSectionTable() {
|
|
super();
|
|
|
|
Integer colNo = 0;
|
|
|
|
Label emptyView = new Label
|
|
("There are currently no content sections installed.");
|
|
emptyView.setFontWeight(Label.ITALIC);
|
|
setEmptyView(emptyView);
|
|
|
|
setClassAttr("dataTable");
|
|
|
|
// add columns to the table
|
|
TableColumnModel columnModel = getColumnModel();
|
|
|
|
//TableColumn contentSectionColumn = new TableColumn(colNo, COLUMN_SECTION);
|
|
TableColumn contentSectionColumn = new TableColumn(
|
|
colNo,
|
|
(String)GlobalizationUtil.globalize("cms.ui.contentcenter.section").localize(),
|
|
COLUMN_SECTION);
|
|
contentSectionColumn.setCellRenderer(new AdminURLTableCellRenderer());
|
|
columnModel.add(contentSectionColumn);
|
|
|
|
if( !ContentSection.getConfig().getHideLegacyPublicSiteLink() ) {
|
|
TableColumn locationColumn = new TableColumn(colNo ++,
|
|
COLUMN_LOCATION);
|
|
locationColumn.setCellRenderer(new URLTableCellRenderer());
|
|
columnModel.add(locationColumn);
|
|
}
|
|
|
|
TableColumn actionColumn = new TableColumn(
|
|
colNo++,
|
|
(String)GlobalizationUtil.globalize("cms.ui.contentcenter.action").localize(),
|
|
COLUMN_ACTION);
|
|
actionColumn.setCellRenderer(new ActionTableCellRenderer());
|
|
columnModel.add(actionColumn);
|
|
|
|
setModelBuilder(new ContentSectionTableModelBuilder());
|
|
}
|
|
|
|
|
|
/**
|
|
* An ContentSections table model builder
|
|
*
|
|
* @author <a href="mailto:mbryzek@arsdigita.com">Michael Bryzek</a>
|
|
**/
|
|
private class ContentSectionTableModelBuilder extends LockableImpl
|
|
implements TableModelBuilder {
|
|
|
|
public TableModel makeModel(Table table, PageState state) {
|
|
table.getRowSelectionModel().clearSelection(state);
|
|
return new ContentSectionTableModel((ContentSectionTable) table, state);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* An ContentSections table model
|
|
*
|
|
* @author <a href="mailto:mbryzek@arsdigita.com">Michael Bryzek</a>
|
|
**/
|
|
private class ContentSectionTableModel implements TableModel {
|
|
|
|
private ContentSectionTable m_table;
|
|
private TableColumnModel m_columnModel;
|
|
private PageState m_state;
|
|
|
|
private ContentSectionCollection m_contentSections;
|
|
private ContentSection m_section;
|
|
|
|
private ContentSectionTableModel(ContentSectionTable table,
|
|
PageState state) {
|
|
m_table = table;
|
|
m_columnModel = table.getColumnModel();
|
|
m_state = state;
|
|
|
|
// retrieve all Content Sections
|
|
m_contentSections = getContentSectionCollection();
|
|
PermissionService.filterObjects(m_contentSections,
|
|
PrivilegeDescriptor.READ,
|
|
Kernel.getContext().getParty().getOID());
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns a collection of ContentSections to display in this
|
|
* table. This implementation orders the content sections by
|
|
* <code>lower(label)</code>.
|
|
**/
|
|
private ContentSectionCollection getContentSectionCollection() {
|
|
ContentSectionCollection sections = ContentSection.getAllSections();
|
|
sections.addOrder("lower(label)");
|
|
return sections;
|
|
}
|
|
|
|
public int getColumnCount() {
|
|
return m_columnModel.size();
|
|
}
|
|
|
|
public boolean nextRow() {
|
|
if (m_contentSections.next()) {
|
|
m_section = m_contentSections.getContentSection();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* By default, we return null. For the section, location, and
|
|
* action columns, we return the current Content Section if
|
|
* there is one.
|
|
*
|
|
* @param columnIndex The index of the current column
|
|
**/
|
|
public Object getElementAt(int columnIndex) {
|
|
if(m_columnModel == null || m_section == null) {
|
|
return null;
|
|
}
|
|
|
|
TableColumn tc = m_columnModel.get(columnIndex);
|
|
String columnName = (String) tc.getHeaderValue();
|
|
|
|
Object result = m_section;
|
|
if (columnName.equals(COLUMN_SECTION) ||
|
|
columnName.equals(COLUMN_LOCATION) ||
|
|
columnName.equals(COLUMN_ACTION)) {
|
|
result = m_section;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public Object getKeyAt(int columnIndex) {
|
|
return m_section.getID();
|
|
}
|
|
|
|
/**
|
|
* Returns the table associated with this table model.
|
|
**/
|
|
protected Table getTable() {
|
|
return m_table;
|
|
}
|
|
|
|
/**
|
|
* Returns the current page state
|
|
**/
|
|
protected PageState getPageState() {
|
|
return m_state;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Sets the hidden parameter in the form containers form to
|
|
* the id of the current section. Then returns the form for
|
|
* display, but only if the user has permission to create new
|
|
* items in the current section.
|
|
*
|
|
* @author <a href="mailto:mbryzek@arsdigita.com">Michael Bryzek</a>
|
|
**/
|
|
private class ActionTableCellRenderer implements TableCellRenderer {
|
|
public Component getComponent(Table table, PageState state, Object value,
|
|
boolean isSelected, Object key,
|
|
int row, int column) {
|
|
ContentSection section = (ContentSection) value;
|
|
Folder folder = null;
|
|
User user = Web.getContext().getUser();
|
|
if ( user != null ) {
|
|
folder = Folder.getUserHomeFolder(user,section);
|
|
}
|
|
if ( folder == null ) {
|
|
folder = section.getRootFolder();
|
|
}
|
|
// If the user has no access, return an empty Label
|
|
SecurityManager sm = new SecurityManager(section);
|
|
|
|
if (! sm.canAccess(state.getRequest(), SecurityManager.NEW_ITEM, folder)
|
|
|| !ContentSection.getConfig().getAllowContentCreateInSectionListing()
|
|
) {
|
|
return new Label(" - - "+
|
|
" "+
|
|
" "+
|
|
" "+
|
|
" ",
|
|
false);
|
|
} else {
|
|
// set the value of the sectionIdParameter in the form
|
|
// to this section
|
|
m_formContainer.getNewItemForm().setSectionId(state, section.getID());
|
|
return m_formContainer.getNewItemForm();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Generates the correct URL to the public pages for a content
|
|
* section.
|
|
*
|
|
* @author <a href="mailto:mbryzek@arsdigita.com">Michael Bryzek</a>
|
|
**/
|
|
public static class URLTableCellRenderer implements TableCellRenderer {
|
|
|
|
/**
|
|
* The object passed in is the current content section. This
|
|
* returns a Link whose name and target are the url to the
|
|
* public pages.
|
|
*
|
|
* @return Link whose name and target are the url to the public pages
|
|
* of the current (passed in) content section
|
|
* or a Label if current use does not habe acces priviledge
|
|
* for the content section
|
|
*/
|
|
public Component getComponent(Table table,
|
|
PageState state,
|
|
Object value,
|
|
boolean isSelected,
|
|
Object key,
|
|
int row,
|
|
int column) {
|
|
|
|
/* cast to ContentSection for further processing */
|
|
ContentSection section = (ContentSection) value;
|
|
String name = section.getName();
|
|
String path = section.getPath() ; // from Application
|
|
|
|
|
|
// If the user has no access, return a Label instead of a Link
|
|
SecurityManager sm = new SecurityManager(section);
|
|
|
|
if (sm.canAccess(state.getRequest(), SecurityManager.PUBLIC_PAGES)
|
|
&& !ContentSection.getConfig().getHideLegacyPublicSiteLink()
|
|
) {
|
|
|
|
return new Link("/"+name+"/", path+"/");
|
|
} else {
|
|
return new Label("/"+name+"/", false);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* Generates the correct URL to the admin pages for a content
|
|
* section.
|
|
*
|
|
* @author <a href="mailto:mbryzek@arsdigita.com">Michael Bryzek</a>
|
|
**/
|
|
public static class AdminURLTableCellRenderer extends URLTableCellRenderer {
|
|
|
|
/**
|
|
* The object passed in is the current content section
|
|
**/
|
|
@Override
|
|
public Component getComponent(Table table, PageState state, Object value,
|
|
boolean isSelected, Object key,
|
|
int row, int column) {
|
|
ContentSection section = (ContentSection) value;
|
|
|
|
// If the user has no access, return a Label instead of a Link
|
|
SecurityManager sm = new SecurityManager(section);
|
|
|
|
if (sm.canAccess(state.getRequest(), SecurityManager.ADMIN_PAGES)) {
|
|
return new Link(section.getName(),
|
|
generateURL(section.getPath() + "/"));
|
|
} else {
|
|
return new Label(section.getName(), false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generates the admin url for the specified prefix. Always
|
|
* returns something that does not start with a forward slash.
|
|
*
|
|
* @param prefix The prefix of the URL
|
|
**/
|
|
protected String generateURL(String prefix) {
|
|
return prefix + PageLocations.SECTION_PAGE;
|
|
}
|
|
}
|
|
|
|
}
|