/* * 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); } }