From f2636f6bb77f20cc204e342757d206194128ea08 Mon Sep 17 00:00:00 2001 From: jensp Date: Wed, 23 Aug 2017 17:20:16 +0000 Subject: [PATCH] CCM NG/ccm-cms: New server side part of the ItemSearchWidget, some other things git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4918 8810af33-2d31-482b-a856-94f89814c4df Former-commit-id: 12278cf3afb088a03d691a883f0bc7009985f786 --- .../cms/ui/ItemSearchBrowsePane.java.todo | 367 -------------- .../cms/ui/ItemSearchFlatBrowsePane.java.todo | 410 ---------------- .../cms/ui/ItemSearchFolderBrowser.java.todo | 457 ------------------ .../arsdigita/cms/ui/ItemSearchPage.java.todo | 387 --------------- .../cms/ui/ItemSearchPopup.java.todo | 200 -------- .../cms/ui/assets/AssetSearchWidget.java | 10 +- .../cms/ui/assets/ItemSearchWidget.java | 117 +++++ .../relatedinfo/InternalLinkAddForm.java | 89 ++++ .../RelatedInfoAttachAssetForm.java | 3 +- .../org/librecms/contentsection/Asset.java | 2 +- .../librecms/contentsection/ContentItem.java | 135 ++++++ .../contentsection/ContentItemRepository.java | 95 ++++ .../librecms/contentsection/rs/Assets.java | 7 +- .../contentsection/rs/ContentItems.java | 291 +++++++++++ 14 files changed, 739 insertions(+), 1831 deletions(-) delete mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchBrowsePane.java.todo delete mode 100644 ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchFlatBrowsePane.java.todo delete mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchFolderBrowser.java.todo delete mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchPage.java.todo delete mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchPopup.java.todo create mode 100644 ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/ItemSearchWidget.java create mode 100644 ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/relatedinfo/InternalLinkAddForm.java create mode 100644 ccm-cms/src/main/java/org/librecms/contentsection/rs/ContentItems.java diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchBrowsePane.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchBrowsePane.java.todo deleted file mode 100755 index 3c45e0475..000000000 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchBrowsePane.java.todo +++ /dev/null @@ -1,367 +0,0 @@ -/* - * 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.BoxPanel; -import com.arsdigita.bebop.Form; -import com.arsdigita.bebop.Label; -import com.arsdigita.bebop.Page; -import com.arsdigita.bebop.PageState; -import com.arsdigita.bebop.Resettable; -import com.arsdigita.bebop.SimpleContainer; -import com.arsdigita.bebop.SingleSelectionModel; -import com.arsdigita.bebop.Tree; -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.FormInitListener; -import com.arsdigita.bebop.event.FormProcessListener; -import com.arsdigita.bebop.event.FormSectionEvent; -import com.arsdigita.bebop.event.FormSubmissionListener; -import com.arsdigita.bebop.event.TreeExpansionEvent; -import com.arsdigita.bebop.event.TreeExpansionListener; -import com.arsdigita.bebop.form.Option; -import com.arsdigita.bebop.form.SingleSelect; -import com.arsdigita.bebop.form.Submit; -import com.arsdigita.bebop.parameters.LongParameter; - -import com.arsdigita.cms.CMS; - -import org.librecms.contentsection.ContentSection; -import org.librecms.contentsection.Folder; - -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 org.apache.logging.log4j.LogManager; - -import org.apache.logging.log4j.Logger; -import org.arsdigita.cms.CMSConfig; -import org.libreccm.categorization.Category; -import org.libreccm.cdi.utils.CdiUtil; -import org.librecms.CmsConstants; -import org.librecms.contentsection.ContentSectionRepository; - -import java.util.List; - -/** - * A pane that contains a folder tree on the left and a folder manipulator on - * the right. - * - * @author David LutterKort <dlutter@redhat.com> - * @author Jens Pelzetter - */ -public class ItemSearchBrowsePane extends SimpleContainer implements Resettable, - TreeExpansionListener, - ChangeListener, - FormProcessListener, - FormSubmissionListener { - - private static final String CONTENT_TYPE_ID = "ct"; - private static final Logger LOGGER = LogManager.getLogger( - ItemSearchBrowsePane.class); - private final FolderSelectionModel folderSelectionModel; - private final FolderRequestLocal folderRequestLocal; - private final Tree tree; - private ItemSearchFolderBrowser folderBrowser; - private SingleSelect sectionSelect; - private SingleSelectionModel typeSelectionModel; - - public ItemSearchBrowsePane() { - - final LayoutPanel mainPanel = new LayoutPanel(); - - setClassAttr("sidebarNavPanel"); - setAttribute("navbar-title", - new GlobalizedMessage("cms.ui.folder_browser", - CmsConstants.CMS_BUNDLE) - .localize().toString()); - - final BoxPanel left = new BoxPanel(BoxPanel.VERTICAL); - - final Label label = new Label(new GlobalizedMessage( - "cms.ui.folder_browser", CmsConstants.CMS_BUNDLE)); - label.setClassAttr("heading"); - left.add(label); - - // As described in ticket 20540, some clients do not want the option to pick items from other - // subsites through the ItemSearchBrowsePane. A new parameter has been added to allow the - // administrator to pick between the old and new versions. - boolean linksOnlyInSameSubsite = CMSConfig.getConfig() - .isLinksOnlyInSameSubsite(); - LOGGER.debug("linksOnlyInSameSubsite value is {}", - linksOnlyInSameSubsite); - - tree = new Tree(new FolderTreeModelBuilder() { - - @Override - protected Category getRootFolder(final PageState state) { - final Category root = ItemSearchBrowsePane.this.getRootFolder( - state); - - if (null == root) { - return super.getRootFolder(state); - } - return root; - } - - }); - folderSelectionModel = createFolderSelectionModel(); - folderSelectionModel.addChangeListener(this); - folderRequestLocal = new FolderRequestLocal(folderSelectionModel); - - if (!linksOnlyInSameSubsite) { - // The client should be able to pick between the subsites - Form sectionForm = getSectionForm(); - add(sectionForm); - } - - tree.setSelectionModel(folderSelectionModel); - - tree.setClassAttr("navbar"); - tree.addTreeExpansionListener(this); - left.add(tree); - - left.setClassAttr("main"); - - final BoxPanel body = new BoxPanel(BoxPanel.VERTICAL); - folderBrowser = new ItemSearchFolderBrowser(folderSelectionModel); - body.add(folderBrowser); - body.add(folderBrowser.getPaginator()); - - mainPanel.setLeft(left); - mainPanel.setBody(body); - add(mainPanel); - } - - @Override - public boolean isVisible(final PageState state) { - // Always expand root node - if (tree.isCollapsed(Long.toString(getRootFolder(state).getObjectId()), - state)) { - tree.expand(Long.toString(getRootFolder(state).getObjectId()), - state); - } - - return super.isVisible(state); - } - - private Form getSectionForm() { - final Form sectionForm = new Form("isfbSectionForm", - new BoxPanel(BoxPanel.HORIZONTAL)); - sectionForm.setClassAttr("navbar"); - - sectionSelect = new SingleSelect(new LongParameter("isfbSection")); - final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); - final ContentSectionRepository sectionRepo = cdiUtil.findBean( - ContentSectionRepository.class); - final List sections = sectionRepo.findAll(); - - sections.forEach(section -> sectionSelect.addOption( - new Option(Long.toString(section.getObjectId()), - section.getDisplayName()))); - - sectionForm.addInitListener(new FormInitListener() { - - @Override - public void init(final FormSectionEvent event) { - final PageState state = event.getPageState(); - - if (null == sectionSelect.getValue(state)) { - ContentSection section = CMS.getContext(). - getContentSection(); - sectionSelect.setValue(state, section.getObjectId()); - } - } - - }); - - sectionForm.add(sectionSelect); - sectionForm.add(new Submit("Change Section")); - - return sectionForm; - } - - private Folder getRootFolder(final PageState state) { - LOGGER.debug("Getting the root folder."); - if (sectionSelect != null) { - // We have more than one subsite to choose between - final Long sectionId = (Long) sectionSelect.getValue(state); - if (LOGGER.isDebugEnabled()) { - if (null == sectionId) { - LOGGER.debug("Using default section"); - } else { - LOGGER.debug("Using section " + sectionId.toString()); - } - } - - if (null == sectionId) { - return null; - } - - final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); - final ContentSectionRepository sectionRepo = cdiUtil.findBean( - ContentSectionRepository.class); - final ContentSection section = sectionRepo.findById(sectionId); - - return section.getRootDocumentsFolder(); - } else { - return null; - } - } - - @Override - public void register(final Page page) { - super.register(page); - page.addComponentStateParam(this, folderSelectionModel - .getStateParameter()); - - // Only add the SingleSelect item if it exists - if (sectionSelect != null) { - page.addComponentStateParam(this, sectionSelect.getParameterModel()); - } - - // Save the state of the new item component -// p.addComponentStateParam(this, m_typeSel.getStateParameter()); - page.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(final ActionEvent event) { - final PageState state = event.getPageState(); - - if (state.isVisibleOnPage(ItemSearchBrowsePane.this)) { - showHideSegments(state); - } - } - - }); - } - - /** - * Show/hide segments based on access checks. - * - * @param state The page state - */ - private void showHideSegments(final PageState state) { - //Empty - } - - @Override - public void reset(final PageState state) { - //Empty - } - - public ItemSearchFolderBrowser getFolderBrowser() { - return folderBrowser; - } - - public final FolderSelectionModel getFolderSelectionModel() { - return folderSelectionModel; - } - - /** - * sets the current level of expansion of the folder tree and in the folder - * browser table - * - * @param state - * @param key - */ - protected void setSelectedFolder(final PageState state, - final String key) { - - //set the selected folder of the folder browser - folderBrowser.getFolderSelectionModel().setSelectedKey( - state, Long.parseLong(key)); - - //set the selected folder of the folder tree - folderSelectionModel.setSelectedKey(state, Long.parseLong(key)); - final Folder current = (Folder) folderSelectionModel.getSelectedObject( - state); - final Folder parent = current.getParentFolder(); - if (parent != null) { - final long parentId = parent.getObjectId(); - tree.expand(Long.toString(parentId), state); - } - } - - // Implement TreeExpansionListener - @Override - public void treeCollapsed(final TreeExpansionEvent event) { - final PageState state = event.getPageState(); - folderSelectionModel.setSelectedKey( - state, Long.parseLong((String) event.getNodeKey())); - } - - @Override - public void treeExpanded(final TreeExpansionEvent event) { - // Empty - } - - @Override - public void stateChanged(final ChangeEvent event) { - final PageState state = event.getPageState(); - final Folder current = (Folder) folderSelectionModel.getSelectedObject(state); - final Folder parent = current.getParentFolder(); - folderBrowser.getPaginator().reset(state); - if (parent != null) { - final Long parentId = parent.getObjectId(); - tree.expand(parentId.toString(), state); - } - } - - @Override - public void process(final FormSectionEvent event) { - final PageState state = event.getPageState(); - browseMode(state); - } - - @Override - public void submitted(final FormSectionEvent event) { - //Nothing - } - - private void browseMode(final PageState state) { - typeSelectionModel.clearSelection(state); - } - - private void newItemMode(final PageState state) { - //Nothing - } - - private FolderSelectionModel createFolderSelectionModel() { - return new FolderSelectionModel("folder") { - - @Override - protected Long getRootFolderID(final PageState state) { - final Folder root = getRootFolder(state); - - if (null == root) { - return super.getRootFolderID(state); - } - return root.getObjectId(); - } - - }; - } - -} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchFlatBrowsePane.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchFlatBrowsePane.java.todo deleted file mode 100644 index 57881e3b4..000000000 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchFlatBrowsePane.java.todo +++ /dev/null @@ -1,410 +0,0 @@ -/* - * - * 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.BoxPanel; -import com.arsdigita.bebop.Component; -import com.arsdigita.bebop.Form; -import com.arsdigita.bebop.FormData; -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.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.event.FormInitListener; -import com.arsdigita.bebop.event.FormProcessListener; -import com.arsdigita.bebop.event.FormSectionEvent; -import com.arsdigita.bebop.form.Submit; -import com.arsdigita.bebop.form.TextField; -import com.arsdigita.bebop.parameters.BigDecimalParameter; -import com.arsdigita.bebop.parameters.ParameterData; -import com.arsdigita.bebop.parameters.StringParameter; -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.globalization.GlobalizedMessage; -import com.arsdigita.toolbox.ui.LayoutPanel; -import com.arsdigita.util.LockableImpl; - -import org.arsdigita.cms.CMSConfig; -import org.libreccm.cdi.utils.CdiUtil; -import org.librecms.CmsConstants; -import org.librecms.contentsection.ContentItem; -import org.librecms.contentsection.ContentItemManager; -import org.librecms.contentsection.ContentItemRepository; -import org.librecms.contentsection.ContentType; -import org.librecms.contentsection.Folder; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -/** - * - * @author Jens Pelzetter - */ -public class ItemSearchFlatBrowsePane extends SimpleContainer { - - private static final String QUERY_PARAM = "queryStr"; - public static final String WIDGET_PARAM = "widget"; - public static final String SEARCHWIDGET_PARAM = "searchWidget"; - public static final String FILTER_SUBMIT = "filterSubmit"; - private final Table resultsTable; - private final Paginator paginator; - private final StringParameter queryParam; - private final QueryFieldsRequestLocal queryFields - = new QueryFieldsRequestLocal(); - private final static CMSConfig CMS_CONFIG = CMSConfig.getConfig(); - - public ItemSearchFlatBrowsePane() { - //super(name); - super(); - - setIdAttr("itemSearchFlatBrowse"); - - //final BoxPanel mainPanel = new BoxPanel(BoxPanel.VERTICAL); - final LayoutPanel mainPanel = new LayoutPanel(); - - queryParam = new StringParameter(QUERY_PARAM); - - mainPanel.setLeft(new FilterForm()); - - resultsTable = new ResultsTable(); - paginator = new Paginator( - (PaginationModelBuilder) resultsTable.getModelBuilder(), - CMS_CONFIG.getItemSearchFlatBrowsePanePageSize()); - final BoxPanel body = new BoxPanel(BoxPanel.VERTICAL); - body.add(paginator); - - body.add(resultsTable); - - mainPanel.setBody(body); - add(mainPanel); - } - - @Override - public void register(final Page page) { - super.register(page); - page.addComponentStateParam(this, queryParam); - } - - public void addQueryField(final String queryField) { - queryFields.addQueryField(queryField); - } - - void resetQueryFields() { - queryFields.reset(); - } - - private class ResultsTable extends Table { - - private static final String TABLE_COL_TITLE = "title"; - private static final String TABLE_COL_PLACE = "place"; - private static final String TABLE_COL_TYPE = "type"; - - public ResultsTable() { - super(); - setEmptyView(new Label(new GlobalizedMessage( - "cms.ui.item_search.flat.no_items", - CmsConstants.CMS_BUNDLE))); - setClassAttr("dataTable"); - - final TableColumnModel columnModel = getColumnModel(); - columnModel.add(new TableColumn( - 0, - new GlobalizedMessage("cms.ui.item_search.flat.title", - CmsConstants.CMS_BUNDLE).localize(), - TABLE_COL_TITLE)); - columnModel.add(new TableColumn( - 1, - new GlobalizedMessage("cms.ui.item_search.flat.place", - CmsConstants.CMS_BUNDLE).localize(), - TABLE_COL_PLACE)); - columnModel.add(new TableColumn( - 2, - new GlobalizedMessage("cms.ui.item_search.flat.type", - CmsConstants.CMS_BUNDLE).localize(), - TABLE_COL_TYPE)); - - setModelBuilder(new ResultsTableModelBuilder()); - - columnModel.get(0).setCellRenderer(new TitleCellRenderer()); - } - - } - - private class ResultsTableModelBuilder extends LockableImpl implements - TableModelBuilder, - PaginationModelBuilder { - - private final RequestLocal collection = new RequestLocal(); - - @Override - @SuppressWarnings("unchecked") - public TableModel makeModel(final Table table, final PageState state) { - - if (collection.get(state) == null) { - query(state); - } - - return new ResultsTableModel( - table, - state, - (List) collection.get(state)); - } - - @Override - public int getTotalSize(final Paginator paginator, - final PageState state) { - if (collection.get(state) == null) { - query(state); - } - return (int) ((List) collection.get(state)).size(); - } - - @Override - public boolean isVisible(final PageState state) { - return true; - } - - private void query(final PageState state) { - //Nothing - } - - } - - private class ResultsTableModel implements TableModel { - - private final Table table; - private final List collection; - private ContentItem currentItem; - private int index = -1; - - public ResultsTableModel(final Table table, - final PageState state, - final List collection) { - this.table = table; - - this.collection = collection; - - } - - @Override - public int getColumnCount() { - return table.getColumnModel().size(); - } - - @Override - public boolean nextRow() { - index++; - - if (collection != null && index < collection.size()) { - currentItem = collection.get(index); - return true; - } else { - return false; - } - } - - @Override - public Object getElementAt(final int columnIndex) { - switch (columnIndex) { - case 0: - return currentItem.getDisplayName(); - case 1: - return getItemPath(currentItem); - case 2: - if (currentItem.getContentType() == null) { - return ""; - } else { - return currentItem.getContentType().getDisplayName(); - } - default: - return null; - } - } - - private String getItemPath(final ContentItem item) { - final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); - final ContentItemManager itemManager = cdiUtil.findBean( - ContentItemManager.class); - - return itemManager.getItemPath(item); - } - - @Override - public Object getKeyAt(final int columnIndex) { - return currentItem.getObjectId(); - } - - } - - private class TitleCellRenderer extends LockableImpl - implements TableCellRenderer { - - @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 == null) { - return new Label("???"); - } - - final Link link = new Link(value.toString(), ""); - - final String widget = (String) state.getValue(new StringParameter( - WIDGET_PARAM)); - final String searchWidget = (String) state.getValue( - new StringParameter( - SEARCHWIDGET_PARAM)); - - final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); - final ContentItemRepository itemRepo = cdiUtil.findBean( - ContentItemRepository.class); - final Optional page = itemRepo.findById(Long.parseLong( - (String) key)); - - final boolean useURL = "true".equals(state.getValue( - new StringParameter( - ItemSearchPopup.URL_PARAM))); - - final String targetValue; - if (useURL) { - targetValue = ItemSearchPopup.getItemURL( - state.getRequest(), page.get().getObjectId()); - } else { - targetValue = key.toString(); - } - - final StringBuffer buffer = new StringBuffer(30); - buffer.append(String.format( - "window.opener.document.%s.value=\"%s\"; ", widget, - targetValue)); - if (searchWidget != null) { - buffer.append(String.format( - "window.opener.document.%s.value=\"%s\"; ", - searchWidget, - page.get().getDisplayName().replace("\"", "\\\""))); - } - - buffer.append("self.close(); return false;"); - - link.setOnClick(buffer.toString()); - - return link; - } - - } - - private class FilterForm extends Form implements FormInitListener, - FormProcessListener { - - private final Submit submit; - - public FilterForm() { - super("ItemSearchFlatBrowsePane"); - - add(new Label(new GlobalizedMessage( - "cms.ui.item_search.flat.filter", - CmsConstants.CMS_BUNDLE))); - final TextField filter = new TextField(new StringParameter( - QUERY_PARAM)); - add(filter); - - submit = new Submit(FILTER_SUBMIT, - new GlobalizedMessage( - "cms.ui.item_search.flat.filter.submit", - CmsConstants.CMS_BUNDLE)); - add(submit); - - addInitListener(this); - addProcessListener(this); - } - - @Override - public void init(final FormSectionEvent fse) throws FormProcessException { - final PageState state = fse.getPageState(); - final FormData data = fse.getFormData(); - - final String query = (String) data.get(QUERY_PARAM); - if ((query == null) || query.isEmpty()) { - data.setParameter( - QUERY_PARAM, - new ParameterData( - queryParam, - state.getValue( - new StringParameter(ItemSearchPopup.QUERY)))); - state.setValue(queryParam, - data.getParameter(QUERY_PARAM).getValue()); - } - } - - @Override - public void process(final FormSectionEvent fse) throws - FormProcessException { - final FormData data = fse.getFormData(); - final PageState state = fse.getPageState(); - - state.setValue(queryParam, data.get(QUERY_PARAM)); - state.setValue(new StringParameter(ItemSearchPopup.QUERY), - data.get(QUERY_PARAM)); - } - - } - - private class QueryFieldsRequestLocal extends RequestLocal { - - private List queryFields = new ArrayList<>(); - - @Override - protected Object initialValue(final PageState state) { - return new ArrayList<>(); - } - - public List getQueryFields() { - return queryFields; - } - - public void setQueryFields(final List queryFields) { - this.queryFields = queryFields; - } - - public void addQueryField(final String queryField) { - queryFields.add(queryField); - } - - public void reset() { - queryFields = new ArrayList<>(); - } - - } - -} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchFolderBrowser.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchFolderBrowser.java.todo deleted file mode 100755 index 740924617..000000000 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchFolderBrowser.java.todo +++ /dev/null @@ -1,457 +0,0 @@ -/* - * 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); - } - -} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchPage.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchPage.java.todo deleted file mode 100755 index 547c74ddf..000000000 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchPage.java.todo +++ /dev/null @@ -1,387 +0,0 @@ -/* - * 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.Component; -import com.arsdigita.bebop.PageState; -import com.arsdigita.bebop.SimpleContainer; -import com.arsdigita.bebop.TabbedPane; -import com.arsdigita.bebop.event.RequestEvent; -import com.arsdigita.bebop.event.RequestListener; -import com.arsdigita.bebop.parameters.BigDecimalParameter; -import com.arsdigita.bebop.parameters.BooleanParameter; -import com.arsdigita.bebop.parameters.IntegerParameter; -import com.arsdigita.bebop.parameters.LongParameter; -import com.arsdigita.bebop.parameters.StringParameter; -import com.arsdigita.cms.dispatcher.CMSPage; -import com.arsdigita.dispatcher.RequestContext; -import com.arsdigita.globalization.GlobalizedMessage; -import com.arsdigita.templating.PresentationManager; -import com.arsdigita.templating.Templating; -import com.arsdigita.util.UncheckedWrapperException; - -import org.libreccm.web.CcmApplication; - -import com.arsdigita.web.Web; -import com.arsdigita.xml.Document; - -import org.arsdigita.cms.CMSConfig; -import org.libreccm.cdi.utils.CdiUtil; -import org.libreccm.security.Shiro; -import org.librecms.CmsConstants; -import org.librecms.contentsection.ContentItemVersion; -import org.librecms.contentsection.ContentSection; -import org.librecms.contentsection.ContentSectionRepository; - -import java.io.IOException; -import java.math.BigDecimal; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - *

- * The Item Search page.

- * - * @author Scott Seago (scott@arsdigita.com) - * @author Sören Bernstein - * @author Jens Pelzetter (jens@jp-digital.de) - */ -public class ItemSearchPage extends CMSPage { - - public static final String CONTENT_SECTION = "section_id"; - - private static final boolean LIMIT_TO_CONTENT_SECTION = false; - private final static String XSL_CLASS = "CMS Admin"; - - private TabbedPane tabbedPane; - private ItemSearchFlatBrowsePane flatBrowsePane; - private ItemSearchBrowsePane browsePane; - private ItemSearchPopup searchPopup; -// private ItemSearchCreateItemPane m_create; - private final LongParameter sectionId; - private int lastTab; - private static final CMSConfig CONFIG = CMSConfig.getConfig(); - - /** - * Construct a new ItemSearchPage - */ - public ItemSearchPage() { - super(new GlobalizedMessage("cms.ui.item_search.page_title", - CmsConstants.CMS_BUNDLE).localize() - .toString(), - new SimpleContainer()); - - setClassAttr("cms-admin"); - - addGlobalStateParam( - new BigDecimalParameter(ItemSearch.SINGLE_TYPE_PARAM)); - addGlobalStateParam(new StringParameter(ItemSearchPopup.WIDGET_PARAM)); - addGlobalStateParam(new StringParameter("searchWidget")); - addGlobalStateParam(new StringParameter("publishWidget")); - addGlobalStateParam(new StringParameter("defaultCreationFolder")); - addGlobalStateParam(new IntegerParameter("lastTab")); - addGlobalStateParam(new BooleanParameter("disableCreatePane")); - addGlobalStateParam(new BooleanParameter("editAfterCreate")); - addGlobalStateParam(new StringParameter("queryField")); - sectionId = new LongParameter(CONTENT_SECTION); - addGlobalStateParam(sectionId); - - flatBrowsePane = getFlatBrowsePane(); - browsePane = getBrowsePane(); - searchPopup = getSearchPane(); -// m_create = getCreatePane(); - - tabbedPane = createTabbedPane(); - tabbedPane.setIdAttr("page-body"); - add(tabbedPane); - - addRequestListener(new RequestListener() { - - public void pageRequested(final RequestEvent event) { - final PageState state = event.getPageState(); - - final String query = (String) state.getValue( - new StringParameter(ItemSearchPopup.QUERY)); - final Boolean disableCreatePane = (Boolean) state.getValue( - new BooleanParameter("disableCreatePane")); - - BigDecimal typeParam = (BigDecimal) state.getValue( - new BigDecimalParameter(ItemSearch.SINGLE_TYPE_PARAM)); - if ((typeParam == null) || disableCreatePane) { -// tabbedPane.setTabVisible(state, m_create, false); -// m_create.setVisible(state, false); - } else { -// tabbedPane.setTabVisible(state, m_create, true); -// m_create.setVisible(state, true); - } - - if (state.getValue(new IntegerParameter("lastTab")) == null) { - if ((query == null) || query.isEmpty()) { - tabbedPane.setSelectedIndex(state, 1); - } else { - tabbedPane.setSelectedIndex(state, 0); - } - -// m_tabbedPane.setTabVisible(state, m_create, false); -// m_create.setVisible(state, false); - } - - state.setValue(new IntegerParameter("lastTab"), tabbedPane - .getSelectedIndex(state)); - - if (state.getValue(new StringParameter("defaultCreationFolder")) - != null) { -// m_create.setDefaultFolder((String) state.getValue( -// new StringParameter("defaultCreationFolder"))); - } - - if (state.getValue(new BooleanParameter("editAfterCreate")) - != null) { -// m_create.setEditAfterCreate((Boolean) state.getValue( -// new BooleanParameter("editAfterCreate"))); - } - - if (state.getValue(new StringParameter("queryField")) == null) { - //Because of Bebops silly stateful behaviour we have to do this... - flatBrowsePane.resetQueryFields(); - } else { - flatBrowsePane.addQueryField((String) state.getValue( - new StringParameter("queryField"))); - } - -// if (m_lastTab != m_tabbedPane.getSelectedIndex(state)) { -// m_lastTab = m_tabbedPane.getSelectedIndex(state); -// return; -// } -// -// //If create pane is selected do nothing (else we don't stay in the create pane) -// if (m_tabbedPane.getCurrentPane(state) == m_create) { -// return; -// } -// -// if ((query == null) || query.isEmpty()) { -// m_tabbedPane.setSelectedIndex(state, 1); -// } else { -// m_tabbedPane.setSelectedIndex(state, 1); -// } -// if (m_tabbedPane.getCurrentPane(state) == m_create) { -// m_tabbedPane.setTabVisible(state, m_create, false); -// m_create.setVisible(state, false); -// } -// -// m_lastTab = m_tabbedPane.getSelectedIndex(state); - } - - }); - -// m_tabbedPane.addActionListener(new ActionListener() { -// -// public void actionPerformed(final ActionEvent event) { -// final PageState state = event.getPageState(); -// -// } -// -// }); -// m_flatBrowse.addProcessListener(new FormProcessListener() { -// -// public void process(final FormSectionEvent fse) throws FormProcessException { -// if (m_flatBrowse.getSubmit().isSelected(fse.getPageState())) { -// enableCreatePane(fse.getPageState()); -// } -// } -// -// }); - } // END constructor - - /** - * Creates, and then caches, the Browse pane. - * - * Overriding this method to return null will prevent this tab from - * appearing. Note: not implemented yet. - * - * @return - */ - protected ItemSearchBrowsePane getBrowsePane() { - if (browsePane == null) { - browsePane = new ItemSearchBrowsePane(); - } - - return browsePane; - } - - protected ItemSearchFlatBrowsePane getFlatBrowsePane() { - if (flatBrowsePane == null) { - //m_flatBrowse = new ItemSearchFlatBrowsePane("flatBrowse"); - flatBrowsePane = new ItemSearchFlatBrowsePane(); - } - - return flatBrowsePane; - } - - /** - * Creates, and then caches, the Creation pane. Overriding this method to - * return null will prevent this tab from appearing. - */ - protected ItemSearchPopup getSearchPane() { - if (searchPopup == null) { - // Always search in every content section -// m_search = new ItemSearchPopup(ContentItem.DRAFT, CMS.getConfig().limitToContentSection()); - searchPopup = new ItemSearchPopup(ContentItemVersion.DRAFT - .toString(), - LIMIT_TO_CONTENT_SECTION); - } - - return searchPopup; - } - -// protected ItemSearchCreateItemPane getCreatePane() { -// if (m_create == null) { -// m_create = new ItemSearchCreateItemPane(this); -// } -// -// return m_create; -// } - /** - * Created the TabbedPane to use for this page. - * - * Sets the class attribute for this tabbed pane. The default implementation - * uses a {@link com.arsdigita.bebop.TabbedPane} and sets the class - * attribute to "CMS Admin." This implementation also adds tasks, content - * sections, and search 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() { - TabbedPane pane = new TabbedPane(); - pane.setClassAttr(XSL_CLASS); - - addToPane(pane, "flatBrowse", getFlatBrowsePane()); - addToPane(pane, "browse", getBrowsePane()); - addToPane(pane, "search", getSearchPane()); -// addToPane(pane, "create", getCreatePane()); - - if ("browse".equals(CONFIG.getItemSearchDefaultTab())) { - pane.setDefaultPane(browsePane); - } - if ("search".equals(CONFIG.getItemSearchDefaultTab())) { - pane.setDefaultPane(searchPopup); - } - - //pane.setDefaultPane(m_flatBrowse); - pane.setDefaultPane(browsePane); - - return pane; - } - - /** - * 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(final TabbedPane pane, - final String tabName, - final Component comp) { - if (comp != null) { - pane.addTab(new GlobalizedMessage(String.format( - "cms.ui.item_search.%s", tabName), CmsConstants.CMS_BUNDLE) - .localize().toString(), - comp); - } - } - - /** - * This strange voodoo from Dan. No idea what it does. - * - * @throws java.io.IOException - * @throws javax.servlet.ServletException - */ - @Override - public void dispatch(final HttpServletRequest request, - final HttpServletResponse response, - final RequestContext actx) { - - final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); - final Shiro shiro = cdiUtil.findBean(Shiro.class); - - shiro.getSystemUser().execute(new Runnable() { - - @Override - public void run() { - - final CcmApplication application = Web.getWebContext() - .getApplication(); - - final CdiUtil util = CdiUtil.createCdiUtil(); - final ContentSectionRepository sectionRepo = util.findBean( - ContentSectionRepository.class); - - final ContentSection section; - if (application instanceof ContentSection) { - section = (ContentSection) application; - } else { - section = sectionRepo.findById(Long.parseLong( - (String) sectionId.transformValue(request))); - } - -// Web.getWebContext().setContentSection(section); - - final Document doc; - try { - doc = buildDocument(request, response); - } catch (ServletException ex) { - throw new UncheckedWrapperException(ex); - } - final PresentationManager pm = Templating - .getPresentationManager(); - - pm.servePage(doc, request, response); - } - - }); - } - - protected void setTabActive(final PageState state, final Component component, - final boolean value) { - tabbedPane.setTabVisible(state, component, value); - } - - protected void setTabActive(final PageState state, final int index, - final boolean value) { - tabbedPane.setTabVisible(state, index, value); - } - -// protected void setDefaultCreationFolder(final Folder folder) { -// m_create.setDefaultFolder(folder.getOID().toString()); -// } -// -// protected void setEditAfterCreate(final boolean editAfterCreate) { -// m_create.setEditAfterCreate(editAfterCreate); -// } - -} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchPopup.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchPopup.java.todo deleted file mode 100755 index 31f335267..000000000 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ItemSearchPopup.java.todo +++ /dev/null @@ -1,200 +0,0 @@ -/* - * 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.Component; -import com.arsdigita.bebop.Page; -import com.arsdigita.bebop.PageState; -import com.arsdigita.bebop.parameters.StringParameter; -import com.arsdigita.globalization.GlobalizedMessage; -import com.arsdigita.search.SearchConstants; - -import org.librecms.contentsection.ContentItem; - -import com.arsdigita.xml.Element; - -import com.arsdigita.search.ui.QueryGenerator; -import com.arsdigita.search.ui.ResultsPane; -import com.arsdigita.web.Web; - -import org.libreccm.core.CcmObject; -import org.librecms.CmsConstants; - -import java.math.BigDecimal; - -import javax.servlet.http.HttpServletRequest; - -/** - * An extension of {@link ItemSearch} for use in a popup search window. The - * display of results is altered so that selecting a result closes the window & - * passes the id of the selected item back to the opener. - * - * @author Stanislav Freidin (sfreidin@arsdigita.com) - * @author Jens Pelzetter - */ -public class ItemSearchPopup extends ItemSearch { - -// private static final org.apache.log4j.Logger s_log = org.apache.log4j.Logger.getLogger( -// ItemSearchPopup.class); - public static final String WIDGET_PARAM = "widget"; - public static final String URL_PARAM = "useURL"; - public static final String QUERY = "query"; - - /** - * Construct a new ItemSearchPopup component - * - * @param context the context for the retrieved items. Should - * be {@link ContentItem#DRAFT} or - * {@link ContentItem#LIVE} - * @param limitToContentSection limit the search to the current content - * section - */ - public ItemSearchPopup(final String context, - final boolean limitToContentSection) { - super(context, limitToContentSection); - } - - // Hide results by default - @Override - public void register(final Page page) { - super.register(page); - page.addGlobalStateParam(new StringParameter(WIDGET_PARAM)); - page.addGlobalStateParam(new StringParameter(URL_PARAM)); - page.addGlobalStateParam(new StringParameter(QUERY)); - } - - @Override - protected ItemSearchSection createSearchSection( - final String context, final boolean limitToContentSection) { - return new ItemSearchSectionPopup(context, limitToContentSection); - } - - private static class ItemSearchSectionPopup extends ItemSearchSection { - - public ItemSearchSectionPopup(final String context, - final boolean limitToContentSection) { - super(context, limitToContentSection); - } - - @Override - protected Component createResultsPane(final QueryGenerator generator) { - return new PopupResultsPane(generator); - } - - } - - /** - * The default context is Live.No need to append &context=live explicitly. - * - * @param request - * @param objectId - * - * @return - */ - public static String getItemURL(final HttpServletRequest request, - final Long objectId) { - // redirect doesn't use /ccm prefix for some reason, so just returning the raw string. - //ParameterMap map = new ParameterMap(); - //map.setParameter("oid", oid.toString()); - //return URL.there(request, "/redirect/", map).toString(); - // Always link directly to the live version. - if (Web.getWebappContextPath() == null) { - return "/redirect/?oid=" + objectId.toString(); - } else { - return Web.getWebappContextPath() + "/redirect/?oid=" + objectId - .toString(); - } - } - - private static class PopupResultsPane extends ResultsPane { - - public PopupResultsPane(final QueryGenerator generator) { - super(generator); - setRelativeURLs(true); - setSearchHelpMsg(new GlobalizedMessage("cms.ui.search.help", - CmsConstants.CMS_BUNDLE)); - setNoResultsMsg(new GlobalizedMessage("cms.ui.search.no_results", - CmsConstants.CMS_BUNDLE)); - } - - @Override - protected Element generateDocumentXML(final PageState state, - final CcmObject doc) { - final Element element = super.generateDocumentXML(state, doc); - - element.addAttribute("class", "jsButton"); - - final String widget = (String) state.getValue(new StringParameter( - WIDGET_PARAM)); - final String searchWidget = (String) state.getValue( - new StringParameter("searchWidget")); - - final boolean useURL = "true".equals(state.getValue( - new StringParameter(URL_PARAM))); - - String fillString; - if (useURL) { - fillString = getItemURL(state.getRequest(), doc.getObjectId()); - } else { - fillString = Long.toString(doc.getObjectId()); - } - - final String title = doc.getDisplayName(); - - final Element jsLabel = new Element( - SearchConstants.XML_PREFIX + "jsAction", - SearchConstants.XML_NS); - jsLabel.addAttribute( - "name", "fillItem" + Long.toString(doc.getObjectId()) + "()"); - jsLabel.setText(generateJSLabel(doc.getObjectId(), - widget, - searchWidget, - fillString, - title)); - jsLabel.addAttribute("action", - String.format( - "window.opener.document.%s.value = \"%s\"; self.close(); return false;", - widget, - fillString)); - element.addContent(jsLabel); - - return element; - } - - private String generateJSLabel(final Long docId, - final String widget, - final String searchWidget, - final String fill, - final String title) { - return " "; - } - - } - -} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/AssetSearchWidget.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/AssetSearchWidget.java index c594b8862..95a91073a 100644 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/AssetSearchWidget.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/AssetSearchWidget.java @@ -37,7 +37,7 @@ import java.util.ResourceBundle; /** * A widget for selecting an asset. The widget does not contain any other * widgets, only the information required to create an HTML/JavaScript dialog - * for selecting an asset. To get the dialog the + * for selecting an asset. To create the dialog the * {@link org.librecms.contentsection.rs.Assets} class can be used which * provides several methods for getting the assets of an content section. * @@ -80,7 +80,7 @@ public class AssetSearchWidget extends Widget { CMS.CMS_XML_NS); widget.addAttribute("name", getName()); - + if (type != null) { widget.addAttribute("asset-type", type.getName()); } @@ -101,10 +101,10 @@ public class AssetSearchWidget extends Widget { final Asset asset = assetRepo .findById(value) .orElseThrow(() -> new IllegalArgumentException(String.format( - "No asset with ID %d in the database.", value))); + "No Asset with ID %d in the database.", value))); - final Element selected = widget.newChildElement( - "cms:selected-asset", CMS.CMS_XML_NS); + final Element selected = widget + .newChildElement("cms:selected-asset", CMS.CMS_XML_NS); selected.addAttribute("assetId", Long.toString(asset.getObjectId())); selected.addAttribute( diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/ItemSearchWidget.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/ItemSearchWidget.java new file mode 100644 index 000000000..1ca0cd220 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/ItemSearchWidget.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2017 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 com.arsdigita.cms.ui.assets; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.form.Widget; +import com.arsdigita.bebop.parameters.LongParameter; +import com.arsdigita.cms.CMS; +import com.arsdigita.xml.Element; + +import org.libreccm.cdi.utils.CdiUtil; +import org.libreccm.l10n.GlobalizationHelper; +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentItemRepository; +import org.librecms.contentsection.ContentSection; +import org.librecms.contenttypes.ContentTypeInfo; +import org.librecms.contenttypes.ContentTypesManager; + +import java.util.ResourceBundle; + +/** + * + * @author Jens Pelzetter + */ +public class ItemSearchWidget extends Widget { + + private Class type; + + public ItemSearchWidget(final String name) { + super(new LongParameter(name)); + } + + @Override + public boolean isCompound() { + return true; + } + + @Override + protected String getType() { + return "item-search-widget"; + } + + @Override + protected String getElementTag() { + return "cms:item-search-widget"; + } + + @Override + public void generateWidget(final PageState state, + final Element parent) { + + final Element widget = parent.newChildElement(getElementTag(), + CMS.CMS_XML_NS); + + widget.addAttribute("name", getName()); + + if (type != null) { + widget.addAttribute("asset-type", type.getName()); + } + + final ContentSection section = CMS.getContext().getContentSection(); + widget.addAttribute("content-section", section.getLabel()); + + final Long value = (Long) getValue(state); + if (value != null) { + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final ContentItemRepository itemRepo = cdiUtil + .findBean(ContentItemRepository.class); + final ContentTypesManager typesManager = cdiUtil + .findBean(ContentTypesManager.class); + final GlobalizationHelper globalizationHelper = cdiUtil + .findBean(GlobalizationHelper.class); + + final ContentItem item = itemRepo + .findById(value) + .orElseThrow(() -> new IllegalArgumentException(String + .format("No ContentItem with ID %d in the database.", value))); + + final Element selected = widget + .newChildElement("cms:selected-content-item", CMS.CMS_XML_NS); + selected.addAttribute("contentItemId", + Long.toString(item.getObjectId())); + selected.addAttribute("name", item.getDisplayName()); + selected.addAttribute( + "title", + globalizationHelper.getValueFromLocalizedString(item.getTitle())); + final ContentTypeInfo typeInfo = typesManager + .getContentTypeInfo(item.getClass()); + final ResourceBundle bundle = ResourceBundle + .getBundle(typeInfo.getLabelBundle(), + globalizationHelper.getNegotiatedLocale()); + final String typeLabel = bundle.getString(typeInfo.getLabelKey()); + selected.addAttribute("type", typeLabel); + + exportAttributes(widget); + + } + + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/relatedinfo/InternalLinkAddForm.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/relatedinfo/InternalLinkAddForm.java new file mode 100644 index 000000000..27abc6f24 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/relatedinfo/InternalLinkAddForm.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2017 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 com.arsdigita.cms.ui.authoring.assets.relatedinfo; + +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.SaveCancelSection; +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.form.TextArea; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.ui.assets.ItemSearchWidget; +import com.arsdigita.cms.ui.authoring.assets.AttachmentListSelectionModel; + +/** + * + * @author Jens Pelzetter + */ +public class InternalLinkAddForm + extends Form + implements FormInitListener, + FormProcessListener, + FormSubmissionListener { + + private final RelatedInfoStep relatedInfoStep; + private final ItemSelectionModel itemSelectionModel; + private final AttachmentListSelectionModel listSelectionModel; + private final StringParameter selectedLanguageParam; + + private final TextField titleField; + private final TextArea descriptionArea; + private final ItemSearchWidget itemSearchWidget; + private final SaveCancelSection saveCancelSection; + + public InternalLinkAddForm( + final RelatedInfoStep relatedInfoStep, + final ItemSelectionModel itemSelectionModel, + final AttachmentListSelectionModel listSelectionModel, + final StringParameter selectedLanguageParam) { + + super("relatedinfo-attach-internallink-form"); + + this.relatedInfoStep = relatedInfoStep; + this.itemSelectionModel = itemSelectionModel; + this.listSelectionModel = listSelectionModel; + this.selectedLanguageParam = selectedLanguageParam; + + titleField = new TextField("link-title"); + descriptionArea = new TextArea("link-description"); + itemSearchWidget = new ItemSearchWidget("link-item-search"); + saveCancelSection = new SaveCancelSection(); + } + + @Override + public void init(FormSectionEvent e) throws FormProcessException { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public void process(FormSectionEvent e) throws FormProcessException { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public void submitted(FormSectionEvent e) throws FormProcessException { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/relatedinfo/RelatedInfoAttachAssetForm.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/relatedinfo/RelatedInfoAttachAssetForm.java index 447410ff9..16cbd1b54 100644 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/relatedinfo/RelatedInfoAttachAssetForm.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/relatedinfo/RelatedInfoAttachAssetForm.java @@ -36,7 +36,6 @@ import org.libreccm.core.UnexpectedErrorException; import org.librecms.contentsection.Asset; import org.librecms.contentsection.AssetRepository; import org.librecms.contentsection.AttachmentList; -import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ItemAttachmentManager; /** @@ -63,7 +62,7 @@ class RelatedInfoAttachAssetForm final AttachmentListSelectionModel listSelectionModel, final StringParameter selectedLangugeParam) { - super("relatedinfo-attachasset-form"); + super("relatedinfo-attach-asset-form"); this.relatedInfoStep = relatedInfoStep; this.itemSelectionModel = itemSelectionModel; diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/Asset.java b/ccm-cms/src/main/java/org/librecms/contentsection/Asset.java index 7ae983f53..2887b2bab 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/Asset.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/Asset.java @@ -195,7 +195,7 @@ import static org.librecms.CmsConstants.*; + "JOIN a.title.values t " + "JOIN a.categories c " + "LEFT JOIN a.permissions p " - + "WHERE LOWER(t) LIKE CONCAT('%s', :title, '%s') " + + "WHERE LOWER(t) LIKE CONCAT('%', :title, '%') " + "AND c.category.section = :section " + "AND (" + " (" diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItem.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItem.java index 8eb1b1c92..381435267 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItem.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItem.java @@ -170,6 +170,94 @@ import static org.librecms.CmsConstants.*; + " OR true = :isSystemUser OR true = :isAdmin" + " )") , + @NamedQuery( + name = "ContentItem.findByContentSection", + query = "SELECT DISTINCT i " + + "FROM ContentItem i " + + "JOIN i.contentType t " + + "LEFT JOIN i.permissions p " + + "WHERE t.contentSection = :section " + + "AND (" + + " (" + + " p.grantee IN :roles " + + " AND p.grantedPrivileges = " + + " (CASE WHEN i.version = 'DRAFT' " + + " THEN '" + ItemPrivileges.PREVIEW + "' " + + " ELSE '" + ItemPrivileges.VIEW_PUBLISHED + + "' " + + " END" + + " )" + + " )" + + " OR true = :isSystemUser OR true = :isAdmin" + + ")") + , + @NamedQuery( + name = "ContentItem.findByNameAndContentSection", + query = "SELECT DISTINCT i " + + "FROM ContentItem i " + + "JOIN i.contentType t " + + "LEFT JOIN i.permissions p " + + "WHERE t.contentSection = :section " + + "AND lower(i.displayName) LIKE CONCAT('%', :name, '%s') " + + "AND (" + + " (" + + " p.grantee IN :roles " + + " AND p.grantedPrivileges = " + + " (CASE WHEN i.version = 'DRAFT' " + + " THEN '" + ItemPrivileges.PREVIEW + "' " + + " ELSE '" + ItemPrivileges.VIEW_PUBLISHED + + "' " + + " END" + + " )" + + " )" + + " OR true = :isSystemUser OR true = :isAdmin" + + ")") + , + @NamedQuery( + name = "ContentItem.findByTypeAndContentSection", + query = "SELECT DISTINCT i " + + "FROM ContentItem i " + + "JOIN i.contentType t " + + "LEFT JOIN i.permissions p " + + "WHERE t.contentSection = :section " + + "AND TYPE(i) = :type " + + "AND (" + + " (" + + " p.grantee IN :roles " + + " AND p.grantedPrivileges = " + + " (CASE WHEN i.version = 'DRAFT' " + + " THEN '" + ItemPrivileges.PREVIEW + "' " + + " ELSE '" + ItemPrivileges.VIEW_PUBLISHED + + "' " + + " END" + + " )" + + " )" + + " OR true = :isSystemUser OR true = :isAdmin" + + ")") + , + @NamedQuery( + name = "ContentItem.findByNameAndTypeAndContentSection", + query = "SELECT DISTINCT i " + + "FROM ContentItem i " + + "JOIN i.contentType t " + + "LEFT JOIN i.permissions p " + + "WHERE t.contentSection = :section " + + "AND TYPE(i) = :type " + + "AND lower(i.displayName) LIKE CONCAT('%', :name, '%s') " + + "AND (" + + " (" + + " p.grantee IN :roles " + + " AND p.grantedPrivileges = " + + " (CASE WHEN i.version = 'DRAFT' " + + " THEN '" + ItemPrivileges.PREVIEW + "' " + + " ELSE '" + ItemPrivileges.VIEW_PUBLISHED + + "' " + + " END" + + " )" + + " )" + + " OR true = :isSystemUser OR true = :isAdmin" + + ")") + , @NamedQuery( name = "ContentItem.findByFolder", query @@ -304,6 +392,53 @@ import static org.librecms.CmsConstants.*; + " )" ) , + @NamedQuery( + name = "ContentItem.filterByFolderAndType", + query = "SELECT DISTINCT i " + + "FROM ContentItem i " + + "JOIN i.categories c " + + "LEFT JOIN i.permissions p " + + "WHERE c.category = :folder " + + "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER + "' " + + "AND TYPE(i) = :type " + + "AND (" + + " (" + + " p.grantee IN :roles " + + " AND p.grantedPrivilege = " + + " (CASE WHEN i.version = 'DRAFT' " + + " THEN '" + ItemPrivileges.PREVIEW + "' " + + " ELSE '" + ItemPrivileges.VIEW_PUBLISHED + "' " + + " END" + + " )" + + " )" + + " OR true = :isSystemUser OR true = :isAdmin" + + " ) " + + "ORDER BY i.displayName") + , + @NamedQuery( + name = "ContentItem.filterByFolderAndTypeAndName", + query = "SELECT DISTINCT i " + + "FROM ContentItem i " + + "JOIN i.categories c " + + "LEFT JOIN i.permissions p " + + "WHERE c.category = :folder " + + "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER + "' " + + "AND LOWER(i.displayName) LIKE CONCAT(LOWER(:name), '%') " + + "AND TYPE(i) = :type" + + "AND (" + + " (" + + " p.grantee IN :roles " + + " AND p.grantedPrivilege = " + + " (CASE WHEN i.version = 'DRAFT' " + + " THEN '" + ItemPrivileges.PREVIEW + "' " + + " ELSE '" + ItemPrivileges.VIEW_PUBLISHED + "' " + + " END" + + " )" + + " )" + + " OR true = :isSystemUser OR true = :isAdmin" + + " ) " + + "ORDER BY i.displayName") + , @NamedQuery( name = "ContentItem.hasLiveVersion", query = "SELECT (CASE WHEN COUNT(i) > 0 THEN true ELSE false END) " diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemRepository.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemRepository.java index ed21394df..13d41dac6 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemRepository.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemRepository.java @@ -238,6 +238,68 @@ public class ContentItemRepository } } + @Transactional(Transactional.TxType.REQUIRED) + @SuppressWarnings("unchecked") + public List findByContentSection( + final ContentSection section) { + + final TypedQuery query = getEntityManager() + .createNamedQuery("ContentItem.findByContentSection", + ContentItem.class); + query.setParameter("section", section); + setAuthorizationParameters(query); + + return (List) query.getResultList(); + } + + @Transactional(Transactional.TxType.REQUIRED) + @SuppressWarnings("unchecked") + public List findByNameAndContentSection( + final String name, final ContentSection section) { + + final TypedQuery query = getEntityManager() + .createNamedQuery("ContentItem.findByNameAndContentSection", + ContentItem.class); + query.setParameter("section", section); + query.setParameter("name", name); + setAuthorizationParameters(query); + + return (List) query.getResultList(); + } + + @Transactional(Transactional.TxType.REQUIRED) + @SuppressWarnings("unchecked") + public List findByTypeAndContentSection( + final Class type, final ContentSection section) { + + final TypedQuery query = getEntityManager() + .createNamedQuery("ContentItem.findByNameAndContentSection", + ContentItem.class); + query.setParameter("section", section); + query.setParameter("type", type); + setAuthorizationParameters(query); + + return (List) query.getResultList(); + } + + @Transactional(Transactional.TxType.REQUIRED) + @SuppressWarnings("unchecked") + public List findByNameAndTypeAndContentSection( + final String name, + final Class type, + final ContentSection section) { + + final TypedQuery query = getEntityManager() + .createNamedQuery("ContentItem.findByNameAndContentSection", + ContentItem.class); + query.setParameter("section", section); + query.setParameter("name", name); + query.setParameter("type", type); + setAuthorizationParameters(query); + + return (List) query.getResultList(); + } + /** * Finds all content items of a specific type. * @@ -357,6 +419,39 @@ public class ContentItemRepository return query.getResultList(); } + @Transactional(Transactional.TxType.REQUIRED) + public List filterByFolderAndType( + final Category folder, + final Class type) { + + final TypedQuery query = getEntityManager() + .createNamedQuery("ContentItem.filterByFolderAndType", + ContentItem.class); + query.setParameter("folder", folder); + query.setParameter("type", type); + setAuthorizationParameters(query); + + return query.getResultList(); + } + + @Transactional(Transactional.TxType.REQUIRED) + public List filterByFolderAndTypeAndName( + final Category folder, + final Class type, + final String name) { + + + final TypedQuery query = getEntityManager() + .createNamedQuery("ContentItem.filterByFolderAndTypeAndName", + ContentItem.class); + query.setParameter("folder", folder); + query.setParameter("name", name); + query.setParameter("type", type); + setAuthorizationParameters(query); + + return query.getResultList(); + } + /** * Counts a items in a specific folder whose {@link CcmObject#displayName} * starts with the provided pattern. diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Assets.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Assets.java index 37ba59c9a..6d9cff2af 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Assets.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Assets.java @@ -18,6 +18,7 @@ */ package org.librecms.contentsection.rs; +import com.arsdigita.cms.ui.assets.AssetSearchWidget; import com.arsdigita.kernel.KernelConfig; import org.libreccm.l10n.GlobalizationHelper; @@ -52,7 +53,9 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; /** - * + * Provides a Web Service (build using JAX-RS). Used for example by the + * {@link AssetSearchWidget}. + * * @author Jens Pelzetter */ @RequestScoped @@ -178,7 +181,7 @@ public class Assets { } else { final Class assetType = toAssetTypeClass(type); assets = assetRepo.findByTitleAndTypeAndContentSection( - type, + query, assetType, contentSection); } diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/ContentItems.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/ContentItems.java new file mode 100644 index 000000000..d08f9a9e2 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/ContentItems.java @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2017 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.rs; + +import org.libreccm.l10n.GlobalizationHelper; +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentItemManager; +import org.librecms.contentsection.ContentItemRepository; +import org.librecms.contentsection.ContentSection; +import org.librecms.contentsection.ContentSectionRepository; +import org.librecms.contentsection.Folder; +import org.librecms.contentsection.FolderManager; +import org.librecms.contentsection.FolderRepository; +import org.librecms.contentsection.FolderType; +import org.librecms.contenttypes.ContentTypeInfo; +import org.librecms.contenttypes.ContentTypesManager; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.ResourceBundle; +import java.util.stream.Collectors; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.transaction.Transactional; +import javax.ws.rs.GET; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; + +/** + * Provides a Web Service (build using JAX-RS). Used for example by the + * {@link ItemSearchWidget}. + * + * @author Jens Pelzetter + */ +@RequestScoped +@Path("/{content-section}/assets/") +public class ContentItems { + + @Inject + private ContentSectionRepository sectionRepo; + + @Inject + private FolderRepository folderRepo; + + @Inject + private FolderManager folderManager; + + @Inject + private ContentItemRepository itemRepo; + + @Inject + private ContentItemManager itemManager; + + @Inject + private ContentTypesManager itemTypesManager; + + @Inject + private GlobalizationHelper globalizationHelper; + + private Class toContentItemTypeClass( + final String type) { + + final Class clazz; + try { + clazz = Class.forName(type); + } catch (ClassNotFoundException ex) { + throw new IllegalArgumentException(String.format( + "Type '%s' is not a valid class.", + type)); + } + + if (ContentItem.class.isAssignableFrom(clazz)) { + @SuppressWarnings("unchecked") + final Class typeClass + = (Class) clazz; + return typeClass; + } else { + throw new IllegalArgumentException(String.format( + "Type '%s is not a subclass of '%s'.", + type, + ContentItem.class.getName())); + } + } + + private Map createItemMapEntry(final Folder folder) { + + final Map result = new HashMap<>(); + + result.put("title", + folder + .getTitle().getValue(globalizationHelper + .getNegotiatedLocale())); + + result.put("type", + Folder.class.getName()); + result.put("place", ""); + + return result; + } + + private Map createItemMapEntry(final ContentItem item) { + + final Map result = new HashMap<>(); + + result.put("itemId", + Long.toString(item.getObjectId())); + + result.put("title", + item.getTitle().getValue(globalizationHelper + .getNegotiatedLocale())); + + result.put("type", + item.getClass().getName()); + + final ContentTypeInfo typeInfo = itemTypesManager + .getContentTypeInfo(item.getClass()); + final ResourceBundle bundle = ResourceBundle + .getBundle(typeInfo.getLabelBundle(), + globalizationHelper.getNegotiatedLocale()); + result.put("typeLabel", bundle.getString(typeInfo.getLabelKey())); + + final Optional itemFolder = itemManager.getItemFolder(item); + if (itemFolder.isPresent()) { + result.put("place", + folderManager.getFolderPath(itemFolder.get())); + } else { + result.put("place", ""); + } + + return result; + } + + @GET + @Path("/") + @Produces("text/json; charset=utf-8") + @Transactional(Transactional.TxType.REQUIRED) + public List> findItems( + @PathParam("content-section") final String section, + @QueryParam("query") final String query, + @QueryParam("type") final String type) { + + final ContentSection contentSection = sectionRepo + .findByLabel(section) + .orElseThrow(() -> new NotFoundException( + String.format("No content section '%s' found.", section))); + + final List items; + if ((query == null || query.trim().isEmpty()) + && (type == null || type.trim().isEmpty())) { + items = itemRepo + .findByContentSection(contentSection); + + } else if ((query != null && !query.trim().isEmpty()) + && (type == null || type.trim().isEmpty())) { + + items = itemRepo.findByNameAndContentSection(query, + contentSection); + } else if ((query == null || query.trim().isEmpty()) + && (type != null && !type.trim().isEmpty())) { + + final Class itemType + = toContentItemTypeClass(type); + items = itemRepo.findByTypeAndContentSection(itemType, + contentSection); + } else { + final Class itemType + = toContentItemTypeClass(type); + items = itemRepo.findByNameAndTypeAndContentSection( + query, + itemType, + contentSection); + } + + return items + .stream() + .map(item -> createItemMapEntry(item)) + .collect(Collectors.toList()); + } + + @GET + @Path("/folders") + @Produces("text/json; charset=utf-8") + @Transactional(Transactional.TxType.REQUIRED) + public List> findItemsInRootFolder( + @PathParam("content-section") final String section, + @QueryParam("query") final String query, + @QueryParam("type") final String type) { + + final ContentSection contentSection = sectionRepo + .findByLabel(section) + .orElseThrow(() -> new NotFoundException(String + .format("No content section with '%s' found.", section))); + + final Folder folder = contentSection.getRootDocumentsFolder(); + + return findItemsInFolder(folder, query, type); + } + + @GET + @Path("/folders/{folder}/") + @Produces("text/json; charset=utf-8") + @Transactional(Transactional.TxType.REQUIRED) + public List> findItemsInFolder( + @PathParam("content-section") final String section, + @PathParam("folder") final String folderPath, + @QueryParam("query") final String query, + @QueryParam("type") final String type) { + + final ContentSection contentSection = sectionRepo + .findByLabel(section) + .orElseThrow(() -> new NotFoundException( + String.format("No content section '%s' found.", section))); + + final Folder folder = folderRepo.findByPath(contentSection, + folderPath, + FolderType.DOCUMENTS_FOLDER) + .orElseThrow(() -> new NotFoundException(String.format( + "No documents folder with path '%s' in content section '%s'", + folderPath, + section))); + + return findItemsInFolder(folder, query, type); + } + + private List> findItemsInFolder(final Folder folder, + final String query, + final String type) { + + final List> subFolderEntries = folder + .getSubFolders() + .stream() + .map(subFolder -> createItemMapEntry(subFolder)) + .collect(Collectors.toList()); + + final List items; + if ((query == null || query.trim().isEmpty()) + && (type == null || type.trim().isEmpty())) { + items = itemRepo.findByFolder(folder); + } else if ((query != null && !query.trim().isEmpty()) + && (type == null || type.trim().isEmpty())) { + items = itemRepo.filterByFolderAndName(folder, query); + } else if ((query == null || query.trim().isEmpty()) + && (type != null && type.trim().isEmpty())) { + final Class itemType + = toContentItemTypeClass(type); + items = itemRepo.filterByFolderAndType(folder, itemType); + } else { + final Class itemType + = toContentItemTypeClass(type); + items = itemRepo.filterByFolderAndTypeAndName(folder, + itemType, + query); + } + + final List> itemEntries = items + .stream() + .map(item -> createItemMapEntry(item)) + .collect(Collectors.toList()); + + final List> result = new ArrayList<>(); + result.addAll(subFolderEntries); + result.addAll(itemEntries); + + return result; + + } + +}