/*
* 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.BebopConfig;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Link;
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.SimpleContainer;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.Text;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.TableActionAdapter;
import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.event.TableActionListener;
import com.arsdigita.bebop.parameters.BigDecimalParameter;
import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.bebop.table.AbstractTableModelBuilder;
import com.arsdigita.bebop.table.DefaultTableCellRenderer;
import com.arsdigita.bebop.table.TableColumn;
import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.bebop.util.BebopConstants;
import com.arsdigita.cms.CMS;
import com.arsdigita.cms.dispatcher.Utilities;
import com.arsdigita.cms.ui.folder.FolderSelectionModel;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.util.Assert;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.arsdigita.cms.CMSConfig;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.core.CcmObject;
import org.libreccm.l10n.GlobalizationHelper;
import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionConfig;
import org.librecms.contentsection.ContentType;
import org.librecms.contentsection.Folder;
import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;
/**
* Browse folders and items. If the user clicks on a folder, the folder
* selection model is updated. If the user clicks on any other item, an separate
* item selection model is updated.
*
* @author David Lutterkort
* @author Jens Pelzetter
*/
public class ItemSearchFolderBrowser extends Table {
private static final Logger LOGGER = LogManager.getLogger(
ItemSearchFolderBrowser.class);
private static final GlobalizedMessage[] HEADERS = {
globalize("cms.ui.folder.name"),
globalize("cms.ui.folder.title"),
globalize("cms.ui.folder.type")};
private FolderSelectionModel currentFolder;
private TableActionListener folderChanger;
private TableActionListener deleter;
private TableActionListener indexChanger;
private TableColumn nameColumn;
private Paginator paginator;
public ItemSearchFolderBrowser(final FolderSelectionModel currentFolder) {
super((FolderTableModelBuilder) null, HEADERS);
final FolderTableModelBuilder builder = new FolderTableModelBuilder();
setModelBuilder(builder);
paginator = new Paginator(
builder, CMSConfig.getConfig().getFolderBrowseListSize());
this.currentFolder = currentFolder;
setClassAttr("dataTable");
getHeader().setDefaultRenderer(
new com.arsdigita.cms.ui.util.DefaultTableCellRenderer());
nameColumn = getColumn(0);
nameColumn.setCellRenderer(new NameCellRenderer());
folderChanger = new FolderChanger();
addTableActionListener(folderChanger);
setEmptyView(new Label(globalize("cms.ui.folder.no_items")));
Assert.exists(currentFolder.getStateParameter());
}
public Paginator getPaginator() {
return paginator;
}
@Override
public void register(final Page page) {
super.register(page);
page.addComponentStateParam(this, currentFolder.getStateParameter());
page.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent event) {
// MP: This action listener should only be called when the
// folder browser is visible.
showHideFolderActions(event.getPageState());
}
});
}
private Folder getCurrentFolder(final PageState state) {
return (Folder) currentFolder.getSelectedObject(state);
}
private void showHideFolderActions(final PageState state) {
// Empty
}
public FolderSelectionModel getFolderSelectionModel() {
return currentFolder;
}
private class FolderTableModelBuilder
extends AbstractTableModelBuilder implements PaginationModelBuilder {
private RequestLocal size = new RequestLocal() {
@Override
protected Object initialValue(final PageState state) {
List items = getItemCollection(state);
if (null == items) {
return 0;
}
return items.size();
}
};
private RequestLocal items = new RequestLocal() {
@Override
protected Object initialValue(final PageState state) {
List items = getItemCollection(state);
return items;
}
};
@Override
public TableModel makeModel(final Table table, final PageState state) {
final FolderSelectionModel selectionModel
= ((ItemSearchFolderBrowser) table)
.getFolderSelectionModel();
final Folder folder = getCurrentFolder(state);
if (LOGGER.isDebugEnabled()) {
if (null == folder) {
LOGGER.debug("Selected folder is null");
} else {
LOGGER.debug("Selected folder: {} {}",
folder.getDisplayName(),
folder.getObjectId());
}
}
if (folder == null) {
return Table.EMPTY_MODEL;
} else {
table.getRowSelectionModel().clearSelection(state);
return new FolderTableModel((List) items.
get(state));
}
}
private List getItemCollection(final PageState state) {
final Folder folder = getCurrentFolder(state);
final List items = folder.getObjects()
.stream()
.map(categorization -> categorization.getCategorizedObject())
.filter(object -> object instanceof ContentItem)
.map(object -> (ContentItem) object)
.collect(Collectors.toList());
return items;
}
@Override
public int getTotalSize(final Paginator paginator,
final PageState state) {
return (int) this.size.get(state);
}
/**
* Indicates whether the paginator should be visible, based on the
* visibility of the folder browser itself and how many items are
* displayed
*
* @return true if folder browser is visible and there is more than 1
* page of items, false otherwise
*/
@Override
public boolean isVisible(final PageState state) {
final int size = (int) this.size.get(state);
return ItemSearchFolderBrowser.this.isVisible(state)
&& (size > CMSConfig.getConfig()
.getFolderBrowseListSize());
}
}
/**
* Produce links to view an item or control links for folders to change into
* the folder.
*/
private class NameCellRenderer extends DefaultTableCellRenderer {
public NameCellRenderer() {
super(true);
}
@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) {
if (value instanceof Folder) {
return super.getComponent(table,
state,
((CcmObject) value).getDisplayName(),
isSelected,
key,
row,
column);
} else if (value instanceof ContentItem) {
final ContentItem item = (ContentItem) value;
final ContentSection section = CMS.getContext()
.getContentSection();
final long objectId = (long) key;
final String name = item.getDisplayName();
if (section == null) {
return new Text(name);
} else {
final SimpleContainer container = new SimpleContainer();
final String widget = (String) state.getValue(
new StringParameter(
ItemSearchPopup.WIDGET_PARAM));
String searchWidget = (String) state.getValue(
new StringParameter("searchWidget"));
boolean useURL = "true".equals(state.getValue(
new StringParameter(
ItemSearchPopup.URL_PARAM)));
String fillString;
if (useURL) {
fillString = ItemSearchPopup.getItemURL(
state.getRequest(), item.getObjectId());
} else {
fillString = Long.toString(objectId);
}
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final GlobalizationHelper globalizationHelper = cdiUtil
.findBean(GlobalizationHelper.class);
final String title = item.getTitle().getValue(
globalizationHelper.getNegotiatedLocale());
final Label jsLabel = new Label(
generateJSLabel(objectId,
widget,
searchWidget,
fillString,
title),
false);
container.add(jsLabel);
final String url = "#";
final Link link = new Link(name, url);
link.setClassAttr("title");
link.setOnClick("return fillItem" + objectId + "()");
container.add(link);
return container;
}
} else {
throw new IllegalArgumentException(String.format(
"Expected value to be either a '{}' or a '{]', but was '{}'.",
Folder.class.getName(),
ContentItem.class.getName(),
value.getClass().getName()));
}
}
private String generateJSLabel(final long id,
final String widget,
final String searchWidget,
final String fill,
final String title) {
final StringBuilder buffer = new StringBuilder();
buffer.append(" ");
return buffer.toString();
}
}
/**
* Table model around ItemCollection
*/
private static class FolderTableModel implements TableModel {
private static final int NAME = 0;
private static final int TITLE = 1;
private static final int TYPE = 2;
private final List items;
private int index = -1;
public FolderTableModel(final List items) {
this.items = items;
}
@Override
public int getColumnCount() {
return 3;
}
@Override
public boolean nextRow() {
index++;
if (index < items.size()) {
return true;
} else {
return false;
}
}
@Override
public Object getElementAt(final int columnIndex) {
switch (columnIndex) {
case NAME:
return items.get(index);
case TITLE:
return items.get(index).getDisplayName();
case TYPE:
return items.get(index).getContentType().getDisplayName();
default:
throw new IllegalArgumentException(String.format(
"Column index {} not in table model.", columnIndex));
}
}
@Override
public Object getKeyAt(final int columnIndex) {
return items.get(index).getObjectId();
}
}
private class FolderChanger extends TableActionAdapter {
@Override
public void cellSelected(final TableActionEvent event) {
final PageState state = event.getPageState();
final int col = event.getColumn();
if (nameColumn != getColumn(col)) {
return;
}
final String key = (String) event.getRowKey();
if (key.startsWith("-")) {
clearSelection(state);
getFolderSelectionModel().setSelectedKey(
state, Long.parseLong(key.substring(1)));
paginator.reset(state);
}
}
}
/**
* Getting the GlobalizedMessage using a CMS Class targetBundle.
*
* @param key The resource key
*
* @pre ( key != null )
*/
private static GlobalizedMessage globalize(final String key) {
return new GlobalizedMessage(key, CmsConstants.CMS_FOLDER_BUNDLE);
}
}