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_CmsSearchConfigurationPagination;
046import org.opencms.jsp.search.config.parser.CmsSimpleSearchConfigurationParser;
047import org.opencms.jsp.search.config.parser.CmsSimpleSearchConfigurationParser.SortOption;
048import org.opencms.jsp.search.controller.CmsSearchController;
049import org.opencms.jsp.search.controller.I_CmsSearchControllerFacetField;
050import org.opencms.jsp.search.controller.I_CmsSearchControllerFacetRange;
051import org.opencms.jsp.search.result.CmsSearchResultWrapper;
052import org.opencms.jsp.search.state.I_CmsSearchStateFacet;
053import org.opencms.loader.CmsLoaderException;
054import org.opencms.lock.CmsLockActionRecord;
055import org.opencms.lock.CmsLockActionRecord.LockChange;
056import org.opencms.lock.CmsLockUtil;
057import org.opencms.main.CmsException;
058import org.opencms.main.CmsLog;
059import org.opencms.main.OpenCms;
060import org.opencms.relations.CmsLink;
061import org.opencms.search.CmsSearchException;
062import org.opencms.search.CmsSearchResource;
063import org.opencms.search.fields.CmsSearchField;
064import org.opencms.search.solr.CmsSolrIndex;
065import org.opencms.search.solr.CmsSolrQuery;
066import org.opencms.search.solr.CmsSolrResultList;
067import org.opencms.ui.A_CmsUI;
068import org.opencms.ui.CmsVaadinUtils;
069import org.opencms.ui.FontOpenCms;
070import org.opencms.ui.I_CmsDialogContext;
071import org.opencms.ui.I_CmsDialogContext.ContextType;
072import org.opencms.ui.I_CmsUpdateListener;
073import org.opencms.ui.actions.A_CmsWorkplaceAction;
074import org.opencms.ui.actions.CmsContextMenuActionItem;
075import org.opencms.ui.actions.CmsDeleteDialogAction;
076import org.opencms.ui.actions.CmsEditDialogAction;
077import org.opencms.ui.actions.CmsResourceInfoAction;
078import org.opencms.ui.apps.A_CmsWorkplaceApp;
079import org.opencms.ui.apps.CmsAppView;
080import org.opencms.ui.apps.CmsAppView.CacheStatus;
081import org.opencms.ui.apps.CmsAppWorkplaceUi;
082import org.opencms.ui.apps.CmsEditor;
083import org.opencms.ui.apps.CmsEditorConfiguration;
084import org.opencms.ui.apps.CmsFileExplorer;
085import org.opencms.ui.apps.CmsFileExplorerSettings;
086import org.opencms.ui.apps.I_CmsAppUIContext;
087import org.opencms.ui.apps.I_CmsCachableApp;
088import org.opencms.ui.apps.I_CmsContextProvider;
089import org.opencms.ui.apps.Messages;
090import org.opencms.ui.apps.lists.CmsOptionDialog.I_OptionHandler;
091import org.opencms.ui.apps.lists.daterestrictions.CmsDateRestrictionParser;
092import org.opencms.ui.apps.lists.daterestrictions.I_CmsListDateRestriction;
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.CmsToolBar;
102import org.opencms.ui.components.I_CmsWindowCloseListener;
103import org.opencms.ui.components.OpenCmsTheme;
104import org.opencms.ui.components.extensions.CmsGwtDialogExtension;
105import org.opencms.ui.contextmenu.CmsMenuItemVisibilityMode;
106import org.opencms.ui.contextmenu.CmsResourceContextMenuBuilder;
107import org.opencms.ui.contextmenu.I_CmsContextMenuItem;
108import org.opencms.ui.contextmenu.I_CmsContextMenuItemProvider;
109import org.opencms.util.CmsStringUtil;
110import org.opencms.util.CmsUUID;
111import org.opencms.workplace.editors.directedit.CmsDateSeriesEditHandler;
112import org.opencms.workplace.editors.directedit.I_CmsEditHandler;
113import org.opencms.workplace.explorer.CmsResourceUtil;
114import org.opencms.xml.containerpage.CmsContainerElementBean;
115import org.opencms.xml.content.CmsXmlContent;
116import org.opencms.xml.content.CmsXmlContentFactory;
117import org.opencms.xml.content.CmsXmlContentValueLocation;
118import org.opencms.xml.types.CmsXmlDisplayFormatterValue;
119import org.opencms.xml.types.CmsXmlVfsFileValue;
120import org.opencms.xml.types.I_CmsXmlContentValue;
121
122import java.util.ArrayList;
123import java.util.Arrays;
124import java.util.Collection;
125import java.util.Collections;
126import java.util.Date;
127import java.util.HashMap;
128import java.util.HashSet;
129import java.util.LinkedHashMap;
130import java.util.List;
131import java.util.Locale;
132import java.util.Map;
133import java.util.Set;
134
135import org.apache.commons.logging.Log;
136
137import com.vaadin.navigator.View;
138import com.vaadin.navigator.ViewChangeListener;
139import com.vaadin.server.Sizeable.Unit;
140import com.vaadin.ui.Button;
141import com.vaadin.ui.Button.ClickEvent;
142import com.vaadin.ui.Button.ClickListener;
143import com.vaadin.ui.Component;
144import com.vaadin.ui.HorizontalSplitPanel;
145import com.vaadin.ui.UI;
146import com.vaadin.ui.Window;
147import com.vaadin.ui.themes.ValoTheme;
148import com.vaadin.v7.data.Item;
149import com.vaadin.v7.data.Property.ValueChangeEvent;
150import com.vaadin.v7.data.Property.ValueChangeListener;
151import com.vaadin.v7.event.FieldEvents.TextChangeEvent;
152import com.vaadin.v7.event.FieldEvents.TextChangeListener;
153import com.vaadin.v7.ui.AbstractSelect.ItemDescriptionGenerator;
154import com.vaadin.v7.ui.ComboBox;
155import com.vaadin.v7.ui.Table;
156import com.vaadin.v7.ui.Table.CellStyleGenerator;
157import com.vaadin.v7.ui.TextField;
158
159/**
160 * Manager for list configuration files.<p>
161 */
162@SuppressWarnings("deprecation")
163public class CmsListManager extends A_CmsWorkplaceApp
164implements I_ResourcePropertyProvider, I_CmsContextProvider, ViewChangeListener, I_CmsWindowCloseListener,
165I_CmsCachableApp {
166
167    /**
168     * Enum representing how selected categories should be combined in a search.<p>
169     */
170    public static enum CategoryMode {
171        /** Combine categories with AND. */
172        AND,
173
174        /** Combine categories with OR. */
175        OR;
176    }
177
178    /**
179     * The list configuration data.<p>
180     */
181    public static class ListConfigurationBean {
182
183        /** The additional content parameters. */
184        private Map<String, String> m_additionalParameters;
185
186        /** The resource blacklist. */
187        private List<CmsUUID> m_blacklist;
188
189        /** The categories. */
190        private List<String> m_categories;
191
192        /** The category mode. */
193        private CategoryMode m_categoryMode;
194
195        /** The date restriction. */
196        private I_CmsListDateRestriction m_dateRestriction;
197
198        /** The display types. */
199        private List<String> m_dislayTypes;
200
201        /** The folders. */
202        private List<String> m_folders;
203
204        /** Search parameters by configuration node name. */
205        private Map<String, String> m_parameterFields;
206
207        /**
208         * Constructor.<p>
209         */
210        public ListConfigurationBean() {
211
212            m_parameterFields = new HashMap<String, String>();
213        }
214
215        /**
216         * Returns the additional content parameters.<p>
217         *
218         * @return the additional content parameters
219         */
220        public Map<String, String> getAdditionalParameters() {
221
222            return m_additionalParameters;
223        }
224
225        /**
226         * Returns the black list.<p>
227         *
228         * @return the black list
229         */
230        public List<CmsUUID> getBlacklist() {
231
232            return m_blacklist;
233        }
234
235        /**
236         * Returns the categories.<p>
237         *
238         * @return the categories
239         */
240        public List<String> getCategories() {
241
242            return m_categories;
243        }
244
245        /**
246         * Gets the category mode.<p>
247         *
248         * @return the category mode
249         */
250        public CategoryMode getCategoryMode() {
251
252            return m_categoryMode;
253        }
254
255        /**
256         * Gets the date restriction.<p>
257         *
258         * @return the date restriction
259         */
260        public I_CmsListDateRestriction getDateRestriction() {
261
262            return m_dateRestriction;
263        }
264
265        /**
266         * Returns the display types.<p>
267         *
268         * @return the display types
269         */
270        public List<String> getDisplayTypes() {
271
272            return m_dislayTypes;
273        }
274
275        /**
276         * Gets the filter query.<p>
277         *
278         * @return the filter query
279         */
280        public String getFilterQuery() {
281
282            return m_parameterFields.get(N_FILTER_QUERY);
283        }
284
285        /**
286         * Returns the folders.<p>
287         *
288         * @return the folders
289         */
290        public List<String> getFolders() {
291
292            return m_folders;
293        }
294
295        /**
296         * Returns the parameter map.<p>
297         *
298         * @return the parameters
299         */
300        public Map<String, String> getParameters() {
301
302            return m_parameterFields;
303        }
304
305        /**
306         * Returns the parameter by name.<p>
307         *
308         * @param key the parameter name
309         *
310         * @return the parameter value
311         */
312        public String getParameterValue(String key) {
313
314            return m_parameterFields.get(key);
315        }
316
317        /**
318         * Gets the sort order.<p>
319         *
320         * @return the sort order
321         */
322        public String getSortOrder() {
323
324            return getParameterValue(N_SORT_ORDER);
325        }
326
327        /**
328         * Returns the search types.<p>
329         *
330         * @return the search types
331         */
332        public List<String> getTypes() {
333
334            List<String> result = new ArrayList<String>();
335            if (m_dislayTypes != null) {
336                for (String displayType : m_dislayTypes) {
337                    String type = displayType;
338                    if (type.contains(CmsXmlDisplayFormatterValue.SEPARATOR)) {
339                        type = type.substring(0, type.indexOf(CmsXmlDisplayFormatterValue.SEPARATOR));
340                    }
341                    if (!result.contains(type)) {
342                        result.add(type);
343                    }
344                }
345            }
346            return result;
347        }
348
349        /**
350         * Returns the 'show expired' setting.<p>
351         *
352         * @return the 'show expired' setting
353         */
354        public boolean isShowExpired() {
355
356            return Boolean.parseBoolean(m_parameterFields.get(N_SHOW_EXPIRED));
357
358        }
359
360        /**
361         * Sets the additional content parameters.<p>
362         *
363         * @param additionalParameters the additional content parameters to set
364         */
365        public void setAdditionalParameters(Map<String, String> additionalParameters) {
366
367            m_additionalParameters = additionalParameters;
368        }
369
370        /**
371         * Sets the blacklist.<p>
372         *
373         * @param blacklist the blacklist
374         */
375        public void setBlacklist(List<CmsUUID> blacklist) {
376
377            m_blacklist = blacklist;
378        }
379
380        /**
381         * Sets the categories.<p>
382         *
383         * @param categories the categories
384         */
385        public void setCategories(List<String> categories) {
386
387            m_categories = categories;
388        }
389
390        /**
391         * Sets the category mode.<p>
392         *
393         * @param categoryMode the category mode to set
394         */
395        public void setCategoryMode(CategoryMode categoryMode) {
396
397            m_categoryMode = categoryMode;
398        }
399
400        /**
401         * Sets the date restrictions.<p>
402         *
403         * @param restriction the date restrictions
404         */
405        public void setDateRestriction(I_CmsListDateRestriction restriction) {
406
407            m_dateRestriction = restriction;
408        }
409
410        /**
411         * Sets the display types.<p>
412         *
413         * @param displayTypes the display types
414         */
415        public void setDisplayTypes(List<String> displayTypes) {
416
417            m_dislayTypes = displayTypes;
418        }
419
420        /**
421         * Sets the folders.<p>
422         *
423         * @param folders the folders
424         */
425        public void setFolders(List<String> folders) {
426
427            m_folders = folders;
428        }
429
430        /**
431         * Sets the parameter by name.<p>
432         *
433         * @param name the parameter name
434         * @param value the parameter value
435         */
436        public void setParameterValue(String name, String value) {
437
438            m_parameterFields.put(name, value);
439
440        }
441    }
442
443    /**
444     * Extended dialog context.<p>
445     */
446    protected class DialogContext extends CmsFileTableDialogContext {
447
448        /** The selected table items. */
449        private List<Item> m_selectedItems;
450
451        /**
452         * Constructor.<p>
453         *
454         * @param appId the app id
455         * @param contextType the context type
456         * @param fileTable the file table instance
457         * @param resources the list of selected resources
458         */
459        public DialogContext(
460            String appId,
461            ContextType contextType,
462            CmsFileTable fileTable,
463            List<CmsResource> resources) {
464
465            super(appId, contextType, fileTable, resources);
466        }
467
468        /**
469         * @see org.opencms.ui.components.CmsFileTableDialogContext#finish(java.util.Collection)
470         */
471        @Override
472        public void finish(Collection<CmsUUID> ids) {
473
474            if (m_selectedItems == null) {
475                super.finish(ids);
476            } else {
477                refreshResult();
478                closeWindow();
479            }
480        }
481
482        /**
483         * Returns the selected table items.<p>
484         *
485         * @return the selected table items
486         */
487        public List<Item> getSelectedItems() {
488
489            return m_selectedItems;
490        }
491
492        /**
493         * Sets the table items.<p>
494         *
495         * @param items the table items
496         */
497        public void setSelectedItems(List<Item> items) {
498
499            m_selectedItems = items;
500        }
501    }
502
503    /**
504     * Overrides the standard delete action to enable use of edit handlers.<p>
505     */
506    class DeleteAction extends CmsDeleteDialogAction {
507
508        /**
509         * @see org.opencms.ui.actions.CmsDeleteDialogAction#executeAction(org.opencms.ui.I_CmsDialogContext)
510         */
511        @Override
512        public void executeAction(final I_CmsDialogContext context) {
513
514            final CmsResource resource = context.getResources().get(0);
515            I_CmsResourceType resourceType = OpenCms.getResourceManager().getResourceType(resource);
516            if ((resourceType instanceof CmsResourceTypeXmlContent)
517                && (((CmsResourceTypeXmlContent)resourceType).getEditHandler(context.getCms()) != null)) {
518                final I_CmsEditHandler handler = ((CmsResourceTypeXmlContent)resourceType).getEditHandler(
519                    context.getCms());
520                final CmsContainerElementBean elementBean = getElementForEditHandler((DialogContext)context);
521                CmsDialogOptions options = handler.getDeleteOptions(
522                    context.getCms(),
523                    elementBean,
524                    null,
525                    Collections.<String, String[]> emptyMap());
526                if (options == null) {
527                    super.executeAction(context);
528                } else if (options.getOptions().size() == 1) {
529                    deleteForOption(resource, elementBean, options.getOptions().get(0).getValue(), handler, context);
530                } else {
531                    Window window = CmsBasicDialog.prepareWindow();
532                    window.setCaption(options.getTitle());
533                    CmsOptionDialog dialog = new CmsOptionDialog(resource, options, new I_OptionHandler() {
534
535                        public void handleOption(String option) {
536
537                            deleteForOption(resource, elementBean, option, handler, context);
538                        }
539                    }, null, window);
540                    window.setContent(dialog);
541                    CmsAppWorkplaceUi.get().addWindow(window);
542                    dialog.initActionHandler(window);
543
544                }
545            } else {
546                super.executeAction(context);
547            }
548        }
549
550        /**
551         * Deletes with the given option.<p>
552         *
553         * @param resource the resource to delete
554         * @param elementBean the element bean
555         * @param deleteOption the delete option
556         * @param editHandler edit handler
557         * @param context the dialog context
558         */
559        void deleteForOption(
560            CmsResource resource,
561            CmsContainerElementBean elementBean,
562            String deleteOption,
563            I_CmsEditHandler editHandler,
564            I_CmsDialogContext context) {
565
566            try {
567                editHandler.handleDelete(context.getCms(), elementBean, deleteOption, null, null);
568            } catch (CmsException e) {
569                CmsErrorDialog.showErrorDialog(e);
570            }
571        }
572    }
573
574    /**
575     * Overrides the standard edit action to enable use of edit handlers.<p>
576     */
577    class EditAction extends CmsEditDialogAction {
578
579        /**
580         * @see org.opencms.ui.actions.CmsEditDialogAction#executeAction(org.opencms.ui.I_CmsDialogContext)
581         */
582        @Override
583        public void executeAction(final I_CmsDialogContext context) {
584
585            final CmsResource resource = context.getResources().get(0);
586            I_CmsResourceType resourceType = OpenCms.getResourceManager().getResourceType(resource);
587            if ((resourceType instanceof CmsResourceTypeXmlContent)
588                && (((CmsResourceTypeXmlContent)resourceType).getEditHandler(context.getCms()) != null)) {
589                final I_CmsEditHandler handler = ((CmsResourceTypeXmlContent)resourceType).getEditHandler(
590                    context.getCms());
591                final CmsContainerElementBean elementBean = getElementForEditHandler((DialogContext)context);
592                CmsDialogOptions options = handler.getEditOptions(
593                    context.getCms(),
594                    elementBean,
595                    null,
596                    Collections.<String, String[]> emptyMap(),
597                    true);
598                if (options == null) {
599                    super.executeAction(context);
600                } else if (options.getOptions().size() == 1) {
601                    editForOption(resource, elementBean, options.getOptions().get(0).getValue(), handler, context);
602                } else {
603                    Window window = CmsBasicDialog.prepareWindow();
604                    window.setCaption(options.getTitle());
605                    CmsOptionDialog dialog = new CmsOptionDialog(resource, options, new I_OptionHandler() {
606
607                        public void handleOption(String option) {
608
609                            editForOption(resource, elementBean, option, handler, context);
610                        }
611                    }, null, window);
612                    window.setContent(dialog);
613                    CmsAppWorkplaceUi.get().addWindow(window);
614                    dialog.initActionHandler(window);
615
616                }
617            } else {
618                super.executeAction(context);
619            }
620        }
621
622        /**
623         * Calls the editor with the given option.<p>
624         *
625         * @param resource the resource to delete
626         * @param elementBean the element bean
627         * @param editOption the edit option
628         * @param editHandler edit handler
629         * @param context the dialog context
630         */
631        void editForOption(
632            CmsResource resource,
633            CmsContainerElementBean elementBean,
634            String editOption,
635            I_CmsEditHandler editHandler,
636            I_CmsDialogContext context) {
637
638            try {
639                CmsUUID id = editHandler.prepareForEdit(
640                    context.getCms(),
641                    elementBean,
642                    editOption,
643                    null,
644                    Collections.<String, String[]> emptyMap());
645                if (resource.getStructureId().equals(id)) {
646                    super.executeAction(context);
647                } else if (id != null) {
648                    CmsFileTableDialogContext changedContext = new CmsFileTableDialogContext(
649                        CmsProjectManagerConfiguration.APP_ID,
650                        ContextType.fileTable,
651                        m_resultTable,
652                        Collections.singletonList(context.getCms().readResource(id)));
653                    super.executeAction(changedContext);
654                }
655            } catch (CmsException e) {
656                CmsErrorDialog.showErrorDialog(e);
657            }
658        }
659    }
660
661    /** SOLR field name. */
662    public static final String FIELD_CATEGORIES = "category_exact";
663
664    /** SOLR field name. */
665    public static final String FIELD_DATE = "instancedate_%s_dt";
666
667    /** SOLR field name. */
668    public static final String FIELD_DATE_FACET_NAME = "instancedate";
669
670    /** SOLR field name. */
671    public static final String FIELD_PARENT_FOLDERS = "parent-folders";
672
673    /** List configuration node name and field key. */
674    public static final String N_BLACKLIST = "Blacklist";
675
676    /** List configuration node name and field key. */
677    public static final String N_CATEGORY = "Category";
678
679    /** List configuration node name for the category mode. */
680    public static final String N_CATEGORY_MODE = "CategoryMode";
681
682    /** XML content node name. */
683    public static final String N_DATE_RESTRICTION = "DateRestriction";
684
685    /** List configuration node name and field key. */
686    public static final String N_DISPLAY_TYPE = "TypesToCollect";
687
688    /** List configuration node name and field key. */
689    public static final String N_FILTER_QUERY = "FilterQuery";
690
691    /** List configuration node name and field key. */
692    public static final String N_KEY = "Key";
693
694    /** List configuration node name and field key. */
695    public static final String N_PARAMETER = "Parameter";
696
697    /** List configuration node name and field key. */
698    public static final String N_SEARCH_FOLDER = "SearchFolder";
699
700    /** List configuration node name and field key. */
701    public static final String N_SHOW_EXPIRED = "ShowExpired";
702
703    /** List configuration node name and field key. */
704    public static final String N_SORT_ORDER = "SortOrder";
705
706    /** List configuration node name and field key. */
707    public static final String N_TITLE = "Title";
708
709    /** List configuration node name and field key. */
710    public static final String N_VALUE = "Value";
711
712    /** List configuration node name and field key. */
713    public static final String PARAM_LOCALE = "locale";
714
715    /** The parameter fields. */
716    public static final String[] PARAMETER_FIELDS = new String[] {
717        N_TITLE,
718        N_CATEGORY,
719        N_FILTER_QUERY,
720        N_SORT_ORDER,
721        N_SHOW_EXPIRED};
722
723    /** The view content list path name. */
724    public static final String PATH_NAME_VIEW = "view";
725
726    /** The list configuration resource type name. */
727    public static final String RES_TYPE_LIST_CONFIG = "listconfig";
728
729    /** The blacklisted table column property id. */
730    protected static final CmsResourceTableProperty BLACKLISTED_PROPERTY = new CmsResourceTableProperty(
731        "BLACKLISTED",
732        Boolean.class,
733        Boolean.FALSE,
734        Messages.GUI_LISTMANAGER_COLUMN_BLACKLISTED_0,
735        true,
736        0,
737        110);
738
739    /** The date series info table column property id. */
740    protected static final CmsResourceTableProperty INFO_PROPERTY = new CmsResourceTableProperty(
741        "INFO_PROPERTY",
742        String.class,
743        null,
744        null,
745        true,
746        1,
747        0);
748
749    /** The date series info label table column property id. */
750    protected static final CmsResourceTableProperty INFO_PROPERTY_LABEL = new CmsResourceTableProperty(
751        "INFO_PROPERTY_LABEL",
752        String.class,
753        null,
754        Messages.GUI_LISTMANAGER_COLUMN_INFO_0,
755        true,
756        0,
757        110);
758
759    /** The blacklisted table column property id. */
760    protected static final CmsResourceTableProperty INSTANCEDATE_PROPERTY = new CmsResourceTableProperty(
761        "INSTANCEDATE_PROPERTY",
762        Date.class,
763        null,
764        Messages.GUI_LISTMANAGER_COLUMN_INSTANCEDATE_0,
765        true,
766        0,
767        145);
768
769    /** The available sort options. */
770    protected static final String[][] SORT_OPTIONS = new String[][] {
771        {
772            SortOption.DATE_ASC.toString(),
773            SortOption.DATE_DESC.toString(),
774            SortOption.TITLE_ASC.toString(),
775            SortOption.TITLE_DESC.toString(),
776            SortOption.ORDER_ASC.toString(),
777            SortOption.ORDER_DESC.toString()},
778        {
779            Messages.GUI_LISTMANAGER_SORT_DATE_ASC_0,
780            Messages.GUI_LISTMANAGER_SORT_DATE_DESC_0,
781            Messages.GUI_LISTMANAGER_SORT_TITLE_ASC_0,
782            Messages.GUI_LISTMANAGER_SORT_TITLE_DESC_0,
783            Messages.GUI_LISTMANAGER_SORT_ORDER_ASC_0,
784            Messages.GUI_LISTMANAGER_SORT_ORDER_DESC_0}};
785
786    /** The month name abbreviations. */
787    static final String[] MONTHS = new String[] {
788        "JAN",
789        "FEB",
790        "MAR",
791        "APR",
792        "MAY",
793        "JUN",
794        "JUL",
795        "AUG",
796        "SEP",
797        "OCT",
798        "NOV",
799        "DEC"};
800
801    /** The logger for this class. */
802    private static final Log LOG = CmsLog.getLog(CmsListManager.class.getName());
803
804    /** Default backend pagination. */
805    private static final I_CmsSearchConfigurationPagination PAGINATION = new CmsSearchConfigurationPagination(
806        null,
807        Integer.valueOf(10000),
808        Integer.valueOf(1));
809
810    /** The serial version id. */
811    private static final long serialVersionUID = -25954374225590319L;
812
813    /** The current list configuration data. */
814    ListConfigurationBean m_currentConfig;
815
816    /** The current list configuration resource. */
817    CmsResource m_currentResource;
818
819    /** The result table. */
820    CmsResultTable m_resultTable;
821
822    /** The create new button. */
823    private Button m_createNewButton;
824
825    /** The current search parser. */
826    private CmsSimpleSearchConfigurationParser m_currentConfigParser;
827
828    /** The current app state. */
829    private String m_currentState;
830
831    /** The current edit dialog window. */
832    private Window m_dialogWindow;
833
834    /** The edit current configuration button. */
835    private Button m_editCurrentButton;
836
837    /** Indicates multiple instances of a series are present in the current search result. */
838    private boolean m_hasSeriesInstances;
839
840    /** Indicates series types are present in the current search result. */
841    private boolean m_hasSeriesType;
842
843    /** Flag indicating individual instances of a date series should be hidden. */
844    private boolean m_hideSeriesInstances;
845
846    /** The info button. */
847    private Button m_infoButton;
848
849    /** Indicates if the overview list is shown. */
850    private boolean m_isOverView;
851
852    /** The locale select. */
853    private ComboBox m_localeSelect;
854
855    /** The current lock action. */
856    private CmsLockActionRecord m_lockAction;
857
858    /** The list configurations overview table. */
859    private CmsFileTable m_overviewTable;
860
861    /** The publish button. */
862    private Button m_publishButton;
863
864    /** The resetting flag. */
865    private boolean m_resetting;
866
867    /** The facet result display. */
868    private CmsResultFacets m_resultFacets;
869
870    /** The mail layout. */
871    private HorizontalSplitPanel m_resultLayout;
872
873    /** The sort select. */
874    private ComboBox m_resultSorter;
875
876    /** The table filter input. */
877    private TextField m_tableFilter;
878
879    /** The text search input. */
880    private TextField m_textSearch;
881
882    /** The toggle date series display. */
883    private Button m_toggleSeriesButton;
884
885    /**
886     * Parses the list configuration resource.<p>
887     *
888     * @param cms the CMS context to use
889     * @param res the list configuration resource
890     *
891     * @return the configuration data bean
892     */
893    public static ListConfigurationBean parseListConfiguration(CmsObject cms, CmsResource res) {
894
895        ListConfigurationBean result = new ListConfigurationBean();
896        try {
897            CmsFile configFile = cms.readFile(res);
898            CmsXmlContent content = CmsXmlContentFactory.unmarshal(cms, configFile);
899            Locale locale = CmsLocaleManager.MASTER_LOCALE;
900
901            if (!content.hasLocale(locale)) {
902                locale = content.getLocales().get(0);
903            }
904            for (String field : PARAMETER_FIELDS) {
905                String val = content.getStringValue(cms, field, locale);
906                if (N_CATEGORY.equals(field)) {
907                    if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(val)) {
908                        result.setCategories(Arrays.asList(val.split(",")));
909                    } else {
910                        result.setCategories(Collections.<String> emptyList());
911                    }
912                } else {
913                    result.setParameterValue(field, val);
914                }
915            }
916
917            I_CmsXmlContentValue restrictValue = content.getValue(N_DATE_RESTRICTION, locale);
918            if (restrictValue != null) {
919                CmsDateRestrictionParser parser = new CmsDateRestrictionParser(cms);
920                I_CmsListDateRestriction restriction = parser.parse(new CmsXmlContentValueLocation(restrictValue));
921                if (restriction == null) {
922                    LOG.warn(
923                        "Improper date restriction configuration in content "
924                            + content.getFile().getRootPath()
925                            + ", online="
926                            + cms.getRequestContext().getCurrentProject().isOnlineProject());
927                }
928                result.setDateRestriction(restriction);
929            }
930
931            I_CmsXmlContentValue categoryModeVal = content.getValue(N_CATEGORY_MODE, locale);
932            CategoryMode categoryMode = CategoryMode.OR;
933            if (categoryModeVal != null) {
934                try {
935                    categoryMode = CategoryMode.valueOf(categoryModeVal.getStringValue(cms));
936                } catch (Exception e) {
937                    LOG.error(e.getLocalizedMessage(), e);
938                }
939            }
940            result.setCategoryMode(categoryMode);
941
942            LinkedHashMap<String, String> parameters = new LinkedHashMap<String, String>();
943            for (I_CmsXmlContentValue parameter : content.getValues(N_PARAMETER, locale)) {
944                I_CmsXmlContentValue keyVal = content.getValue(parameter.getPath() + "/" + N_KEY, locale);
945                I_CmsXmlContentValue valueVal = content.getValue(parameter.getPath() + "/" + N_VALUE, locale);
946                if ((keyVal != null)
947                    && CmsStringUtil.isNotEmptyOrWhitespaceOnly(keyVal.getStringValue(cms))
948                    && (valueVal != null)) {
949                    parameters.put(keyVal.getStringValue(cms), valueVal.getStringValue(cms));
950                }
951            }
952            result.setAdditionalParameters(parameters);
953            List<String> displayTypes = new ArrayList<String>();
954            List<I_CmsXmlContentValue> typeValues = content.getValues(N_DISPLAY_TYPE, locale);
955            if (!typeValues.isEmpty()) {
956                for (I_CmsXmlContentValue value : typeValues) {
957                    displayTypes.add(value.getStringValue(cms));
958                }
959            }
960            result.setDisplayTypes(displayTypes);
961            List<String> folders = new ArrayList<String>();
962            List<I_CmsXmlContentValue> folderValues = content.getValues(N_SEARCH_FOLDER, locale);
963            if (!folderValues.isEmpty()) {
964                for (I_CmsXmlContentValue value : folderValues) {
965                    CmsLink val = ((CmsXmlVfsFileValue)value).getLink(cms);
966                    if (val != null) {
967                        // we are using root paths
968                        folders.add(cms.getRequestContext().addSiteRoot(val.getSitePath(cms)));
969                    }
970                }
971            }
972            result.setFolders(folders);
973            List<CmsUUID> blackList = new ArrayList<CmsUUID>();
974            List<I_CmsXmlContentValue> blacklistValues = content.getValues(N_BLACKLIST, locale);
975            if (!blacklistValues.isEmpty()) {
976                for (I_CmsXmlContentValue value : blacklistValues) {
977                    CmsLink link = ((CmsXmlVfsFileValue)value).getLink(cms);
978                    if (link != null) {
979                        blackList.add(link.getStructureId());
980                    }
981                }
982            }
983            result.setBlacklist(blackList);
984        } catch (CmsException e) {
985            e.printStackTrace();
986        }
987        return result;
988    }
989
990    /**
991     * @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)
992     */
993    @Override
994    public void addItemProperties(Item resourceItem, CmsObject cms, CmsResource resource, Locale locale) {
995
996        if ((m_currentConfig != null) && (resourceItem.getItemProperty(CmsListManager.BLACKLISTED_PROPERTY) != null)) {
997            resourceItem.getItemProperty(CmsListManager.BLACKLISTED_PROPERTY).setValue(
998                Boolean.valueOf(m_currentConfig.getBlacklist().contains(resource.getStructureId())));
999        }
1000        if ((m_currentConfig != null)
1001            && (resourceItem.getItemProperty(CmsResourceTableProperty.PROPERTY_TITLE) != null)) {
1002            CmsResourceUtil resUtil = new CmsResourceUtil(cms, resource);
1003            String title = resUtil.getGalleryTitle((Locale)m_localeSelect.getValue());
1004            if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(title)) {
1005                resourceItem.getItemProperty(CmsResourceTableProperty.PROPERTY_TITLE).setValue(title);
1006            }
1007        }
1008        if ((resource instanceof CmsSearchResource)
1009            && (resourceItem.getItemProperty(CmsListManager.INFO_PROPERTY_LABEL) != null)) {
1010            String seriesType = ((CmsSearchResource)resource).getField(CmsSearchField.FIELD_SERIESDATES_TYPE);
1011            resourceItem.getItemProperty(CmsListManager.INFO_PROPERTY_LABEL).setValue(
1012                CmsVaadinUtils.getMessageText(
1013                    "GUI_LISTMANAGER_SERIES_TYPE_" + (seriesType == null ? "DEFAULT" : seriesType) + "_0"));
1014            resourceItem.getItemProperty(CmsListManager.INFO_PROPERTY).setValue(seriesType);
1015
1016        }
1017        if ((resource instanceof CmsSearchResource)
1018            && (resourceItem.getItemProperty(CmsListManager.INSTANCEDATE_PROPERTY) != null)) {
1019            Date date = ((CmsSearchResource)resource).getDateField(m_resultTable.getDateFieldKey());
1020            resourceItem.getItemProperty(CmsListManager.INSTANCEDATE_PROPERTY).setValue(date);
1021        }
1022    }
1023
1024    /**
1025     * @see com.vaadin.navigator.ViewChangeListener#afterViewChange(com.vaadin.navigator.ViewChangeListener.ViewChangeEvent)
1026     */
1027    @Override
1028    public void afterViewChange(ViewChangeEvent event) {
1029
1030        // nothing to do
1031    }
1032
1033    /**
1034     * @see com.vaadin.navigator.ViewChangeListener#beforeViewChange(com.vaadin.navigator.ViewChangeListener.ViewChangeEvent)
1035     */
1036    @Override
1037    public boolean beforeViewChange(ViewChangeEvent event) {
1038
1039        unlockCurrent();
1040        return true;
1041    }
1042
1043    /**
1044     * @see org.opencms.ui.apps.I_CmsContextProvider#getDialogContext()
1045     */
1046    @Override
1047    public I_CmsDialogContext getDialogContext() {
1048
1049        CmsFileTable table = isOverView() ? m_overviewTable : m_resultTable;
1050        List<CmsResource> resources = table.getSelectedResources();
1051        DialogContext context = new DialogContext(
1052            CmsProjectManagerConfiguration.APP_ID,
1053            ContextType.fileTable,
1054            table,
1055            resources);
1056        if (!isOverView()) {
1057            context.setSelectedItems(m_resultTable.getSelectedItems());
1058        }
1059        return context;
1060    }
1061
1062    /**
1063     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#initUI(org.opencms.ui.apps.I_CmsAppUIContext)
1064     */
1065    @Override
1066    public void initUI(I_CmsAppUIContext uiContext) {
1067
1068        super.initUI(uiContext);
1069        m_publishButton = CmsToolBar.createButton(
1070            FontOpenCms.PUBLISH,
1071            CmsVaadinUtils.getMessageText(Messages.GUI_PUBLISH_BUTTON_TITLE_0));
1072        if (CmsAppWorkplaceUi.isOnlineProject()) {
1073            // disable publishing in online project
1074            m_publishButton.setEnabled(false);
1075            m_publishButton.setDescription(CmsVaadinUtils.getMessageText(Messages.GUI_TOOLBAR_NOT_AVAILABLE_ONLINE_0));
1076        }
1077
1078        m_publishButton.addClickListener(new ClickListener() {
1079
1080            /** Serial version id. */
1081            private static final long serialVersionUID = 1L;
1082
1083            @Override
1084            public void buttonClick(ClickEvent event) {
1085
1086                publish();
1087            }
1088        });
1089        uiContext.addToolbarButton(m_publishButton);
1090
1091        m_editCurrentButton = CmsToolBar.createButton(
1092            FontOpenCms.PEN,
1093            CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_EDIT_CONFIG_0));
1094        m_editCurrentButton.addClickListener(new ClickListener() {
1095
1096            /** Serial version id. */
1097            private static final long serialVersionUID = 1L;
1098
1099            @Override
1100            public void buttonClick(ClickEvent event) {
1101
1102                editListConfiguration(m_currentResource);
1103            }
1104        });
1105        uiContext.addToolbarButton(m_editCurrentButton);
1106
1107        m_infoButton = CmsToolBar.createButton(
1108            FontOpenCms.INFO,
1109            CmsVaadinUtils.getMessageText(org.opencms.ui.Messages.GUI_RESOURCE_INFO_0));
1110        m_infoButton.addClickListener(new ClickListener() {
1111
1112            /** Serial version id. */
1113            private static final long serialVersionUID = 1L;
1114
1115            @Override
1116            public void buttonClick(ClickEvent event) {
1117
1118                DialogContext context = new DialogContext(
1119                    CmsProjectManagerConfiguration.APP_ID,
1120                    ContextType.fileTable,
1121                    m_resultTable,
1122                    Collections.singletonList(m_currentResource));
1123                CmsResourceInfoAction action = new CmsResourceInfoAction();
1124                action.openDialog(context, CmsResourceStatusTabId.tabRelationsTo.name());
1125            }
1126        });
1127        uiContext.addToolbarButton(m_infoButton);
1128
1129        m_toggleSeriesButton = CmsToolBar.createButton(
1130            FontOpenCms.LIST,
1131            CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_TOGGLE_SERIES_BUTTON_0));
1132        m_toggleSeriesButton.addClickListener(new ClickListener() {
1133
1134            /** Serial version id. */
1135            private static final long serialVersionUID = 1L;
1136
1137            @Override
1138            public void buttonClick(ClickEvent event) {
1139
1140                toggleDateSeries();
1141            }
1142        });
1143        uiContext.addToolbarButton(m_toggleSeriesButton);
1144
1145        m_createNewButton = CmsToolBar.createButton(
1146            FontOpenCms.WAND,
1147            CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_CREATE_NEW_0));
1148        m_createNewButton.addClickListener(new ClickListener() {
1149
1150            /** Serial version id. */
1151            private static final long serialVersionUID = 1L;
1152
1153            @Override
1154            public void buttonClick(ClickEvent event) {
1155
1156                createNew();
1157            }
1158        });
1159        uiContext.addToolbarButton(m_createNewButton);
1160
1161        m_rootLayout.setMainHeightFull(true);
1162        m_resultLayout = new HorizontalSplitPanel();
1163        m_resultLayout.setSizeFull();
1164        m_resultFacets = new CmsResultFacets(this);
1165        m_resultFacets.setWidth("100%");
1166        m_resultLayout.setFirstComponent(m_resultFacets);
1167        LinkedHashMap<CmsResourceTableProperty, Integer> tableColumns = new LinkedHashMap<CmsResourceTableProperty, Integer>();
1168        // insert columns a specific positions
1169        for (Map.Entry<CmsResourceTableProperty, Integer> columnsEntry : CmsFileTable.DEFAULT_TABLE_PROPERTIES.entrySet()) {
1170            if (columnsEntry.getKey().equals(CmsResourceTableProperty.PROPERTY_RESOURCE_NAME)) {
1171                tableColumns.put(INFO_PROPERTY_LABEL, Integer.valueOf(0));
1172            } else if (columnsEntry.getKey().equals(CmsResourceTableProperty.PROPERTY_RESOURCE_TYPE)) {
1173                tableColumns.put(INSTANCEDATE_PROPERTY, Integer.valueOf(0));
1174            }
1175            tableColumns.put(columnsEntry.getKey(), columnsEntry.getValue());
1176        }
1177        tableColumns.put(BLACKLISTED_PROPERTY, Integer.valueOf(CmsResourceTable.INVISIBLE));
1178        tableColumns.put(INFO_PROPERTY, Integer.valueOf(CmsResourceTable.INVISIBLE));
1179        m_resultTable = new CmsResultTable(null, tableColumns);
1180        m_resultTable.applyWorkplaceAppSettings();
1181        CmsResourceContextMenuBuilder menuBuilderOverView = new CmsResourceContextMenuBuilder();
1182        menuBuilderOverView.addMenuItemProvider(OpenCms.getWorkplaceAppManager().getMenuItemProvider());
1183        menuBuilderOverView.addMenuItemProvider(new I_CmsContextMenuItemProvider() {
1184
1185            @Override
1186            public List<I_CmsContextMenuItem> getMenuItems() {
1187
1188                return Arrays.<I_CmsContextMenuItem> asList(new CmsContextMenuActionItem(new CmsEditDialogAction() {
1189
1190                    @Override
1191                    public void executeAction(I_CmsDialogContext context) {
1192
1193                        editListConfiguration(context.getResources().get(0));
1194                    }
1195                }, null, 10, 1000));
1196            }
1197        });
1198        CmsResourceContextMenuBuilder menuBuilder = new CmsResourceContextMenuBuilder();
1199        menuBuilder.addMenuItemProvider(OpenCms.getWorkplaceAppManager().getMenuItemProvider());
1200        menuBuilder.addMenuItemProvider(new I_CmsContextMenuItemProvider() {
1201
1202            @Override
1203            public List<I_CmsContextMenuItem> getMenuItems() {
1204
1205                return Arrays.<I_CmsContextMenuItem> asList(new CmsContextMenuActionItem(new A_CmsWorkplaceAction() {
1206
1207                    @Override
1208                    public void executeAction(I_CmsDialogContext context) {
1209
1210                        CmsUUID structureId = context.getResources().get(0).getStructureId();
1211                        m_currentConfig.getBlacklist().add(structureId);
1212                        saveBlacklist(m_currentConfig);
1213                        context.finish(Collections.singletonList(structureId));
1214                    }
1215
1216                    @Override
1217                    public String getId() {
1218
1219                        return "hideresource";
1220                    }
1221
1222                    @Override
1223                    public String getTitleKey() {
1224
1225                        return Messages.GUI_LISTMANAGER_BLACKLIST_MENU_ENTRY_0;
1226                    }
1227
1228                    @Override
1229                    public CmsMenuItemVisibilityMode getVisibility(CmsObject cms, List<CmsResource> resources) {
1230
1231                        if ((m_currentConfig != null)
1232                            && (resources != null)
1233                            && (resources.size() == 1)
1234                            && !m_currentConfig.getBlacklist().contains(resources.get(0).getStructureId())) {
1235                            return CmsEditDialogAction.VISIBILITY.getVisibility(
1236                                cms,
1237                                Collections.singletonList(m_currentResource));
1238                        } else {
1239                            return CmsMenuItemVisibilityMode.VISIBILITY_INVISIBLE;
1240                        }
1241                    }
1242
1243                }, null, 10, 0), new CmsContextMenuActionItem(new A_CmsWorkplaceAction() {
1244
1245                    @Override
1246                    public void executeAction(I_CmsDialogContext context) {
1247
1248                        CmsUUID structureId = context.getResources().get(0).getStructureId();
1249                        m_currentConfig.getBlacklist().remove(structureId);
1250                        saveBlacklist(m_currentConfig);
1251                        context.finish(Collections.singletonList(structureId));
1252                    }
1253
1254                    @Override
1255                    public String getId() {
1256
1257                        return "showresource";
1258                    }
1259
1260                    @Override
1261                    public String getTitleKey() {
1262
1263                        return Messages.GUI_LISTMANAGER_REMOVE_FROM_BLACKLIST_MENU_ENTRY_0;
1264                    }
1265
1266                    @Override
1267                    public CmsMenuItemVisibilityMode getVisibility(CmsObject cms, List<CmsResource> resources) {
1268
1269                        if ((m_currentConfig != null)
1270                            && (resources != null)
1271                            && (resources.size() == 1)
1272                            && m_currentConfig.getBlacklist().contains(resources.get(0).getStructureId())) {
1273                            return CmsEditDialogAction.VISIBILITY.getVisibility(
1274                                cms,
1275                                Collections.singletonList(m_currentResource));
1276                        } else {
1277                            return CmsMenuItemVisibilityMode.VISIBILITY_INVISIBLE;
1278                        }
1279                    }
1280
1281                }, null, 10, 0),
1282                    new CmsContextMenuActionItem(new EditAction(), null, 10, 1000),
1283                    new CmsContextMenuActionItem(new DeleteAction(), null, 10, 1000));
1284            }
1285        });
1286        m_resultTable.setMenuBuilder(menuBuilder);
1287        m_resultTable.addAdditionalStyleGenerator(new CellStyleGenerator() {
1288
1289            private static final long serialVersionUID = 1L;
1290
1291            @Override
1292            public String getStyle(Table source, Object itemId, Object propertyId) {
1293
1294                String style = "";
1295                Item item = source.getItem(itemId);
1296                Boolean blacklisted = (Boolean)item.getItemProperty(BLACKLISTED_PROPERTY).getValue();
1297                if (blacklisted.booleanValue()) {
1298                    style += OpenCmsTheme.PROJECT_OTHER + " ";
1299                } else if (CmsResourceTableProperty.PROPERTY_TITLE.equals(propertyId)
1300                    && ((item.getItemProperty(CmsResourceTableProperty.PROPERTY_RELEASED_NOT_EXPIRED) == null)
1301                        || ((Boolean)item.getItemProperty(
1302                            CmsResourceTableProperty.PROPERTY_RELEASED_NOT_EXPIRED).getValue()).booleanValue())) {
1303                    style += OpenCmsTheme.IN_NAVIGATION + " ";
1304                }
1305                if (INFO_PROPERTY_LABEL.equals(propertyId)) {
1306                    if (blacklisted.booleanValue()) {
1307                        style += OpenCmsTheme.TABLE_COLUMN_BOX_BLACK;
1308                    } else {
1309                        Object value = item.getItemProperty(INFO_PROPERTY).getValue();
1310                        if (value == null) {
1311                            style += OpenCmsTheme.TABLE_COLUMN_BOX_GRAY;
1312                        } else {
1313                            I_CmsSerialDateValue.DateType type = I_CmsSerialDateValue.DateType.valueOf((String)value);
1314                            switch (type) {
1315                                case SERIES:
1316                                    style += OpenCmsTheme.TABLE_COLUMN_BOX_BLUE_LIGHT;
1317                                    break;
1318                                case SINGLE:
1319                                    style += OpenCmsTheme.TABLE_COLUMN_BOX_GRAY;
1320                                    break;
1321                                case EXTRACTED:
1322                                    style += OpenCmsTheme.TABLE_COLUMN_BOX_ORANGE;
1323                                    break;
1324                                default:
1325                                    break;
1326                            }
1327                        }
1328                    }
1329                }
1330                return style;
1331            }
1332        });
1333        m_resultTable.setsetItemDescriptionGenerator(new ItemDescriptionGenerator() {
1334
1335            private static final long serialVersionUID = 1L;
1336
1337            public String generateDescription(Component source, Object itemId, Object propertyId) {
1338
1339                Item item = ((Table)source).getItem(itemId);
1340                if (INFO_PROPERTY_LABEL.equals(propertyId)
1341                    && ((Boolean)item.getItemProperty(BLACKLISTED_PROPERTY).getValue()).booleanValue()) {
1342                    return CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_COLUMN_BLACKLISTED_0);
1343                }
1344                return null;
1345            }
1346        });
1347        m_resultTable.setContextProvider(this);
1348        m_resultTable.addPropertyProvider(this);
1349        m_resultTable.setSizeFull();
1350        m_resultLayout.setSecondComponent(m_resultTable);
1351        m_overviewTable = new CmsFileTable(this);
1352        m_overviewTable.applyWorkplaceAppSettings();
1353        m_overviewTable.setMenuBuilder(menuBuilderOverView);
1354        m_overviewTable.setSizeFull();
1355
1356        m_tableFilter = new TextField();
1357        m_tableFilter.setIcon(FontOpenCms.FILTER);
1358        m_tableFilter.setInputPrompt(
1359            Messages.get().getBundle(UI.getCurrent().getLocale()).key(Messages.GUI_EXPLORER_FILTER_0));
1360        m_tableFilter.addStyleName(ValoTheme.TEXTFIELD_INLINE_ICON);
1361        m_tableFilter.setWidth("200px");
1362        m_tableFilter.addTextChangeListener(new TextChangeListener() {
1363
1364            private static final long serialVersionUID = 1L;
1365
1366            @Override
1367            public void textChange(TextChangeEvent event) {
1368
1369                filterTable(event.getText());
1370
1371            }
1372        });
1373        m_infoLayout.addComponent(m_tableFilter);
1374
1375        m_localeSelect = new ComboBox();
1376        m_localeSelect.setNullSelectionAllowed(false);
1377        m_localeSelect.setWidth("100px");
1378        m_localeSelect.addValueChangeListener(new ValueChangeListener() {
1379
1380            /** Serial version id. */
1381            private static final long serialVersionUID = 1L;
1382
1383            @Override
1384            public void valueChange(ValueChangeEvent event) {
1385
1386                changeContentLocale((Locale)event.getProperty().getValue());
1387            }
1388        });
1389        m_infoLayout.addComponent(m_localeSelect);
1390
1391        m_resultSorter = new ComboBox();
1392        m_resultSorter.setNullSelectionAllowed(false);
1393        m_resultSorter.setWidth("200px");
1394        for (int i = 0; i < SORT_OPTIONS[0].length; i++) {
1395            m_resultSorter.addItem(SORT_OPTIONS[0][i]);
1396            m_resultSorter.setItemCaption(SORT_OPTIONS[0][i], CmsVaadinUtils.getMessageText(SORT_OPTIONS[1][i]));
1397        }
1398        m_resultSorter.addValueChangeListener(new ValueChangeListener() {
1399
1400            /** Serial version id. */
1401            private static final long serialVersionUID = 1L;
1402
1403            @Override
1404            public void valueChange(ValueChangeEvent event) {
1405
1406                sortResult();
1407            }
1408        });
1409        m_infoLayout.addComponent(m_resultSorter);
1410
1411        m_textSearch = new TextField();
1412        m_textSearch.setIcon(FontOpenCms.SEARCH);
1413        m_textSearch.setInputPrompt(CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_SEARCH_0));
1414        m_textSearch.addStyleName(ValoTheme.TEXTFIELD_INLINE_ICON);
1415        m_textSearch.setWidth("200px");
1416        m_textSearch.addValueChangeListener(new ValueChangeListener() {
1417
1418            /** Serial version id. */
1419            private static final long serialVersionUID = 1L;
1420
1421            @Override
1422            public void valueChange(ValueChangeEvent event) {
1423
1424                search((String)event.getProperty().getValue());
1425            }
1426        });
1427        m_infoLayout.addComponent(m_textSearch);
1428        m_resultLayout.setSecondComponent(m_resultTable);
1429        m_resultLayout.setSplitPosition(CmsFileExplorer.LAYOUT_SPLIT_POSITION, Unit.PIXELS);
1430    }
1431
1432    /**
1433     * @see org.opencms.ui.apps.I_CmsCachableApp#isCachable()
1434     */
1435    public boolean isCachable() {
1436
1437        return true;
1438    }
1439
1440    /**
1441     * @see org.opencms.ui.apps.I_CmsCachableApp#onRestoreFromCache()
1442     */
1443    public void onRestoreFromCache() {
1444
1445        if (isOverView()) {
1446            CmsFileExplorerSettings state = m_overviewTable.getTableSettings();
1447            displayListConfigs();
1448            m_overviewTable.setTableState(state);
1449            m_overviewTable.updateSorting();
1450        } else {
1451            refreshResult();
1452        }
1453    }
1454
1455    /**
1456     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#onStateChange(java.lang.String)
1457     */
1458    @Override
1459    public void onStateChange(String state) {
1460
1461        if ((m_currentState == null) || !m_currentState.equals(state)) {
1462            m_currentState = state;
1463            super.onStateChange(state);
1464        }
1465    }
1466
1467    /**
1468     * @see org.opencms.ui.components.I_CmsWindowCloseListener#onWindowClose()
1469     */
1470    @Override
1471    public void onWindowClose() {
1472
1473        unlockCurrent();
1474    }
1475
1476    /**
1477     * Saves the blacklist from the bean in the current list configuration.<p>
1478     *
1479     * @param configBean the bean whose blacklist should be saved
1480     */
1481    public void saveBlacklist(ListConfigurationBean configBean) {
1482
1483        if (m_dialogWindow != null) {
1484            m_dialogWindow.close();
1485            m_dialogWindow = null;
1486        }
1487        CmsObject cms = A_CmsUI.getCmsObject();
1488
1489        try {
1490            m_lockAction = CmsLockUtil.ensureLock(cms, m_currentResource);
1491        } catch (CmsException e) {
1492            CmsErrorDialog.showErrorDialog(e);
1493            return;
1494        }
1495
1496        try {
1497            CmsFile configFile = cms.readFile(m_currentResource);
1498            CmsXmlContent content = CmsXmlContentFactory.unmarshal(cms, configFile);
1499            // list configurations are single locale contents
1500            Locale locale = CmsLocaleManager.MASTER_LOCALE;
1501            int count = 0;
1502            while (content.hasValue(N_BLACKLIST, locale)) {
1503                content.removeValue(N_BLACKLIST, locale, 0);
1504            }
1505            for (CmsUUID hiddenId : configBean.getBlacklist()) {
1506                CmsXmlVfsFileValue contentVal;
1507                contentVal = (CmsXmlVfsFileValue)content.addValue(cms, N_BLACKLIST, locale, count);
1508                contentVal.setIdValue(cms, hiddenId);
1509                count++;
1510            }
1511            configFile.setContents(content.marshal());
1512            cms.writeFile(configFile);
1513            if (m_lockAction.getChange().equals(LockChange.locked)) {
1514                CmsLockUtil.tryUnlock(cms, configFile);
1515            }
1516        } catch (CmsException e) {
1517            e.printStackTrace();
1518        }
1519        m_currentConfig = configBean;
1520    }
1521
1522    /**
1523     * Execute a search with the given search configuration parser.<p>
1524     *
1525     * @param configParser the search configuration parser
1526     * @param resource the current configuration resource
1527     */
1528    public void search(CmsSimpleSearchConfigurationParser configParser, CmsResource resource) {
1529
1530        m_currentResource = resource;
1531        m_currentConfigParser = configParser;
1532        resetContentLocale(configParser.getSearchLocale());
1533        m_resetting = true;
1534        m_resultSorter.setValue(m_currentConfig.getParameterValue(N_SORT_ORDER));
1535        m_resetting = false;
1536
1537        search(null, null, null);
1538    }
1539
1540    /**
1541     * Updates the search result.<p>
1542     *
1543     * @param fieldFacets the field facets
1544     * @param rangeFacets the range facets
1545     */
1546    public void search(Map<String, List<String>> fieldFacets, Map<String, List<String>> rangeFacets) {
1547
1548        search(fieldFacets, rangeFacets, null);
1549    }
1550
1551    /**
1552     * Updates the search result.<p>
1553     *
1554     * @param fieldFacets the field facets
1555     * @param rangeFacets the range facets
1556     * @param additionalQuery the additional query
1557     */
1558    public void search(
1559        Map<String, List<String>> fieldFacets,
1560        Map<String, List<String>> rangeFacets,
1561        String additionalQuery) {
1562
1563        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly((String)m_resultSorter.getValue())) {
1564            m_currentConfigParser.setSortOption((String)m_resultSorter.getValue());
1565        }
1566
1567        CmsSolrQuery query = m_currentConfigParser.getInitialQuery();
1568        CmsSearchController controller = new CmsSearchController(new CmsSearchConfiguration(m_currentConfigParser));
1569        controller.getPagination().getState().setCurrentPage(1);
1570        if (fieldFacets != null) {
1571            Map<String, I_CmsSearchControllerFacetField> fieldFacetControllers = controller.getFieldFacets().getFieldFacetController();
1572            for (Map.Entry<String, List<String>> facetEntry : fieldFacets.entrySet()) {
1573                I_CmsSearchStateFacet state = fieldFacetControllers.get(facetEntry.getKey()).getState();
1574                state.clearChecked();
1575                for (String check : facetEntry.getValue()) {
1576                    state.addChecked(check);
1577                }
1578            }
1579        }
1580        if (rangeFacets != null) {
1581            Map<String, I_CmsSearchControllerFacetRange> rangeFacetControllers = controller.getRangeFacets().getRangeFacetController();
1582            for (Map.Entry<String, List<String>> facetEntry : rangeFacets.entrySet()) {
1583                I_CmsSearchStateFacet state = rangeFacetControllers.get(facetEntry.getKey()).getState();
1584                state.clearChecked();
1585                for (String check : facetEntry.getValue()) {
1586                    state.addChecked(check);
1587                }
1588            }
1589        }
1590        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(additionalQuery)) {
1591            controller.getCommon().getState().setQuery(additionalQuery);
1592        } else {
1593            resetTextSearch();
1594        }
1595
1596        controller.addQueryParts(query, A_CmsUI.getCmsObject());
1597        executeSearch(controller, query);
1598    }
1599
1600    /**
1601     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getBreadCrumbForState(java.lang.String)
1602     */
1603    @Override
1604    protected LinkedHashMap<String, String> getBreadCrumbForState(String state) {
1605
1606        LinkedHashMap<String, String> crumbs = new LinkedHashMap<String, String>();
1607        if (CmsStringUtil.isEmptyOrWhitespaceOnly(state)) {
1608            crumbs.put("", CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_TITLE_0));
1609        } else if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(
1610            A_CmsWorkplaceApp.getParamFromState(state, CmsEditor.RESOURCE_ID_PREFIX))) {
1611            crumbs.put(
1612                CmsListManagerConfiguration.APP_ID,
1613                CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_TITLE_0));
1614            String title = "";
1615            try {
1616                title = A_CmsUI.getCmsObject().readPropertyObject(
1617                    m_currentResource,
1618                    CmsPropertyDefinition.PROPERTY_TITLE,
1619                    false).getValue();
1620            } catch (Exception e) {
1621                // ignore
1622            }
1623            if ((m_currentResource != null) && CmsStringUtil.isEmptyOrWhitespaceOnly(title)) {
1624                title = m_currentResource.getName();
1625            }
1626            crumbs.put("", CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_VIEW_1, title));
1627        }
1628        return crumbs;
1629    }
1630
1631    /**
1632     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getComponentForState(java.lang.String)
1633     */
1634    @Override
1635    protected Component getComponentForState(String state) {
1636
1637        CmsObject cms = A_CmsUI.getCmsObject();
1638        boolean showOverview = true;
1639        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(
1640            A_CmsWorkplaceApp.getParamFromState(state, CmsEditor.RESOURCE_ID_PREFIX))) {
1641            try {
1642                CmsUUID id = new CmsUUID(A_CmsWorkplaceApp.getParamFromState(state, CmsEditor.RESOURCE_ID_PREFIX));
1643                CmsResource res = cms.readResource(id, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
1644                m_currentConfig = parseListConfiguration(A_CmsUI.getCmsObject(), res);
1645                String localeString = A_CmsWorkplaceApp.getParamFromState(state, PARAM_LOCALE);
1646                Locale locale;
1647                if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(localeString)) {
1648                    locale = CmsLocaleManager.getLocale(localeString);
1649                } else {
1650                    locale = getContentLocale(m_currentConfig);
1651                }
1652                //SearchConfigParser configParser = new SearchConfigParser(m_currentConfig, m_collapseItemSeries, locale);
1653                CmsSimpleSearchConfigurationParser configParser = new CmsSimpleSearchConfigurationParser(
1654                    cms,
1655                    m_currentConfig,
1656                    null);
1657                setBackendSpecificOptions(configParser, locale);
1658                search(configParser, res);
1659                showOverview = false;
1660
1661            } catch (Exception e) {
1662                CmsErrorDialog.showErrorDialog(e);
1663                LOG.error(e.getLocalizedMessage(), e);
1664            }
1665        }
1666        if (showOverview) {
1667            unlockCurrent();
1668            m_lockAction = null;
1669            displayListConfigs();
1670        }
1671        enableOverviewMode(showOverview);
1672
1673        return showOverview ? m_overviewTable : m_resultLayout;
1674    }
1675
1676    /**
1677     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getSubNavEntries(java.lang.String)
1678     */
1679    @Override
1680    protected List<NavEntry> getSubNavEntries(String state) {
1681
1682        return null;
1683    }
1684
1685    /**
1686     * Changes the search content locale, reissuing a search.<p>
1687     *
1688     * @param contentLocale the content locale to set
1689     */
1690    void changeContentLocale(Locale contentLocale) {
1691
1692        if (!m_resetting) {
1693            m_currentConfigParser.setSearchLocale(contentLocale);
1694        }
1695        m_resultTable.setContentLocale(contentLocale);
1696        search(null, null, null);
1697    }
1698
1699    /**
1700     * Closes the edit dialog window.<p>
1701     */
1702    void closeEditDialog() {
1703
1704        if (m_dialogWindow != null) {
1705            m_dialogWindow.close();
1706            m_dialogWindow = null;
1707        }
1708        if (m_isOverView) {
1709            unlockCurrent();
1710            m_currentResource = null;
1711        }
1712    }
1713
1714    /**
1715     * Opens the create new dialog.<p>
1716     */
1717    void createNew() {
1718
1719        if (m_isOverView) {
1720            editListConfiguration(null);
1721        }
1722    }
1723
1724    /**
1725     * Displays the search result in the result table.<p>
1726     *
1727     * @param resultList the search result
1728     */
1729    void displayResult(CmsSolrResultList resultList) {
1730
1731        List<CmsResource> resources;
1732        evalSeries(resultList);
1733        if (m_hideSeriesInstances) {
1734            Set<CmsUUID> instanceIds = new HashSet<CmsUUID>();
1735            resources = new ArrayList<CmsResource>();
1736            for (CmsSearchResource res : resultList) {
1737                if (!instanceIds.contains(res.getStructureId())) {
1738                    instanceIds.add(res.getStructureId());
1739                    resources.add(res);
1740                }
1741            }
1742        } else {
1743            resources = new ArrayList<CmsResource>(resultList);
1744        }
1745        m_resultTable.fillTable(A_CmsUI.getCmsObject(), resources, true, false);
1746        String state = A_CmsWorkplaceApp.addParamToState(
1747            "",
1748            CmsEditor.RESOURCE_ID_PREFIX,
1749            m_currentResource.getStructureId().toString());
1750        state = A_CmsWorkplaceApp.addParamToState(
1751            state,
1752            PARAM_LOCALE,
1753            m_currentConfigParser.getSearchLocale().toString());
1754        m_currentState = state;
1755        CmsAppWorkplaceUi.get().changeCurrentAppState(state);
1756        if (m_isOverView) {
1757            enableOverviewMode(false);
1758            updateBreadCrumb(getBreadCrumbForState(state));
1759        }
1760    }
1761
1762    /**
1763     * Edits the given list configuration resource.<p>
1764     *
1765     * @param resource the configuration resource
1766     */
1767    void editListConfiguration(CmsResource resource) {
1768
1769        try {
1770            CmsObject cms = A_CmsUI.getCmsObject();
1771            String editState;
1772            if (resource == null) {
1773                editState = CmsEditor.getEditStateForNew(
1774                    cms,
1775                    OpenCms.getResourceManager().getResourceType(RES_TYPE_LIST_CONFIG),
1776                    "/",
1777                    null,
1778                    false,
1779                    UI.getCurrent().getPage().getLocation().toString());
1780            } else {
1781                editState = CmsEditor.getEditState(
1782                    resource.getStructureId(),
1783                    false,
1784                    UI.getCurrent().getPage().getLocation().toString());
1785            }
1786            View view = CmsAppWorkplaceUi.get().getCurrentView();
1787            if (view instanceof CmsAppView) {
1788                ((CmsAppView)view).setCacheStatus(CacheStatus.cacheOnce);
1789            }
1790            CmsAppWorkplaceUi.get().showApp(
1791                OpenCms.getWorkplaceAppManager().getAppConfiguration(CmsEditorConfiguration.APP_ID),
1792                editState);
1793
1794        } catch (CmsLoaderException e) {
1795            CmsErrorDialog.showErrorDialog(e);
1796        }
1797    }
1798
1799    /**
1800     * Enables the overview mode.<p>
1801     *
1802     * @param enabled <code>true</code> to enable the mode
1803     */
1804    void enableOverviewMode(boolean enabled) {
1805
1806        boolean isOffline = !A_CmsUI.getCmsObject().getRequestContext().getCurrentProject().isOnlineProject();
1807        m_publishButton.setVisible(!enabled);
1808        m_publishButton.setEnabled(isOffline);
1809        m_infoButton.setVisible(!enabled);
1810        m_tableFilter.setVisible(enabled);
1811        m_textSearch.setVisible(!enabled);
1812        m_editCurrentButton.setVisible(!enabled);
1813        m_editCurrentButton.setEnabled(isOffline);
1814
1815        m_toggleSeriesButton.setVisible(m_hasSeriesType && !enabled);
1816        m_resultSorter.setVisible(!enabled);
1817        m_localeSelect.setVisible(!enabled);
1818        m_isOverView = enabled;
1819        m_rootLayout.setMainContent(enabled ? m_overviewTable : m_resultLayout);
1820        m_createNewButton.setVisible(enabled);
1821        if (enabled) {
1822            if (!isOffline) {
1823                m_createNewButton.setEnabled(false);
1824                m_createNewButton.setDescription(
1825                    CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_NOT_CREATABLE_ONLINE_0));
1826            } else {
1827                CmsObject cms = A_CmsUI.getCmsObject();
1828                CmsADEConfigData data = OpenCms.getADEManager().lookupConfiguration(
1829                    cms,
1830                    cms.getRequestContext().getSiteRoot());
1831                CmsResourceTypeConfig typeConfig = data.getResourceType(RES_TYPE_LIST_CONFIG);
1832                try {
1833                    if ((typeConfig == null)
1834                        || !typeConfig.checkCreatable(cms, cms.getRequestContext().getSiteRoot())) {
1835                        m_createNewButton.setEnabled(false);
1836                        m_createNewButton.setDescription(
1837                            CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_NOT_CREATABLE_TYPE_0));
1838                    } else {
1839                        m_createNewButton.setEnabled(true);
1840                        m_createNewButton.setDescription(
1841                            CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_CREATE_NEW_0));
1842                    }
1843                } catch (CmsException e) {
1844                    m_createNewButton.setEnabled(false);
1845                    m_createNewButton.setDescription(
1846                        CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_NOT_CREATABLE_TYPE_0));
1847                }
1848            }
1849        }
1850    }
1851
1852    /**
1853     * Evaluates if date series types are present and if more than one instance of a series is in the search result.<p>
1854     *
1855     * @param resultList the search result list
1856     */
1857    void evalSeries(CmsSolrResultList resultList) {
1858
1859        m_hasSeriesType = false;
1860        m_hasSeriesInstances = false;
1861        Set<CmsUUID> instanceIds = new HashSet<CmsUUID>();
1862        for (CmsSearchResource res : resultList) {
1863            String seriesType = res.getField(CmsSearchField.FIELD_SERIESDATES_TYPE);
1864            m_hasSeriesType = m_hasSeriesType || CmsStringUtil.isNotEmptyOrWhitespaceOnly(seriesType);
1865            if (m_hasSeriesType && I_CmsSerialDateValue.DateType.SERIES.name().equals(seriesType)) {
1866                if (instanceIds.contains(res.getStructureId())) {
1867                    m_hasSeriesInstances = true;
1868                    break;
1869                } else {
1870                    instanceIds.add(res.getStructureId());
1871                }
1872            }
1873        }
1874        if (!m_hasSeriesInstances) {
1875            setsDateSeriesHiddenFlag(false);
1876        }
1877        m_toggleSeriesButton.setEnabled(m_hasSeriesInstances);
1878        m_toggleSeriesButton.setVisible(m_hasSeriesType);
1879
1880    }
1881
1882    /**
1883     * Filters the result table.<p>
1884     *
1885     * @param filter the filter string
1886     */
1887    void filterTable(String filter) {
1888
1889        if (!m_resetting) {
1890            m_overviewTable.filterTable(filter);
1891        }
1892    }
1893
1894    /**
1895     * Creates an element bean of the selected table item to be used with edit handlers.<p>
1896     *
1897     * @param context the dialog context
1898     *
1899     * @return the element bean
1900     */
1901    CmsContainerElementBean getElementForEditHandler(DialogContext context) {
1902
1903        List<Item> selected = context.getSelectedItems();
1904        if (selected.size() == 1) {
1905            Item item = selected.get(0);
1906            Date instanceDate = (Date)item.getItemProperty(INSTANCEDATE_PROPERTY).getValue();
1907            CmsResource resource = context.getResources().get(0);
1908            return new CmsContainerElementBean(
1909                resource.getStructureId(),
1910                null,
1911                Collections.singletonMap(
1912                    CmsDateSeriesEditHandler.PARAM_INSTANCEDATE,
1913                    String.valueOf(instanceDate.getTime())),
1914                false);
1915        }
1916        return null;
1917    }
1918
1919    /**
1920     * Returns the resources to publish for the current list.<p>
1921     *
1922     * @return the publish resources
1923     */
1924    List<CmsResource> getPublishResources() {
1925
1926        List<CmsResource> result = new ArrayList<CmsResource>();
1927        if (m_currentResource != null) {
1928            result.add(m_currentResource);
1929            CmsObject cms = A_CmsUI.getCmsObject();
1930            CmsSolrQuery query = m_currentConfigParser.getInitialQuery();
1931            CmsSearchController controller = new CmsSearchController(new CmsSearchConfiguration(m_currentConfigParser));
1932            controller.getPagination().getState().setCurrentPage(1);
1933            controller.addQueryParts(query, A_CmsUI.getCmsObject());
1934
1935            CmsSolrIndex index = OpenCms.getSearchManager().getIndexSolr(CmsSolrIndex.DEFAULT_INDEX_NAME_OFFLINE);
1936            try {
1937                CmsSolrResultList solrResultList = index.search(cms, query, true, CmsResourceFilter.IGNORE_EXPIRATION);
1938                result.addAll(solrResultList);
1939            } catch (CmsSearchException e) {
1940                LOG.error("Error reading resources for publish.", e);
1941            }
1942        }
1943        return result;
1944    }
1945
1946    /**
1947     * Returns whether the overview mode is active.<p>
1948     *
1949     * @return <code>true</code> in case the overview mode is active
1950     */
1951    boolean isOverView() {
1952
1953        return m_isOverView;
1954    }
1955
1956    /**
1957     * Opens the publish dialog to publish all resources related to the current search configuration.<p>
1958     */
1959    void publish() {
1960
1961        I_CmsUpdateListener<String> updateListener = new I_CmsUpdateListener<String>() {
1962
1963            @Override
1964            public void onUpdate(List<String> updatedItems) {
1965
1966                updateItems(updatedItems);
1967            }
1968        };
1969        CmsAppWorkplaceUi.get().disableGlobalShortcuts();
1970        CmsGwtDialogExtension extension = new CmsGwtDialogExtension(A_CmsUI.get(), updateListener);
1971        extension.openPublishDialog(getPublishResources());
1972    }
1973
1974    /**
1975     * Refreshes the search result maintaining the current scroll position.<p>
1976     */
1977    void refreshResult() {
1978
1979        String itemId = m_resultTable.getCurrentPageFirstItemId();
1980        CmsFileExplorerSettings state = m_resultTable.getTableSettings();
1981        search(
1982            m_resultFacets.getSelectedFieldFacets(),
1983            m_resultFacets.getSelectedRangeFactes(),
1984            m_textSearch.getValue());
1985        m_resultTable.setTableState(state);
1986        m_resultTable.updateSorting();
1987        m_resultTable.setCurrentPageFirstItemId(itemId);
1988    }
1989
1990    /**
1991     * Searches within the current list.<p>
1992     *
1993     * @param query the query string
1994     */
1995    void search(String query) {
1996
1997        if (!m_resetting) {
1998            search(null, null, query);
1999        }
2000    }
2001
2002    /**
2003     * Sets the date series hidden flag.<p>
2004     *
2005     * @param hide the date series hidden flag
2006     */
2007    void setsDateSeriesHiddenFlag(boolean hide) {
2008
2009        m_hideSeriesInstances = hide;
2010        if (m_hideSeriesInstances) {
2011            m_toggleSeriesButton.addStyleName(OpenCmsTheme.BUTTON_PRESSED);
2012        } else {
2013            m_toggleSeriesButton.removeStyleName(OpenCmsTheme.BUTTON_PRESSED);
2014        }
2015    }
2016
2017    /**
2018     * Sorts the search result.<p>
2019     */
2020    void sortResult() {
2021
2022        if (!m_resetting) {
2023            search(
2024                m_resultFacets.getSelectedFieldFacets(),
2025                m_resultFacets.getSelectedRangeFactes(),
2026                m_textSearch.getValue());
2027        }
2028    }
2029
2030    /**
2031     * Toggles the date series filter.<p>
2032     */
2033    void toggleDateSeries() {
2034
2035        setsDateSeriesHiddenFlag(!m_hideSeriesInstances);
2036        refreshResult();
2037    }
2038
2039    /**
2040     * Tries to unlocks the current resource if available.<p>
2041     */
2042    void tryUnlockCurrent() {
2043
2044        if ((m_lockAction != null) && m_lockAction.getChange().equals(CmsLockActionRecord.LockChange.locked)) {
2045            try {
2046                A_CmsUI.getCmsObject().unlockResource(m_currentResource);
2047            } catch (CmsException e) {
2048                e.printStackTrace();
2049            }
2050        }
2051    }
2052
2053    /**
2054     * Unlocks the current resource in case it has been locked by previous actions.<p>
2055     */
2056    void unlockCurrent() {
2057
2058        if (m_currentResource != null) {
2059            if ((m_lockAction != null) && m_lockAction.getChange().equals(LockChange.locked)) {
2060                CmsLockUtil.tryUnlock(A_CmsUI.getCmsObject(), m_currentResource);
2061            }
2062        }
2063        m_lockAction = null;
2064    }
2065
2066    /**
2067     * Updates the given items in the result table.<p>
2068     *
2069     * @param updatedItems the items to update
2070     */
2071    void updateItems(List<String> updatedItems) {
2072
2073        Set<CmsUUID> ids = new HashSet<CmsUUID>();
2074        for (String id : updatedItems) {
2075            ids.add(new CmsUUID(id));
2076        }
2077        m_resultTable.update(ids, false);
2078    }
2079
2080    /**
2081     * Displays the list config resources.<p>
2082     */
2083    private void displayListConfigs() {
2084
2085        CmsObject cms = A_CmsUI.getCmsObject();
2086        resetTableFilter();
2087        try {
2088            // display the search configuration overview
2089            List<CmsResource> resources = cms.readResources(
2090                "/",
2091                CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireType(
2092                    OpenCms.getResourceManager().getResourceType(RES_TYPE_LIST_CONFIG)));
2093            m_overviewTable.fillTable(cms, resources);
2094        } catch (Exception e) {
2095            CmsErrorDialog.showErrorDialog(e);
2096            LOG.error(e.getLocalizedMessage(), e);
2097        }
2098    }
2099
2100    /**
2101     * Executes a search.<p>
2102     *
2103     * @param controller the search controller
2104     * @param query the SOLR query
2105     */
2106    private void executeSearch(CmsSearchController controller, CmsSolrQuery query) {
2107
2108        CmsObject cms = A_CmsUI.getCmsObject();
2109        CmsSolrIndex index = OpenCms.getSearchManager().getIndexSolr(
2110            cms.getRequestContext().getCurrentProject().isOnlineProject()
2111            ? CmsSolrIndex.DEFAULT_INDEX_NAME_ONLINE
2112            : CmsSolrIndex.DEFAULT_INDEX_NAME_OFFLINE);
2113        try {
2114            CmsSolrResultList solrResultList = index.search(cms, query, true, CmsResourceFilter.IGNORE_EXPIRATION);
2115            displayResult(solrResultList);
2116            m_resultFacets.displayFacetResult(
2117                solrResultList,
2118                new CmsSearchResultWrapper(controller, solrResultList, query, cms, null));
2119        } catch (CmsSearchException e) {
2120            CmsErrorDialog.showErrorDialog(e);
2121
2122            LOG.error("Error executing search.", e);
2123        }
2124    }
2125
2126    /**
2127     * Returns the content locale configured for the first search root folder of the search configuration.<p>
2128     *
2129     * @param bean the search configuration data
2130     *
2131     * @return the locale
2132     */
2133    private Locale getContentLocale(ListConfigurationBean bean) {
2134
2135        CmsObject cms = A_CmsUI.getCmsObject();
2136        if (bean.getFolders().isEmpty()) {
2137            return OpenCms.getLocaleManager().getDefaultLocale(cms, "/");
2138        } else {
2139            return OpenCms.getLocaleManager().getDefaultLocale(
2140                cms,
2141                cms.getRequestContext().removeSiteRoot(m_currentConfig.getFolders().get(0)));
2142        }
2143    }
2144
2145    /**
2146     * Resets the locale select according to the current configuration data.<p>
2147     *
2148     * @param defaultLocale the default content locale
2149     */
2150    private void resetContentLocale(Locale defaultLocale) {
2151
2152        m_resetting = true;
2153        m_localeSelect.removeAllItems();
2154        if (m_currentConfig.getFolders().isEmpty()) {
2155            m_localeSelect.addItem(defaultLocale);
2156            m_localeSelect.setItemCaption(defaultLocale, defaultLocale.getDisplayLanguage(UI.getCurrent().getLocale()));
2157        } else {
2158            for (String folder : m_currentConfig.getFolders()) {
2159                for (Locale locale : OpenCms.getLocaleManager().getAvailableLocales(A_CmsUI.getCmsObject(), folder)) {
2160                    if (!m_localeSelect.containsId(locale)) {
2161                        m_localeSelect.addItem(locale);
2162                        m_localeSelect.setItemCaption(locale, locale.getDisplayLanguage(UI.getCurrent().getLocale()));
2163                    }
2164                }
2165            }
2166        }
2167        m_localeSelect.setValue(defaultLocale);
2168        m_localeSelect.setEnabled(m_localeSelect.getItemIds().size() > 1);
2169        m_resetting = false;
2170    }
2171
2172    /**
2173     * Resets the table filter.<p>
2174     */
2175    private void resetTableFilter() {
2176
2177        m_resetting = true;
2178        m_tableFilter.clear();
2179        m_resetting = false;
2180    }
2181
2182    /**
2183     * Resets the text search input.<p>
2184     */
2185    private void resetTextSearch() {
2186
2187        m_resetting = true;
2188        m_textSearch.clear();
2189        m_resetting = false;
2190    }
2191
2192    /**
2193     * Sets options which are specific to the backend list manager on the cnofiguration parser.<p>
2194     *
2195     * @param configParser the configuration parser
2196     * @param locale the search locale
2197     */
2198    private void setBackendSpecificOptions(CmsSimpleSearchConfigurationParser configParser, Locale locale) {
2199
2200        configParser.setSearchLocale(locale);
2201        configParser.setIgnoreBlacklist(true);
2202        configParser.setPagination(PAGINATION);
2203    }
2204}