001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.ui.apps.lists;
029
030import org.opencms.acacia.shared.I_CmsSerialDateValue;
031import org.opencms.ade.configuration.CmsADEConfigData;
032import org.opencms.ade.configuration.CmsResourceTypeConfig;
033import org.opencms.ade.containerpage.shared.CmsDialogOptions;
034import org.opencms.file.CmsFile;
035import org.opencms.file.CmsObject;
036import org.opencms.file.CmsPropertyDefinition;
037import org.opencms.file.CmsResource;
038import org.opencms.file.CmsResourceFilter;
039import org.opencms.file.types.CmsResourceTypeXmlContent;
040import org.opencms.file.types.I_CmsResourceType;
041import org.opencms.gwt.shared.CmsResourceStatusTabId;
042import org.opencms.i18n.CmsLocaleManager;
043import org.opencms.jsp.search.config.CmsSearchConfiguration;
044import org.opencms.jsp.search.config.CmsSearchConfigurationPagination;
045import org.opencms.jsp.search.config.I_CmsSearchConfigurationCommon;
046import org.opencms.jsp.search.config.I_CmsSearchConfigurationPagination;
047import org.opencms.jsp.search.config.parser.CmsSimpleSearchConfigurationParser;
048import org.opencms.jsp.search.config.parser.CmsSimpleSearchConfigurationParser.SortOption;
049import org.opencms.jsp.search.config.parser.simplesearch.CmsConfigParserUtils;
050import org.opencms.jsp.search.config.parser.simplesearch.CmsConfigurationBean;
051import org.opencms.jsp.search.controller.CmsSearchController;
052import org.opencms.jsp.search.controller.I_CmsSearchControllerFacetField;
053import org.opencms.jsp.search.controller.I_CmsSearchControllerFacetRange;
054import org.opencms.jsp.search.result.CmsSearchResultWrapper;
055import org.opencms.jsp.search.state.I_CmsSearchStateFacet;
056import org.opencms.loader.CmsLoaderException;
057import org.opencms.lock.CmsLockActionRecord;
058import org.opencms.lock.CmsLockActionRecord.LockChange;
059import org.opencms.lock.CmsLockUtil;
060import org.opencms.main.CmsException;
061import org.opencms.main.CmsLog;
062import org.opencms.main.OpenCms;
063import org.opencms.search.CmsSearchException;
064import org.opencms.search.CmsSearchResource;
065import org.opencms.search.fields.CmsSearchField;
066import org.opencms.search.solr.CmsSolrIndex;
067import org.opencms.search.solr.CmsSolrQuery;
068import org.opencms.search.solr.CmsSolrResultList;
069import org.opencms.ui.A_CmsUI;
070import org.opencms.ui.CmsVaadinUtils;
071import org.opencms.ui.FontOpenCms;
072import org.opencms.ui.I_CmsDialogContext;
073import org.opencms.ui.I_CmsDialogContext.ContextType;
074import org.opencms.ui.I_CmsUpdateListener;
075import org.opencms.ui.actions.A_CmsWorkplaceAction;
076import org.opencms.ui.actions.CmsContextMenuActionItem;
077import org.opencms.ui.actions.CmsDeleteDialogAction;
078import org.opencms.ui.actions.CmsEditDialogAction;
079import org.opencms.ui.actions.CmsResourceInfoAction;
080import org.opencms.ui.apps.A_CmsWorkplaceApp;
081import org.opencms.ui.apps.CmsAppView;
082import org.opencms.ui.apps.CmsAppView.CacheStatus;
083import org.opencms.ui.apps.CmsAppWorkplaceUi;
084import org.opencms.ui.apps.CmsEditor;
085import org.opencms.ui.apps.CmsEditorConfiguration;
086import org.opencms.ui.apps.CmsFileExplorer;
087import org.opencms.ui.apps.CmsFileExplorerSettings;
088import org.opencms.ui.apps.I_CmsAppUIContext;
089import org.opencms.ui.apps.I_CmsCachableApp;
090import org.opencms.ui.apps.I_CmsContextProvider;
091import org.opencms.ui.apps.Messages;
092import org.opencms.ui.apps.lists.CmsOptionDialog.I_OptionHandler;
093import org.opencms.ui.apps.projects.CmsProjectManagerConfiguration;
094import org.opencms.ui.components.CmsBasicDialog;
095import org.opencms.ui.components.CmsErrorDialog;
096import org.opencms.ui.components.CmsFileTable;
097import org.opencms.ui.components.CmsFileTableDialogContext;
098import org.opencms.ui.components.CmsResourceTable;
099import org.opencms.ui.components.CmsResourceTable.I_ResourcePropertyProvider;
100import org.opencms.ui.components.CmsResourceTableProperty;
101import org.opencms.ui.components.CmsResultFacets;
102import org.opencms.ui.components.CmsToolBar;
103import org.opencms.ui.components.I_CmsResultFacetsManager;
104import org.opencms.ui.components.I_CmsWindowCloseListener;
105import org.opencms.ui.components.OpenCmsTheme;
106import org.opencms.ui.components.extensions.CmsGwtDialogExtension;
107import org.opencms.ui.contextmenu.CmsMenuItemVisibilityMode;
108import org.opencms.ui.contextmenu.CmsResourceContextMenuBuilder;
109import org.opencms.ui.contextmenu.I_CmsContextMenuItem;
110import org.opencms.ui.contextmenu.I_CmsContextMenuItemProvider;
111import org.opencms.util.CmsStringUtil;
112import org.opencms.util.CmsUUID;
113import org.opencms.workplace.editors.directedit.CmsDateSeriesEditHandler;
114import org.opencms.workplace.editors.directedit.I_CmsEditHandler;
115import org.opencms.workplace.explorer.CmsResourceUtil;
116import org.opencms.xml.containerpage.CmsContainerElementBean;
117import org.opencms.xml.content.CmsXmlContent;
118import org.opencms.xml.content.CmsXmlContentFactory;
119
120import java.util.ArrayList;
121import java.util.Arrays;
122import java.util.Collection;
123import java.util.Collections;
124import java.util.Date;
125import java.util.HashSet;
126import java.util.LinkedHashMap;
127import java.util.List;
128import java.util.Locale;
129import java.util.Map;
130import java.util.Set;
131
132import org.apache.commons.logging.Log;
133
134import com.vaadin.navigator.View;
135import com.vaadin.navigator.ViewChangeListener;
136import com.vaadin.server.Sizeable.Unit;
137import com.vaadin.ui.Button;
138import com.vaadin.ui.Button.ClickEvent;
139import com.vaadin.ui.Button.ClickListener;
140import com.vaadin.ui.Component;
141import com.vaadin.ui.HorizontalSplitPanel;
142import com.vaadin.ui.UI;
143import com.vaadin.ui.Window;
144import com.vaadin.ui.themes.ValoTheme;
145import com.vaadin.v7.data.Item;
146import com.vaadin.v7.data.Property.ValueChangeEvent;
147import com.vaadin.v7.data.Property.ValueChangeListener;
148import com.vaadin.v7.event.FieldEvents.TextChangeEvent;
149import com.vaadin.v7.event.FieldEvents.TextChangeListener;
150import com.vaadin.v7.ui.AbstractSelect.ItemDescriptionGenerator;
151import com.vaadin.v7.ui.ComboBox;
152import com.vaadin.v7.ui.Table;
153import com.vaadin.v7.ui.Table.CellStyleGenerator;
154import com.vaadin.v7.ui.TextField;
155
156/**
157 * Manager for list configuration files.<p>
158 */
159@SuppressWarnings("deprecation")
160public class CmsListManager extends A_CmsWorkplaceApp
161implements I_ResourcePropertyProvider, I_CmsContextProvider, ViewChangeListener, I_CmsWindowCloseListener,
162I_CmsCachableApp, I_CmsResultFacetsManager {
163
164    /**
165     * Extended dialog context.<p>
166     */
167    protected class DialogContext extends CmsFileTableDialogContext {
168
169        /** The selected table items. */
170        private List<Item> m_selectedItems;
171
172        /**
173         * Constructor.<p>
174         *
175         * @param appId the app id
176         * @param contextType the context type
177         * @param fileTable the file table instance
178         * @param resources the list of selected resources
179         */
180        public DialogContext(
181            String appId,
182            ContextType contextType,
183            CmsFileTable fileTable,
184            List<CmsResource> resources) {
185
186            super(appId, contextType, fileTable, resources);
187        }
188
189        /**
190         * @see org.opencms.ui.components.CmsFileTableDialogContext#finish(java.util.Collection)
191         */
192        @Override
193        public void finish(Collection<CmsUUID> ids) {
194
195            if (m_selectedItems == null) {
196                super.finish(ids);
197            } else {
198                refreshResult();
199                closeWindow();
200            }
201        }
202
203        /**
204         * Returns the selected table items.<p>
205         *
206         * @return the selected table items
207         */
208        public List<Item> getSelectedItems() {
209
210            return m_selectedItems;
211        }
212
213        /**
214         * Sets the table items.<p>
215         *
216         * @param items the table items
217         */
218        public void setSelectedItems(List<Item> items) {
219
220            m_selectedItems = items;
221        }
222    }
223
224    /**
225     * Overrides the standard delete action to enable use of edit handlers.<p>
226     */
227    class DeleteAction extends CmsDeleteDialogAction {
228
229        /**
230         * @see org.opencms.ui.actions.CmsDeleteDialogAction#executeAction(org.opencms.ui.I_CmsDialogContext)
231         */
232        @Override
233        public void executeAction(final I_CmsDialogContext context) {
234
235            final CmsResource resource = context.getResources().get(0);
236            I_CmsResourceType resourceType = OpenCms.getResourceManager().getResourceType(resource);
237            if ((resourceType instanceof CmsResourceTypeXmlContent)
238                && (((CmsResourceTypeXmlContent)resourceType).getEditHandler(context.getCms()) != null)) {
239                final I_CmsEditHandler handler = ((CmsResourceTypeXmlContent)resourceType).getEditHandler(
240                    context.getCms());
241                final CmsContainerElementBean elementBean = getElementForEditHandler((DialogContext)context);
242                CmsDialogOptions options = handler.getDeleteOptions(
243                    context.getCms(),
244                    elementBean,
245                    null,
246                    Collections.<String, String[]> emptyMap());
247                if (options == null) {
248                    super.executeAction(context);
249                } else if (options.getOptions().size() == 1) {
250                    deleteForOption(resource, elementBean, options.getOptions().get(0).getValue(), handler, context);
251                } else {
252                    Window window = CmsBasicDialog.prepareWindow();
253                    window.setCaption(options.getTitle());
254                    CmsOptionDialog dialog = new CmsOptionDialog(resource, options, new I_OptionHandler() {
255
256                        public void handleOption(String option) {
257
258                            deleteForOption(resource, elementBean, option, handler, context);
259                        }
260                    }, null, window);
261                    window.setContent(dialog);
262                    CmsAppWorkplaceUi.get().addWindow(window);
263                    dialog.initActionHandler(window);
264
265                }
266            } else {
267                super.executeAction(context);
268            }
269        }
270
271        /**
272         * Deletes with the given option.<p>
273         *
274         * @param resource the resource to delete
275         * @param elementBean the element bean
276         * @param deleteOption the delete option
277         * @param editHandler edit handler
278         * @param context the dialog context
279         */
280        void deleteForOption(
281            CmsResource resource,
282            CmsContainerElementBean elementBean,
283            String deleteOption,
284            I_CmsEditHandler editHandler,
285            I_CmsDialogContext context) {
286
287            try {
288                editHandler.handleDelete(context.getCms(), elementBean, deleteOption, null, null);
289            } catch (CmsException e) {
290                CmsErrorDialog.showErrorDialog(e);
291            }
292        }
293    }
294
295    /**
296     * Overrides the standard edit action to enable use of edit handlers.<p>
297     */
298    class EditAction extends CmsEditDialogAction {
299
300        /**
301         * @see org.opencms.ui.actions.CmsEditDialogAction#executeAction(org.opencms.ui.I_CmsDialogContext)
302         */
303        @Override
304        public void executeAction(final I_CmsDialogContext context) {
305
306            final CmsResource resource = context.getResources().get(0);
307            I_CmsResourceType resourceType = OpenCms.getResourceManager().getResourceType(resource);
308            if ((resourceType instanceof CmsResourceTypeXmlContent)
309                && (((CmsResourceTypeXmlContent)resourceType).getEditHandler(context.getCms()) != null)) {
310                final I_CmsEditHandler handler = ((CmsResourceTypeXmlContent)resourceType).getEditHandler(
311                    context.getCms());
312                final CmsContainerElementBean elementBean = getElementForEditHandler((DialogContext)context);
313                CmsDialogOptions options = handler.getEditOptions(
314                    context.getCms(),
315                    elementBean,
316                    null,
317                    Collections.<String, String[]> emptyMap(),
318                    true);
319                if (options == null) {
320                    super.executeAction(context);
321                } else if (options.getOptions().size() == 1) {
322                    editForOption(resource, elementBean, options.getOptions().get(0).getValue(), handler, context);
323                } else {
324                    Window window = CmsBasicDialog.prepareWindow();
325                    window.setCaption(options.getTitle());
326                    CmsOptionDialog dialog = new CmsOptionDialog(resource, options, new I_OptionHandler() {
327
328                        public void handleOption(String option) {
329
330                            editForOption(resource, elementBean, option, handler, context);
331                        }
332                    }, null, window);
333                    window.setContent(dialog);
334                    CmsAppWorkplaceUi.get().addWindow(window);
335                    dialog.initActionHandler(window);
336
337                }
338            } else {
339                super.executeAction(context);
340            }
341        }
342
343        /**
344         * Calls the editor with the given option.<p>
345         *
346         * @param resource the resource to delete
347         * @param elementBean the element bean
348         * @param editOption the edit option
349         * @param editHandler edit handler
350         * @param context the dialog context
351         */
352        void editForOption(
353            CmsResource resource,
354            CmsContainerElementBean elementBean,
355            String editOption,
356            I_CmsEditHandler editHandler,
357            I_CmsDialogContext context) {
358
359            try {
360                CmsUUID id = editHandler.prepareForEdit(
361                    context.getCms(),
362                    elementBean,
363                    editOption,
364                    null,
365                    Collections.<String, String[]> emptyMap());
366                if (resource.getStructureId().equals(id)) {
367                    super.executeAction(context);
368                } else if (id != null) {
369                    CmsFileTableDialogContext changedContext = new CmsFileTableDialogContext(
370                        CmsProjectManagerConfiguration.APP_ID,
371                        ContextType.fileTable,
372                        m_resultTable,
373                        Collections.singletonList(context.getCms().readResource(id)));
374                    super.executeAction(changedContext);
375                }
376            } catch (CmsException e) {
377                CmsErrorDialog.showErrorDialog(e);
378            }
379        }
380    }
381
382    /** List configuration node name and field key. */
383    public static final String PARAM_LOCALE = "locale";
384
385    /** The view content list path name. */
386    public static final String PATH_NAME_VIEW = "view";
387
388    /** The list configuration resource type name. */
389    public static final String RES_TYPE_LIST_CONFIG = "listconfig";
390
391    /** The blacklisted table column property id. */
392    protected static final CmsResourceTableProperty BLACKLISTED_PROPERTY = new CmsResourceTableProperty(
393        "BLACKLISTED",
394        Boolean.class,
395        Boolean.FALSE,
396        Messages.GUI_LISTMANAGER_COLUMN_BLACKLISTED_0,
397        true,
398        0,
399        110);
400
401    /** The date series info table column property id. */
402    protected static final CmsResourceTableProperty INFO_PROPERTY = new CmsResourceTableProperty(
403        "INFO_PROPERTY",
404        String.class,
405        null,
406        null,
407        true,
408        1,
409        0);
410
411    /** The date series info label table column property id. */
412    protected static final CmsResourceTableProperty INFO_PROPERTY_LABEL = new CmsResourceTableProperty(
413        "INFO_PROPERTY_LABEL",
414        String.class,
415        null,
416        Messages.GUI_LISTMANAGER_COLUMN_INFO_0,
417        true,
418        0,
419        110);
420
421    /** The blacklisted table column property id. */
422    public static final CmsResourceTableProperty INSTANCEDATE_PROPERTY = new CmsResourceTableProperty(
423        "INSTANCEDATE_PROPERTY",
424        Date.class,
425        null,
426        Messages.GUI_LISTMANAGER_COLUMN_INSTANCEDATE_0,
427        true,
428        0,
429        145);
430
431    /** The available sort options. */
432    protected static final String[][] SORT_OPTIONS = new String[][] {
433        {
434            SortOption.DATE_ASC.toString(),
435            SortOption.DATE_DESC.toString(),
436            SortOption.TITLE_ASC.toString(),
437            SortOption.TITLE_DESC.toString(),
438            SortOption.ORDER_ASC.toString(),
439            SortOption.ORDER_DESC.toString()},
440        {
441            Messages.GUI_LISTMANAGER_SORT_DATE_ASC_0,
442            Messages.GUI_LISTMANAGER_SORT_DATE_DESC_0,
443            Messages.GUI_LISTMANAGER_SORT_TITLE_ASC_0,
444            Messages.GUI_LISTMANAGER_SORT_TITLE_DESC_0,
445            Messages.GUI_LISTMANAGER_SORT_ORDER_ASC_0,
446            Messages.GUI_LISTMANAGER_SORT_ORDER_DESC_0}};
447
448    /** The month name abbreviations. */
449    public static final String[] MONTHS = new String[] {
450        "JAN",
451        "FEB",
452        "MAR",
453        "APR",
454        "MAY",
455        "JUN",
456        "JUL",
457        "AUG",
458        "SEP",
459        "OCT",
460        "NOV",
461        "DEC"};
462
463    /** The logger for this class. */
464    static final Log LOG = CmsLog.getLog(CmsListManager.class.getName());
465
466    /** Default backend pagination. */
467    private static final I_CmsSearchConfigurationPagination PAGINATION = new CmsSearchConfigurationPagination(
468        null,
469        Integer.valueOf(10000),
470        Integer.valueOf(1));
471
472    /** The serial version id. */
473    private static final long serialVersionUID = -25954374225590319L;
474
475    /** The current list configuration data. */
476    CmsConfigurationBean m_currentConfig;
477
478    /** The current list configuration resource. */
479    CmsResource m_currentResource;
480
481    /** The result table. */
482    CmsResultTable m_resultTable;
483
484    /** The create new button. */
485    private Button m_createNewButton;
486
487    /** The current search parser. */
488    private CmsSimpleSearchConfigurationParser m_currentConfigParser;
489
490    /** The current app state. */
491    private String m_currentState;
492
493    /** The current edit dialog window. */
494    private Window m_dialogWindow;
495
496    /** The edit current configuration button. */
497    private Button m_editCurrentButton;
498
499    /** Indicates multiple instances of a series are present in the current search result. */
500    private boolean m_hasSeriesInstances;
501
502    /** Indicates series types are present in the current search result. */
503    private boolean m_hasSeriesType;
504
505    /** Flag indicating individual instances of a date series should be hidden. */
506    private boolean m_hideSeriesInstances;
507
508    /** The info button. */
509    private Button m_infoButton;
510
511    /** Indicates if the overview list is shown. */
512    private boolean m_isOverView;
513
514    /** The locale select. */
515    private ComboBox m_localeSelect;
516
517    /** The current lock action. */
518    private CmsLockActionRecord m_lockAction;
519
520    /** The list configurations overview table. */
521    private CmsFileTable m_overviewTable;
522
523    /** The publish button. */
524    private Button m_publishButton;
525
526    /** The resetting flag. */
527    private boolean m_resetting;
528
529    /** The facet result display. */
530    private CmsResultFacets m_resultFacets;
531
532    /** The mail layout. */
533    private HorizontalSplitPanel m_resultLayout;
534
535    /** The sort select. */
536    private ComboBox m_resultSorter;
537
538    /** The table filter input. */
539    private TextField m_tableFilter;
540
541    /** The text search input. */
542    private TextField m_textSearch;
543
544    /** The toggle date series display. */
545    private Button m_toggleSeriesButton;
546
547    /**
548     * @see org.opencms.ui.components.CmsResourceTable.I_ResourcePropertyProvider#addItemProperties(com.vaadin.v7.data.Item, org.opencms.file.CmsObject, org.opencms.file.CmsResource, java.util.Locale)
549     */
550    @SuppressWarnings("javadoc")
551    @Override
552    public void addItemProperties(Item resourceItem, CmsObject cms, CmsResource resource, Locale locale) {
553
554        if ((m_currentConfig != null) && (resourceItem.getItemProperty(CmsListManager.BLACKLISTED_PROPERTY) != null)) {
555            resourceItem.getItemProperty(CmsListManager.BLACKLISTED_PROPERTY).setValue(
556                Boolean.valueOf(m_currentConfig.getBlacklist().contains(resource.getStructureId())));
557        }
558        if ((m_currentConfig != null)
559            && (resourceItem.getItemProperty(CmsResourceTableProperty.PROPERTY_TITLE) != null)) {
560            CmsResourceUtil resUtil = new CmsResourceUtil(cms, resource);
561            String title = resUtil.getGalleryTitle((Locale)m_localeSelect.getValue());
562            if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(title)) {
563                resourceItem.getItemProperty(CmsResourceTableProperty.PROPERTY_TITLE).setValue(title);
564            }
565        }
566        if ((resource instanceof CmsSearchResource)
567            && (resourceItem.getItemProperty(CmsListManager.INFO_PROPERTY_LABEL) != null)) {
568            String seriesType = ((CmsSearchResource)resource).getField(CmsSearchField.FIELD_SERIESDATES_TYPE);
569            resourceItem.getItemProperty(CmsListManager.INFO_PROPERTY_LABEL).setValue(
570                CmsVaadinUtils.getMessageText(
571                    "GUI_LISTMANAGER_SERIES_TYPE_" + (seriesType == null ? "DEFAULT" : seriesType) + "_0"));
572            resourceItem.getItemProperty(CmsListManager.INFO_PROPERTY).setValue(seriesType);
573
574        }
575        if ((resource instanceof CmsSearchResource)
576            && (resourceItem.getItemProperty(CmsListManager.INSTANCEDATE_PROPERTY) != null)) {
577            Date date = ((CmsSearchResource)resource).getDateField(m_resultTable.getDateFieldKey());
578            resourceItem.getItemProperty(CmsListManager.INSTANCEDATE_PROPERTY).setValue(date);
579        }
580    }
581
582    /**
583     * @see com.vaadin.navigator.ViewChangeListener#afterViewChange(com.vaadin.navigator.ViewChangeListener.ViewChangeEvent)
584     */
585    @Override
586    public void afterViewChange(ViewChangeEvent event) {
587
588        // nothing to do
589    }
590
591    /**
592     * @see com.vaadin.navigator.ViewChangeListener#beforeViewChange(com.vaadin.navigator.ViewChangeListener.ViewChangeEvent)
593     */
594    @Override
595    public boolean beforeViewChange(ViewChangeEvent event) {
596
597        unlockCurrent();
598        return true;
599    }
600
601    /**
602     * @see org.opencms.ui.apps.I_CmsContextProvider#getDialogContext()
603     */
604    @Override
605    public I_CmsDialogContext getDialogContext() {
606
607        CmsFileTable table = isOverView() ? m_overviewTable : m_resultTable;
608        List<CmsResource> resources = table.getSelectedResources();
609        DialogContext context = new DialogContext(
610            CmsProjectManagerConfiguration.APP_ID,
611            ContextType.fileTable,
612            table,
613            resources);
614        if (!isOverView()) {
615            context.setSelectedItems(m_resultTable.getSelectedItems());
616        }
617        return context;
618    }
619
620    /**
621     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#initUI(org.opencms.ui.apps.I_CmsAppUIContext)
622     */
623    @Override
624    public void initUI(I_CmsAppUIContext uiContext) {
625
626        super.initUI(uiContext);
627        m_publishButton = CmsToolBar.createButton(
628            FontOpenCms.PUBLISH,
629            CmsVaadinUtils.getMessageText(Messages.GUI_PUBLISH_BUTTON_TITLE_0));
630        if (CmsAppWorkplaceUi.isOnlineProject()) {
631            // disable publishing in online project
632            m_publishButton.setEnabled(false);
633            m_publishButton.setDescription(CmsVaadinUtils.getMessageText(Messages.GUI_TOOLBAR_NOT_AVAILABLE_ONLINE_0));
634        }
635
636        m_publishButton.addClickListener(new ClickListener() {
637
638            /** Serial version id. */
639            private static final long serialVersionUID = 1L;
640
641            @Override
642            public void buttonClick(ClickEvent event) {
643
644                publish();
645            }
646        });
647        uiContext.addToolbarButton(m_publishButton);
648
649        m_editCurrentButton = CmsToolBar.createButton(
650            FontOpenCms.PEN,
651            CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_EDIT_CONFIG_0));
652        m_editCurrentButton.addClickListener(new ClickListener() {
653
654            /** Serial version id. */
655            private static final long serialVersionUID = 1L;
656
657            @Override
658            public void buttonClick(ClickEvent event) {
659
660                editListConfiguration(m_currentResource);
661            }
662        });
663        uiContext.addToolbarButton(m_editCurrentButton);
664
665        m_infoButton = CmsToolBar.createButton(
666            FontOpenCms.INFO,
667            CmsVaadinUtils.getMessageText(org.opencms.ui.Messages.GUI_RESOURCE_INFO_0));
668        m_infoButton.addClickListener(new ClickListener() {
669
670            /** Serial version id. */
671            private static final long serialVersionUID = 1L;
672
673            @Override
674            public void buttonClick(ClickEvent event) {
675
676                DialogContext context = new DialogContext(
677                    CmsProjectManagerConfiguration.APP_ID,
678                    ContextType.fileTable,
679                    m_resultTable,
680                    Collections.singletonList(m_currentResource));
681                CmsResourceInfoAction action = new CmsResourceInfoAction();
682                action.openDialog(context, CmsResourceStatusTabId.tabRelationsTo.name());
683            }
684        });
685        uiContext.addToolbarButton(m_infoButton);
686
687        m_toggleSeriesButton = CmsToolBar.createButton(
688            FontOpenCms.LIST,
689            CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_TOGGLE_SERIES_BUTTON_0));
690        m_toggleSeriesButton.addClickListener(new ClickListener() {
691
692            /** Serial version id. */
693            private static final long serialVersionUID = 1L;
694
695            @Override
696            public void buttonClick(ClickEvent event) {
697
698                toggleDateSeries();
699            }
700        });
701        uiContext.addToolbarButton(m_toggleSeriesButton);
702
703        m_createNewButton = CmsToolBar.createButton(
704            FontOpenCms.WAND,
705            CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_CREATE_NEW_0));
706        m_createNewButton.addClickListener(new ClickListener() {
707
708            /** Serial version id. */
709            private static final long serialVersionUID = 1L;
710
711            @Override
712            public void buttonClick(ClickEvent event) {
713
714                createNew();
715            }
716        });
717        uiContext.addToolbarButton(m_createNewButton);
718
719        m_rootLayout.setMainHeightFull(true);
720        m_resultLayout = new HorizontalSplitPanel();
721        m_resultLayout.setSizeFull();
722        m_resultFacets = new CmsResultFacets(this);
723        m_resultFacets.setWidth("100%");
724        m_resultLayout.setFirstComponent(m_resultFacets);
725        LinkedHashMap<CmsResourceTableProperty, Integer> tableColumns = new LinkedHashMap<CmsResourceTableProperty, Integer>();
726        // insert columns a specific positions
727        for (Map.Entry<CmsResourceTableProperty, Integer> columnsEntry : CmsFileTable.DEFAULT_TABLE_PROPERTIES.entrySet()) {
728            if (columnsEntry.getKey().equals(CmsResourceTableProperty.PROPERTY_RESOURCE_NAME)) {
729                tableColumns.put(INFO_PROPERTY_LABEL, Integer.valueOf(0));
730            } else if (columnsEntry.getKey().equals(CmsResourceTableProperty.PROPERTY_RESOURCE_TYPE)) {
731                tableColumns.put(INSTANCEDATE_PROPERTY, Integer.valueOf(0));
732            }
733            tableColumns.put(columnsEntry.getKey(), columnsEntry.getValue());
734        }
735        tableColumns.put(BLACKLISTED_PROPERTY, Integer.valueOf(CmsResourceTable.INVISIBLE));
736        tableColumns.put(INFO_PROPERTY, Integer.valueOf(CmsResourceTable.INVISIBLE));
737        m_resultTable = new CmsResultTable(null, tableColumns);
738        m_resultTable.applyWorkplaceAppSettings();
739        CmsResourceContextMenuBuilder menuBuilderOverView = new CmsResourceContextMenuBuilder();
740        menuBuilderOverView.addMenuItemProvider(OpenCms.getWorkplaceAppManager().getMenuItemProvider());
741        menuBuilderOverView.addMenuItemProvider(new I_CmsContextMenuItemProvider() {
742
743            @Override
744            public List<I_CmsContextMenuItem> getMenuItems() {
745
746                return Arrays.<I_CmsContextMenuItem> asList(new CmsContextMenuActionItem(new CmsEditDialogAction() {
747
748                    @Override
749                    public void executeAction(I_CmsDialogContext context) {
750
751                        editListConfiguration(context.getResources().get(0));
752                    }
753                }, null, 10, 1000));
754            }
755        });
756        CmsResourceContextMenuBuilder menuBuilder = new CmsResourceContextMenuBuilder();
757        menuBuilder.addMenuItemProvider(OpenCms.getWorkplaceAppManager().getMenuItemProvider());
758        menuBuilder.addMenuItemProvider(new I_CmsContextMenuItemProvider() {
759
760            @Override
761            public List<I_CmsContextMenuItem> getMenuItems() {
762
763                return Arrays.<I_CmsContextMenuItem> asList(new CmsContextMenuActionItem(new A_CmsWorkplaceAction() {
764
765                    @Override
766                    public void executeAction(I_CmsDialogContext context) {
767
768                        CmsUUID structureId = context.getResources().get(0).getStructureId();
769                        m_currentConfig.getBlacklist().add(structureId);
770                        saveBlacklist(m_currentConfig);
771                        context.finish(Collections.singletonList(structureId));
772                    }
773
774                    @Override
775                    public String getId() {
776
777                        return "hideresource";
778                    }
779
780                    @Override
781                    public String getTitleKey() {
782
783                        return Messages.GUI_LISTMANAGER_BLACKLIST_MENU_ENTRY_0;
784                    }
785
786                    @Override
787                    public CmsMenuItemVisibilityMode getVisibility(CmsObject cms, List<CmsResource> resources) {
788
789                        if ((m_currentConfig != null)
790                            && (resources != null)
791                            && (resources.size() == 1)
792                            && !m_currentConfig.getBlacklist().contains(resources.get(0).getStructureId())) {
793                            return CmsEditDialogAction.VISIBILITY.getVisibility(
794                                cms,
795                                Collections.singletonList(m_currentResource));
796                        } else {
797                            return CmsMenuItemVisibilityMode.VISIBILITY_INVISIBLE;
798                        }
799                    }
800
801                }, null, 10, 0), new CmsContextMenuActionItem(new A_CmsWorkplaceAction() {
802
803                    @Override
804                    public void executeAction(I_CmsDialogContext context) {
805
806                        CmsUUID structureId = context.getResources().get(0).getStructureId();
807                        m_currentConfig.getBlacklist().remove(structureId);
808                        saveBlacklist(m_currentConfig);
809                        context.finish(Collections.singletonList(structureId));
810                    }
811
812                    @Override
813                    public String getId() {
814
815                        return "showresource";
816                    }
817
818                    @Override
819                    public String getTitleKey() {
820
821                        return Messages.GUI_LISTMANAGER_REMOVE_FROM_BLACKLIST_MENU_ENTRY_0;
822                    }
823
824                    @Override
825                    public CmsMenuItemVisibilityMode getVisibility(CmsObject cms, List<CmsResource> resources) {
826
827                        if ((m_currentConfig != null)
828                            && (resources != null)
829                            && (resources.size() == 1)
830                            && m_currentConfig.getBlacklist().contains(resources.get(0).getStructureId())) {
831                            return CmsEditDialogAction.VISIBILITY.getVisibility(
832                                cms,
833                                Collections.singletonList(m_currentResource));
834                        } else {
835                            return CmsMenuItemVisibilityMode.VISIBILITY_INVISIBLE;
836                        }
837                    }
838
839                }, null, 10, 0),
840                    new CmsContextMenuActionItem(new EditAction(), null, 10, 1000),
841                    new CmsContextMenuActionItem(new DeleteAction(), null, 10, 1000));
842            }
843        });
844        m_resultTable.setMenuBuilder(menuBuilder);
845        m_resultTable.addAdditionalStyleGenerator(new CellStyleGenerator() {
846
847            private static final long serialVersionUID = 1L;
848
849            @Override
850            public String getStyle(Table source, Object itemId, Object propertyId) {
851
852                String style = "";
853                Item item = source.getItem(itemId);
854                Boolean blacklisted = (Boolean)item.getItemProperty(BLACKLISTED_PROPERTY).getValue();
855                if (blacklisted.booleanValue()) {
856                    style += OpenCmsTheme.PROJECT_OTHER + " ";
857                } else if (CmsResourceTableProperty.PROPERTY_TITLE.equals(propertyId)
858                    && ((item.getItemProperty(CmsResourceTableProperty.PROPERTY_RELEASED_NOT_EXPIRED) == null)
859                        || ((Boolean)item.getItemProperty(
860                            CmsResourceTableProperty.PROPERTY_RELEASED_NOT_EXPIRED).getValue()).booleanValue())) {
861                                style += OpenCmsTheme.IN_NAVIGATION + " ";
862                            }
863                if (INFO_PROPERTY_LABEL.equals(propertyId)) {
864                    if (blacklisted.booleanValue()) {
865                        style += OpenCmsTheme.TABLE_COLUMN_BOX_BLACK;
866                    } else {
867                        Object value = item.getItemProperty(INFO_PROPERTY).getValue();
868                        if (value == null) {
869                            style += OpenCmsTheme.TABLE_COLUMN_BOX_GRAY;
870                        } else {
871                            I_CmsSerialDateValue.DateType type = I_CmsSerialDateValue.DateType.valueOf((String)value);
872                            switch (type) {
873                                case SERIES:
874                                    style += OpenCmsTheme.TABLE_COLUMN_BOX_BLUE_LIGHT;
875                                    break;
876                                case SINGLE:
877                                    style += OpenCmsTheme.TABLE_COLUMN_BOX_GRAY;
878                                    break;
879                                case EXTRACTED:
880                                    style += OpenCmsTheme.TABLE_COLUMN_BOX_ORANGE;
881                                    break;
882                                default:
883                                    break;
884                            }
885                        }
886                    }
887                }
888                return style;
889            }
890        });
891        final ItemDescriptionGenerator defaultDescriptionGenerator = new CmsResourceTable.DefaultItemDescriptionGenerator();
892        m_resultTable.setsetItemDescriptionGenerator(new ItemDescriptionGenerator() {
893
894            private static final long serialVersionUID = 1L;
895
896            public String generateDescription(Component source, Object itemId, Object propertyId) {
897
898                Item item = ((Table)source).getItem(itemId);
899                if (INFO_PROPERTY_LABEL.equals(propertyId)
900                    && ((Boolean)item.getItemProperty(BLACKLISTED_PROPERTY).getValue()).booleanValue()) {
901                    return CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_COLUMN_BLACKLISTED_0);
902                }
903                return defaultDescriptionGenerator.generateDescription(source, itemId, propertyId);
904            }
905        });
906        m_resultTable.setContextProvider(this);
907        m_resultTable.addPropertyProvider(this);
908        m_resultTable.setSizeFull();
909        m_resultLayout.setSecondComponent(m_resultTable);
910        m_overviewTable = new CmsFileTable(this);
911        m_overviewTable.applyWorkplaceAppSettings();
912        m_overviewTable.setMenuBuilder(menuBuilderOverView);
913        m_overviewTable.setSizeFull();
914
915        m_tableFilter = new TextField();
916        m_tableFilter.setIcon(FontOpenCms.FILTER);
917        m_tableFilter.setInputPrompt(
918            Messages.get().getBundle(UI.getCurrent().getLocale()).key(Messages.GUI_EXPLORER_FILTER_0));
919        m_tableFilter.addStyleName(ValoTheme.TEXTFIELD_INLINE_ICON);
920        m_tableFilter.setWidth("200px");
921        m_tableFilter.addTextChangeListener(new TextChangeListener() {
922
923            private static final long serialVersionUID = 1L;
924
925            @Override
926            public void textChange(TextChangeEvent event) {
927
928                filterTable(event.getText());
929
930            }
931        });
932        m_infoLayout.addComponent(m_tableFilter);
933
934        m_localeSelect = new ComboBox();
935        m_localeSelect.setNullSelectionAllowed(false);
936        m_localeSelect.setWidth("100px");
937        m_localeSelect.addValueChangeListener(new ValueChangeListener() {
938
939            /** Serial version id. */
940            private static final long serialVersionUID = 1L;
941
942            @Override
943            public void valueChange(ValueChangeEvent event) {
944
945                changeContentLocale((Locale)event.getProperty().getValue());
946            }
947        });
948        m_infoLayout.addComponent(m_localeSelect);
949
950        m_resultSorter = new ComboBox();
951        m_resultSorter.setNullSelectionAllowed(false);
952        m_resultSorter.setWidth("200px");
953        for (int i = 0; i < SORT_OPTIONS[0].length; i++) {
954            m_resultSorter.addItem(SORT_OPTIONS[0][i]);
955            m_resultSorter.setItemCaption(SORT_OPTIONS[0][i], CmsVaadinUtils.getMessageText(SORT_OPTIONS[1][i]));
956        }
957        m_resultSorter.addValueChangeListener(new ValueChangeListener() {
958
959            /** Serial version id. */
960            private static final long serialVersionUID = 1L;
961
962            @Override
963            public void valueChange(ValueChangeEvent event) {
964
965                sortResult();
966            }
967        });
968        m_infoLayout.addComponent(m_resultSorter);
969
970        m_textSearch = new TextField();
971        m_textSearch.setIcon(FontOpenCms.SEARCH);
972        m_textSearch.setInputPrompt(CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_SEARCH_0));
973        m_textSearch.addStyleName(ValoTheme.TEXTFIELD_INLINE_ICON);
974        m_textSearch.setWidth("200px");
975        m_textSearch.addValueChangeListener(new ValueChangeListener() {
976
977            /** Serial version id. */
978            private static final long serialVersionUID = 1L;
979
980            @Override
981            public void valueChange(ValueChangeEvent event) {
982
983                search((String)event.getProperty().getValue());
984            }
985        });
986        m_infoLayout.addComponent(m_textSearch);
987        m_resultLayout.setSecondComponent(m_resultTable);
988        m_resultLayout.setSplitPosition(CmsFileExplorer.LAYOUT_SPLIT_POSITION, Unit.PIXELS);
989    }
990
991    /**
992     * @see org.opencms.ui.apps.I_CmsCachableApp#isCachable()
993     */
994    public boolean isCachable() {
995
996        return true;
997    }
998
999    /**
1000     * @see org.opencms.ui.apps.I_CmsCachableApp#onRestoreFromCache()
1001     */
1002    public void onRestoreFromCache() {
1003
1004        if (isOverView()) {
1005            CmsFileExplorerSettings state = m_overviewTable.getTableSettings();
1006            displayListConfigs();
1007            m_overviewTable.setTableState(state);
1008            m_overviewTable.updateSorting();
1009        } else {
1010            refreshResult();
1011        }
1012    }
1013
1014    /**
1015     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#onStateChange(java.lang.String)
1016     */
1017    @Override
1018    public void onStateChange(String state) {
1019
1020        if ((m_currentState == null) || !m_currentState.equals(state)) {
1021            m_currentState = state;
1022            super.onStateChange(state);
1023        }
1024    }
1025
1026    /**
1027     * @see org.opencms.ui.components.I_CmsWindowCloseListener#onWindowClose()
1028     */
1029    @Override
1030    public void onWindowClose() {
1031
1032        unlockCurrent();
1033    }
1034
1035    /**
1036     * Saves the blacklist from the bean in the current list configuration.<p>
1037     *
1038     * @param configBean the bean whose blacklist should be saved
1039     */
1040    public void saveBlacklist(CmsConfigurationBean configBean) {
1041
1042        if (m_dialogWindow != null) {
1043            m_dialogWindow.close();
1044            m_dialogWindow = null;
1045        }
1046        CmsObject cms = A_CmsUI.getCmsObject();
1047
1048        try {
1049            m_lockAction = CmsLockUtil.ensureLock(cms, m_currentResource);
1050        } catch (CmsException e) {
1051            CmsErrorDialog.showErrorDialog(e);
1052            return;
1053        }
1054
1055        try {
1056            CmsFile configFile = cms.readFile(m_currentResource);
1057            CmsXmlContent content = CmsXmlContentFactory.unmarshal(cms, configFile);
1058            content = CmsConfigParserUtils.updateBlackList(cms, content, configBean);
1059            configFile.setContents(content.marshal());
1060            cms.writeFile(configFile);
1061            if (m_lockAction.getChange().equals(LockChange.locked)) {
1062                CmsLockUtil.tryUnlock(cms, configFile);
1063            }
1064        } catch (CmsException e) {
1065            e.printStackTrace();
1066        }
1067        m_currentConfig = configBean;
1068    }
1069
1070    /**
1071     * Execute a search with the given search configuration parser.<p>
1072     *
1073     * @param configParser the search configuration parser
1074     * @param resource the current configuration resource
1075     */
1076    public void search(CmsSimpleSearchConfigurationParser configParser, CmsResource resource) {
1077
1078        m_currentResource = resource;
1079        m_currentConfigParser = configParser;
1080        resetContentLocale(configParser.getSearchLocale());
1081        m_resetting = true;
1082        m_resultSorter.setValue(m_currentConfig.getParameterValue(CmsConfigurationBean.PARAM_SORT_ORDER));
1083        m_resetting = false;
1084
1085        search(null, null, null);
1086    }
1087
1088    /**
1089     * Updates the search result.<p>
1090     *
1091     * @param fieldFacets the field facets
1092     * @param rangeFacets the range facets
1093     */
1094    public void search(Map<String, List<String>> fieldFacets, Map<String, List<String>> rangeFacets) {
1095
1096        search(fieldFacets, rangeFacets, null);
1097    }
1098
1099    /**
1100     * Updates the search result.<p>
1101     *
1102     * @param fieldFacets the field facets
1103     * @param rangeFacets the range facets
1104     * @param additionalQuery the additional query
1105     */
1106    public void search(
1107        Map<String, List<String>> fieldFacets,
1108        Map<String, List<String>> rangeFacets,
1109        String additionalQuery) {
1110
1111        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly((String)m_resultSorter.getValue())) {
1112            m_currentConfigParser.setSortOption((String)m_resultSorter.getValue());
1113        }
1114
1115        CmsSolrQuery query = m_currentConfigParser.getInitialQuery();
1116        CmsSearchController controller = new CmsSearchController(
1117            new CmsSearchConfiguration(m_currentConfigParser, A_CmsUI.getCmsObject()));
1118        controller.getPagination().getState().setCurrentPage(1);
1119        if (fieldFacets != null) {
1120            Map<String, I_CmsSearchControllerFacetField> fieldFacetControllers = controller.getFieldFacets().getFieldFacetController();
1121            for (Map.Entry<String, List<String>> facetEntry : fieldFacets.entrySet()) {
1122                I_CmsSearchStateFacet state = fieldFacetControllers.get(facetEntry.getKey()).getState();
1123                state.clearChecked();
1124                for (String check : facetEntry.getValue()) {
1125                    state.addChecked(check);
1126                }
1127            }
1128        }
1129        if (rangeFacets != null) {
1130            Map<String, I_CmsSearchControllerFacetRange> rangeFacetControllers = controller.getRangeFacets().getRangeFacetController();
1131            for (Map.Entry<String, List<String>> facetEntry : rangeFacets.entrySet()) {
1132                I_CmsSearchStateFacet state = rangeFacetControllers.get(facetEntry.getKey()).getState();
1133                state.clearChecked();
1134                for (String check : facetEntry.getValue()) {
1135                    state.addChecked(check);
1136                }
1137            }
1138        }
1139        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(additionalQuery)) {
1140            controller.getCommon().getState().setQuery(additionalQuery);
1141        } else {
1142            resetTextSearch();
1143        }
1144
1145        controller.addQueryParts(query, A_CmsUI.getCmsObject());
1146        executeSearch(controller, query);
1147    }
1148
1149    /**
1150     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getBreadCrumbForState(java.lang.String)
1151     */
1152    @Override
1153    protected LinkedHashMap<String, String> getBreadCrumbForState(String state) {
1154
1155        LinkedHashMap<String, String> crumbs = new LinkedHashMap<String, String>();
1156        if (CmsStringUtil.isEmptyOrWhitespaceOnly(state)) {
1157            crumbs.put("", CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_TITLE_0));
1158        } else if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(
1159            A_CmsWorkplaceApp.getParamFromState(state, CmsEditor.RESOURCE_ID_PREFIX))) {
1160                crumbs.put(
1161                    CmsListManagerConfiguration.APP_ID,
1162                    CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_TITLE_0));
1163                String title = "";
1164                try {
1165                    title = A_CmsUI.getCmsObject().readPropertyObject(
1166                        m_currentResource,
1167                        CmsPropertyDefinition.PROPERTY_TITLE,
1168                        false).getValue();
1169                } catch (Exception e) {
1170                    // ignore
1171                }
1172                if ((m_currentResource != null) && CmsStringUtil.isEmptyOrWhitespaceOnly(title)) {
1173                    title = m_currentResource.getName();
1174                }
1175                crumbs.put("", CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_VIEW_1, title));
1176            }
1177        return crumbs;
1178    }
1179
1180    /**
1181     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getComponentForState(java.lang.String)
1182     */
1183    @Override
1184    protected Component getComponentForState(String state) {
1185
1186        CmsObject cms = A_CmsUI.getCmsObject();
1187        boolean showOverview = true;
1188        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(
1189            A_CmsWorkplaceApp.getParamFromState(state, CmsEditor.RESOURCE_ID_PREFIX))) {
1190            try {
1191                CmsUUID id = new CmsUUID(A_CmsWorkplaceApp.getParamFromState(state, CmsEditor.RESOURCE_ID_PREFIX));
1192                CmsResource res = cms.readResource(id, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
1193                m_currentConfig = CmsConfigParserUtils.parseListConfiguration(A_CmsUI.getCmsObject(), res);
1194                String localeString = A_CmsWorkplaceApp.getParamFromState(state, PARAM_LOCALE);
1195                Locale locale;
1196                if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(localeString)) {
1197                    locale = CmsLocaleManager.getLocale(localeString);
1198                } else {
1199                    locale = getContentLocale(m_currentConfig);
1200                }
1201                //SearchConfigParser configParser = new SearchConfigParser(m_currentConfig, m_collapseItemSeries, locale);
1202                CmsSimpleSearchConfigurationParser configParser = new CmsSimpleSearchConfigurationParser(
1203                    cms,
1204                    m_currentConfig,
1205                    null);
1206                setBackendSpecificOptions(configParser, locale);
1207                search(configParser, res);
1208                showOverview = false;
1209
1210            } catch (Exception e) {
1211                CmsErrorDialog.showErrorDialog(e);
1212                LOG.error(e.getLocalizedMessage(), e);
1213            }
1214        }
1215        if (showOverview) {
1216            unlockCurrent();
1217            m_lockAction = null;
1218            displayListConfigs();
1219        }
1220        enableOverviewMode(showOverview);
1221
1222        return showOverview ? m_overviewTable : m_resultLayout;
1223    }
1224
1225    /**
1226     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getSubNavEntries(java.lang.String)
1227     */
1228    @Override
1229    protected List<NavEntry> getSubNavEntries(String state) {
1230
1231        return null;
1232    }
1233
1234    /**
1235     * Changes the search content locale, reissuing a search.<p>
1236     *
1237     * @param contentLocale the content locale to set
1238     */
1239    void changeContentLocale(Locale contentLocale) {
1240
1241        if (!m_resetting) {
1242            m_currentConfigParser.setSearchLocale(contentLocale);
1243        }
1244        m_resultTable.setContentLocale(contentLocale);
1245        search(null, null, null);
1246    }
1247
1248    /**
1249     * Closes the edit dialog window.<p>
1250     */
1251    void closeEditDialog() {
1252
1253        if (m_dialogWindow != null) {
1254            m_dialogWindow.close();
1255            m_dialogWindow = null;
1256        }
1257        if (m_isOverView) {
1258            unlockCurrent();
1259            m_currentResource = null;
1260        }
1261    }
1262
1263    /**
1264     * Opens the create new dialog.<p>
1265     */
1266    void createNew() {
1267
1268        if (m_isOverView) {
1269            editListConfiguration(null);
1270        }
1271    }
1272
1273    /**
1274     * Displays the search result in the result table.<p>
1275     *
1276     * @param resultList the search result
1277     */
1278    void displayResult(CmsSolrResultList resultList) {
1279
1280        List<CmsResource> resources;
1281        evalSeries(resultList);
1282        if (m_hideSeriesInstances) {
1283            Set<CmsUUID> instanceIds = new HashSet<CmsUUID>();
1284            resources = new ArrayList<CmsResource>();
1285            for (CmsSearchResource res : resultList) {
1286                if (!instanceIds.contains(res.getStructureId())) {
1287                    instanceIds.add(res.getStructureId());
1288                    resources.add(res);
1289                }
1290            }
1291        } else {
1292            resources = new ArrayList<CmsResource>(resultList);
1293        }
1294        m_resultTable.fillTable(A_CmsUI.getCmsObject(), resources, true, false);
1295        String state = A_CmsWorkplaceApp.addParamToState(
1296            "",
1297            CmsEditor.RESOURCE_ID_PREFIX,
1298            m_currentResource.getStructureId().toString());
1299        state = A_CmsWorkplaceApp.addParamToState(
1300            state,
1301            PARAM_LOCALE,
1302            m_currentConfigParser.getSearchLocale().toString());
1303        m_currentState = state;
1304        CmsAppWorkplaceUi.get().changeCurrentAppState(state);
1305        if (m_isOverView) {
1306            enableOverviewMode(false);
1307            updateBreadCrumb(getBreadCrumbForState(state));
1308        }
1309    }
1310
1311    /**
1312     * Edits the given list configuration resource.<p>
1313     *
1314     * @param resource the configuration resource
1315     */
1316    void editListConfiguration(CmsResource resource) {
1317
1318        try {
1319            CmsObject cms = A_CmsUI.getCmsObject();
1320            String editState;
1321            if (resource == null) {
1322                editState = CmsEditor.getEditStateForNew(
1323                    cms,
1324                    OpenCms.getResourceManager().getResourceType(RES_TYPE_LIST_CONFIG),
1325                    "/",
1326                    null,
1327                    false,
1328                    UI.getCurrent().getPage().getLocation().toString());
1329            } else {
1330                editState = CmsEditor.getEditState(
1331                    resource.getStructureId(),
1332                    false,
1333                    UI.getCurrent().getPage().getLocation().toString());
1334            }
1335            View view = CmsAppWorkplaceUi.get().getCurrentView();
1336            if (view instanceof CmsAppView) {
1337                ((CmsAppView)view).setCacheStatus(CacheStatus.cacheOnce);
1338            }
1339            CmsAppWorkplaceUi.get().showApp(
1340                OpenCms.getWorkplaceAppManager().getAppConfiguration(CmsEditorConfiguration.APP_ID),
1341                editState);
1342
1343        } catch (CmsLoaderException e) {
1344            CmsErrorDialog.showErrorDialog(e);
1345        }
1346    }
1347
1348    /**
1349     * Enables the overview mode.<p>
1350     *
1351     * @param enabled <code>true</code> to enable the mode
1352     */
1353    void enableOverviewMode(boolean enabled) {
1354
1355        boolean isOffline = !A_CmsUI.getCmsObject().getRequestContext().getCurrentProject().isOnlineProject();
1356        m_publishButton.setVisible(!enabled);
1357        m_publishButton.setEnabled(isOffline);
1358        m_infoButton.setVisible(!enabled);
1359        m_tableFilter.setVisible(enabled);
1360        m_textSearch.setVisible(!enabled);
1361        m_editCurrentButton.setVisible(!enabled);
1362        m_editCurrentButton.setEnabled(isOffline);
1363
1364        m_toggleSeriesButton.setVisible(m_hasSeriesType && !enabled);
1365        m_resultSorter.setVisible(!enabled);
1366        m_localeSelect.setVisible(!enabled);
1367        m_isOverView = enabled;
1368        m_rootLayout.setMainContent(enabled ? m_overviewTable : m_resultLayout);
1369        m_createNewButton.setVisible(enabled);
1370        if (enabled) {
1371            if (!isOffline) {
1372                m_createNewButton.setEnabled(false);
1373                m_createNewButton.setDescription(
1374                    CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_NOT_CREATABLE_ONLINE_0));
1375            } else {
1376                CmsObject cms = A_CmsUI.getCmsObject();
1377                CmsADEConfigData data = OpenCms.getADEManager().lookupConfiguration(
1378                    cms,
1379                    cms.getRequestContext().getSiteRoot());
1380                CmsResourceTypeConfig typeConfig = data.getResourceType(RES_TYPE_LIST_CONFIG);
1381                try {
1382                    if ((typeConfig == null)
1383                        || !typeConfig.checkCreatable(cms, cms.getRequestContext().getSiteRoot())) {
1384                        m_createNewButton.setEnabled(false);
1385                        m_createNewButton.setDescription(
1386                            CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_NOT_CREATABLE_TYPE_0));
1387                    } else {
1388                        m_createNewButton.setEnabled(true);
1389                        m_createNewButton.setDescription(
1390                            CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_CREATE_NEW_0));
1391                    }
1392                } catch (CmsException e) {
1393                    m_createNewButton.setEnabled(false);
1394                    m_createNewButton.setDescription(
1395                        CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_NOT_CREATABLE_TYPE_0));
1396                }
1397            }
1398        }
1399    }
1400
1401    /**
1402     * Evaluates if date series types are present and if more than one instance of a series is in the search result.<p>
1403     *
1404     * @param resultList the search result list
1405     */
1406    void evalSeries(CmsSolrResultList resultList) {
1407
1408        m_hasSeriesType = false;
1409        m_hasSeriesInstances = false;
1410        Set<CmsUUID> instanceIds = new HashSet<CmsUUID>();
1411        for (CmsSearchResource res : resultList) {
1412            String seriesType = res.getField(CmsSearchField.FIELD_SERIESDATES_TYPE);
1413            m_hasSeriesType = m_hasSeriesType || CmsStringUtil.isNotEmptyOrWhitespaceOnly(seriesType);
1414            if (m_hasSeriesType && I_CmsSerialDateValue.DateType.SERIES.name().equals(seriesType)) {
1415                if (instanceIds.contains(res.getStructureId())) {
1416                    m_hasSeriesInstances = true;
1417                    break;
1418                } else {
1419                    instanceIds.add(res.getStructureId());
1420                }
1421            }
1422        }
1423        if (!m_hasSeriesInstances) {
1424            setsDateSeriesHiddenFlag(false);
1425        }
1426        m_toggleSeriesButton.setEnabled(m_hasSeriesInstances);
1427        m_toggleSeriesButton.setVisible(m_hasSeriesType);
1428
1429    }
1430
1431    /**
1432     * Filters the result table.<p>
1433     *
1434     * @param filter the filter string
1435     */
1436    void filterTable(String filter) {
1437
1438        if (!m_resetting) {
1439            m_overviewTable.filterTable(filter);
1440        }
1441    }
1442
1443    /**
1444     * Creates an element bean of the selected table item to be used with edit handlers.<p>
1445     *
1446     * @param context the dialog context
1447     *
1448     * @return the element bean
1449     */
1450    CmsContainerElementBean getElementForEditHandler(DialogContext context) {
1451
1452        List<Item> selected = context.getSelectedItems();
1453        if (selected.size() == 1) {
1454            Item item = selected.get(0);
1455            Date instanceDate = (Date)item.getItemProperty(INSTANCEDATE_PROPERTY).getValue();
1456            CmsResource resource = context.getResources().get(0);
1457            return new CmsContainerElementBean(
1458                resource.getStructureId(),
1459                null,
1460                Collections.singletonMap(
1461                    CmsDateSeriesEditHandler.PARAM_INSTANCEDATE,
1462                    String.valueOf(instanceDate.getTime())),
1463                false);
1464        }
1465        return null;
1466    }
1467
1468    /**
1469     * Returns the resources to publish for the current list.<p>
1470     *
1471     * @return the publish resources
1472     */
1473    List<CmsResource> getPublishResources() {
1474
1475        List<CmsResource> result = new ArrayList<CmsResource>();
1476        if (m_currentResource != null) {
1477            result.add(m_currentResource);
1478            CmsObject cms = A_CmsUI.getCmsObject();
1479            CmsSolrQuery query = m_currentConfigParser.getInitialQuery();
1480            CmsSearchController controller = new CmsSearchController(
1481                new CmsSearchConfiguration(m_currentConfigParser, A_CmsUI.getCmsObject()));
1482            controller.getPagination().getState().setCurrentPage(1);
1483            controller.addQueryParts(query, A_CmsUI.getCmsObject());
1484            I_CmsSearchConfigurationCommon commonConfig = controller.getCommon().getConfig();
1485            CmsSolrIndex index = OpenCms.getSearchManager().getIndexSolr(commonConfig.getSolrIndex());
1486            try {
1487                CmsSolrResultList solrResultList = index.search(
1488                    cms,
1489                    query,
1490                    true,
1491                    null,
1492                    false,
1493                    CmsResourceFilter.IGNORE_EXPIRATION,
1494                    commonConfig.getMaxReturnedResults());
1495                result.addAll(solrResultList);
1496            } catch (CmsSearchException e) {
1497                LOG.error("Error reading resources for publish.", e);
1498            }
1499        }
1500        return result;
1501    }
1502
1503    /**
1504     * Returns whether the overview mode is active.<p>
1505     *
1506     * @return <code>true</code> in case the overview mode is active
1507     */
1508    boolean isOverView() {
1509
1510        return m_isOverView;
1511    }
1512
1513    /**
1514     * Opens the publish dialog to publish all resources related to the current search configuration.<p>
1515     */
1516    void publish() {
1517
1518        I_CmsUpdateListener<String> updateListener = new I_CmsUpdateListener<String>() {
1519
1520            @Override
1521            public void onUpdate(List<String> updatedItems) {
1522
1523                updateItems(updatedItems);
1524            }
1525        };
1526        CmsAppWorkplaceUi.get().disableGlobalShortcuts();
1527        CmsGwtDialogExtension extension = new CmsGwtDialogExtension(A_CmsUI.get(), updateListener);
1528        extension.openPublishDialog(getPublishResources());
1529    }
1530
1531    /**
1532     * Refreshes the search result maintaining the current scroll position.<p>
1533     */
1534    void refreshResult() {
1535
1536        String itemId = m_resultTable.getCurrentPageFirstItemId();
1537        CmsFileExplorerSettings state = m_resultTable.getTableSettings();
1538        search(
1539            m_resultFacets.getSelectedFieldFacets(),
1540            m_resultFacets.getSelectedRangeFactes(),
1541            m_textSearch.getValue());
1542        m_resultTable.setTableState(state);
1543        m_resultTable.updateSorting();
1544        m_resultTable.setCurrentPageFirstItemId(itemId);
1545    }
1546
1547    /**
1548     * Searches within the current list.<p>
1549     *
1550     * @param query the query string
1551     */
1552    void search(String query) {
1553
1554        if (!m_resetting) {
1555            search(null, null, query);
1556        }
1557    }
1558
1559    /**
1560     * Sets the date series hidden flag.<p>
1561     *
1562     * @param hide the date series hidden flag
1563     */
1564    void setsDateSeriesHiddenFlag(boolean hide) {
1565
1566        m_hideSeriesInstances = hide;
1567        if (m_hideSeriesInstances) {
1568            m_toggleSeriesButton.addStyleName(OpenCmsTheme.BUTTON_PRESSED);
1569        } else {
1570            m_toggleSeriesButton.removeStyleName(OpenCmsTheme.BUTTON_PRESSED);
1571        }
1572    }
1573
1574    /**
1575     * Sorts the search result.<p>
1576     */
1577    void sortResult() {
1578
1579        if (!m_resetting) {
1580            search(
1581                m_resultFacets.getSelectedFieldFacets(),
1582                m_resultFacets.getSelectedRangeFactes(),
1583                m_textSearch.getValue());
1584        }
1585    }
1586
1587    /**
1588     * Toggles the date series filter.<p>
1589     */
1590    void toggleDateSeries() {
1591
1592        setsDateSeriesHiddenFlag(!m_hideSeriesInstances);
1593        refreshResult();
1594    }
1595
1596    /**
1597     * Tries to unlocks the current resource if available.<p>
1598     */
1599    void tryUnlockCurrent() {
1600
1601        if ((m_lockAction != null) && m_lockAction.getChange().equals(CmsLockActionRecord.LockChange.locked)) {
1602            try {
1603                A_CmsUI.getCmsObject().unlockResource(m_currentResource);
1604            } catch (CmsException e) {
1605                e.printStackTrace();
1606            }
1607        }
1608    }
1609
1610    /**
1611     * Unlocks the current resource in case it has been locked by previous actions.<p>
1612     */
1613    void unlockCurrent() {
1614
1615        if (m_currentResource != null) {
1616            if ((m_lockAction != null) && m_lockAction.getChange().equals(LockChange.locked)) {
1617                CmsLockUtil.tryUnlock(A_CmsUI.getCmsObject(), m_currentResource);
1618            }
1619        }
1620        m_lockAction = null;
1621    }
1622
1623    /**
1624     * Updates the given items in the result table.<p>
1625     *
1626     * @param updatedItems the items to update
1627     */
1628    void updateItems(List<String> updatedItems) {
1629
1630        Set<CmsUUID> ids = new HashSet<CmsUUID>();
1631        for (String id : updatedItems) {
1632            ids.add(new CmsUUID(id));
1633        }
1634        m_resultTable.update(ids, false);
1635    }
1636
1637    /**
1638     * Displays the list config resources.<p>
1639     */
1640    private void displayListConfigs() {
1641
1642        CmsObject cms = A_CmsUI.getCmsObject();
1643        resetTableFilter();
1644        try {
1645            // display the search configuration overview
1646            List<CmsResource> resources = cms.readResources(
1647                "/",
1648                CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireType(
1649                    OpenCms.getResourceManager().getResourceType(RES_TYPE_LIST_CONFIG)));
1650            m_overviewTable.fillTable(cms, resources);
1651        } catch (Exception e) {
1652            CmsErrorDialog.showErrorDialog(e);
1653            LOG.error(e.getLocalizedMessage(), e);
1654        }
1655    }
1656
1657    /**
1658     * Executes a search.<p>
1659     *
1660     * @param controller the search controller
1661     * @param query the SOLR query
1662     */
1663    private void executeSearch(CmsSearchController controller, CmsSolrQuery query) {
1664
1665        CmsObject cms = A_CmsUI.getCmsObject();
1666        I_CmsSearchConfigurationCommon commonConfig = controller.getCommon().getConfig();
1667        CmsSolrIndex index = OpenCms.getSearchManager().getIndexSolr(commonConfig.getSolrIndex());
1668        try {
1669            CmsSolrResultList solrResultList = index.search(
1670                cms,
1671                query,
1672                true,
1673                null,
1674                false,
1675                CmsResourceFilter.IGNORE_EXPIRATION,
1676                commonConfig.getMaxReturnedResults());
1677            displayResult(solrResultList);
1678            CmsSearchResultWrapper searchResultWrapper = new CmsSearchResultWrapper(
1679                controller,
1680                solrResultList,
1681                query,
1682                cms,
1683                null);
1684            I_CmsSearchControllerFacetField categoriesFacetController = searchResultWrapper.getController().getFieldFacets().getFieldFacetController().get(
1685                CmsSimpleSearchConfigurationParser.FIELD_CATEGORIES);
1686            I_CmsSearchControllerFacetRange dateFacetController = searchResultWrapper.getController().getRangeFacets().getRangeFacetController().get(
1687                CmsSimpleSearchConfigurationParser.FIELD_DATE_FACET_NAME);
1688            I_CmsSearchControllerFacetField folderFacetController = searchResultWrapper.getController().getFieldFacets().getFieldFacetController().get(
1689                CmsSimpleSearchConfigurationParser.FIELD_PARENT_FOLDERS);
1690            m_resultFacets.displayFacetResult(
1691                solrResultList,
1692                categoriesFacetController.getState().getIsChecked(),
1693                dateFacetController.getState().getIsChecked(),
1694                folderFacetController.getState().getIsChecked(),
1695                A_CmsUI.getCmsObject());
1696        } catch (CmsSearchException e) {
1697            CmsErrorDialog.showErrorDialog(e);
1698
1699            LOG.error("Error executing search.", e);
1700        }
1701    }
1702
1703    /**
1704     * Returns the content locale configured for the first search root folder of the search configuration.<p>
1705     *
1706     * @param bean the search configuration data
1707     *
1708     * @return the locale
1709     */
1710    private Locale getContentLocale(CmsConfigurationBean bean) {
1711
1712        CmsObject cms = A_CmsUI.getCmsObject();
1713        if (bean.getFolders().isEmpty()) {
1714            return OpenCms.getLocaleManager().getDefaultLocale(cms, "/");
1715        } else {
1716            return OpenCms.getLocaleManager().getDefaultLocale(
1717                cms,
1718                cms.getRequestContext().removeSiteRoot(m_currentConfig.getFolders().get(0)));
1719        }
1720    }
1721
1722    /**
1723     * Resets the locale select according to the current configuration data.<p>
1724     *
1725     * @param defaultLocale the default content locale
1726     */
1727    private void resetContentLocale(Locale defaultLocale) {
1728
1729        m_resetting = true;
1730        m_localeSelect.removeAllItems();
1731        if (m_currentConfig.getFolders().isEmpty()) {
1732            m_localeSelect.addItem(defaultLocale);
1733            m_localeSelect.setItemCaption(defaultLocale, defaultLocale.getDisplayLanguage(UI.getCurrent().getLocale()));
1734        } else {
1735            for (String folder : m_currentConfig.getFolders()) {
1736                for (Locale locale : OpenCms.getLocaleManager().getAvailableLocales(A_CmsUI.getCmsObject(), folder)) {
1737                    if (!m_localeSelect.containsId(locale)) {
1738                        m_localeSelect.addItem(locale);
1739                        m_localeSelect.setItemCaption(locale, locale.getDisplayLanguage(UI.getCurrent().getLocale()));
1740                    }
1741                }
1742            }
1743        }
1744        m_localeSelect.setValue(defaultLocale);
1745        m_localeSelect.setEnabled(m_localeSelect.getItemIds().size() > 1);
1746        m_resetting = false;
1747    }
1748
1749    /**
1750     * Resets the table filter.<p>
1751     */
1752    private void resetTableFilter() {
1753
1754        m_resetting = true;
1755        m_tableFilter.clear();
1756        m_resetting = false;
1757    }
1758
1759    /**
1760     * Resets the text search input.<p>
1761     */
1762    private void resetTextSearch() {
1763
1764        m_resetting = true;
1765        m_textSearch.clear();
1766        m_resetting = false;
1767    }
1768
1769    /**
1770     * Sets options which are specific to the backend list manager on the cnofiguration parser.<p>
1771     *
1772     * @param configParser the configuration parser
1773     * @param locale the search locale
1774     */
1775    private void setBackendSpecificOptions(CmsSimpleSearchConfigurationParser configParser, Locale locale) {
1776
1777        configParser.setSearchLocale(locale);
1778        configParser.setIgnoreBlacklist(true);
1779        configParser.setPagination(PAGINATION);
1780    }
1781}