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.components;
029
030import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_CACHE;
031import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_COPYRIGHT;
032import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_DATE_CREATED;
033import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_DATE_EXPIRED;
034import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_DATE_MODIFIED;
035import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_DATE_RELEASED;
036import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_INSIDE_PROJECT;
037import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_INTERNAL_RESOURCE_TYPE;
038import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_IN_NAVIGATION;
039import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_IS_FOLDER;
040import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_NAVIGATION_POSITION;
041import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_NAVIGATION_TEXT;
042import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_PERMISSIONS;
043import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_PROJECT;
044import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_RELEASED_NOT_EXPIRED;
045import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_RESOURCE_NAME;
046import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_RESOURCE_TYPE;
047import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_SITE_PATH;
048import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_SIZE;
049import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_STATE;
050import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_STATE_NAME;
051import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_TITLE;
052import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_TYPE_ICON;
053import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_USER_CREATED;
054import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_USER_LOCKED;
055import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_USER_MODIFIED;
056
057import org.opencms.ade.sitemap.shared.CmsClientSitemapEntry;
058import org.opencms.db.CmsResourceState;
059import org.opencms.file.CmsObject;
060import org.opencms.file.CmsProperty;
061import org.opencms.file.CmsPropertyDefinition;
062import org.opencms.file.CmsResource;
063import org.opencms.file.types.I_CmsResourceType;
064import org.opencms.i18n.CmsEncoder;
065import org.opencms.main.CmsException;
066import org.opencms.main.CmsLog;
067import org.opencms.main.OpenCms;
068import org.opencms.ui.A_CmsUI;
069import org.opencms.ui.CmsCssIcon;
070import org.opencms.ui.CmsVaadinUtils;
071import org.opencms.ui.util.I_CmsItemSorter;
072import org.opencms.util.CmsStringUtil;
073import org.opencms.util.CmsUUID;
074import org.opencms.workplace.CmsWorkplaceMessages;
075import org.opencms.workplace.explorer.CmsResourceUtil;
076
077import java.util.ArrayList;
078import java.util.Arrays;
079import java.util.Collection;
080import java.util.Collections;
081import java.util.HashMap;
082import java.util.LinkedHashSet;
083import java.util.List;
084import java.util.Locale;
085import java.util.Map;
086import java.util.Set;
087
088import org.apache.commons.lang3.ClassUtils;
089import org.apache.commons.logging.Log;
090
091import com.google.common.collect.Lists;
092import com.google.common.collect.Sets;
093import com.vaadin.event.dd.DropHandler;
094import com.vaadin.ui.Component;
095import com.vaadin.ui.CustomComponent;
096import com.vaadin.v7.data.Item;
097import com.vaadin.v7.data.Property;
098import com.vaadin.v7.data.util.IndexedContainer;
099import com.vaadin.v7.data.util.converter.Converter;
100import com.vaadin.v7.shared.ui.label.ContentMode;
101import com.vaadin.v7.ui.AbstractSelect.ItemDescriptionGenerator;
102import com.vaadin.v7.ui.Label;
103import com.vaadin.v7.ui.Table;
104import com.vaadin.v7.ui.Table.RowHeaderMode;
105import com.vaadin.v7.ui.Table.TableDragMode;
106
107/**
108 * Generic table for displaying lists of resources.<p>
109 */
110@SuppressWarnings("deprecation")
111public class CmsResourceTable extends CustomComponent {
112
113    /**
114     * Helper class for easily configuring a set of columns to display, together with their visibility / collapsed status.<p>
115     */
116    public class ColumnBuilder {
117
118        /** The column entries configured so far. */
119        private List<ColumnEntry> m_columnEntries = Lists.newArrayList();
120
121        /**
122         * Sets up the table and its container using the columns configured so far.<p>
123         */
124        public void buildColumns() {
125
126            Set<CmsResourceTableProperty> visible = new LinkedHashSet<CmsResourceTableProperty>();
127            Set<CmsResourceTableProperty> collapsed = new LinkedHashSet<CmsResourceTableProperty>();
128            for (ColumnEntry entry : m_columnEntries) {
129                CmsResourceTableProperty prop = entry.getColumn();
130                m_container.addContainerProperty(prop, prop.getColumnType(), prop.getDefaultValue());
131                if (entry.isCollapsed()) {
132                    collapsed.add(entry.getColumn());
133                }
134                if (entry.isVisible()) {
135                    visible.add(entry.getColumn());
136                }
137            }
138            m_fileTable.setVisibleColumns(visible.toArray(new Object[0]));
139            setCollapsedColumns(collapsed.toArray(new Object[0]));
140            for (CmsResourceTableProperty visibleProp : visible) {
141                String headerKey = visibleProp.getHeaderKey();
142                if (!CmsStringUtil.isEmptyOrWhitespaceOnly(headerKey)) {
143                    m_fileTable.setColumnHeader(visibleProp, CmsVaadinUtils.getMessageText(headerKey));
144                } else {
145                    m_fileTable.setColumnHeader(visibleProp, "");
146                }
147                m_fileTable.setColumnCollapsible(visibleProp, visibleProp.isCollapsible());
148                if (visibleProp.getColumnWidth() > 0) {
149                    m_fileTable.setColumnWidth(visibleProp, visibleProp.getColumnWidth());
150                }
151                if (visibleProp.getExpandRatio() > 0) {
152                    m_fileTable.setColumnExpandRatio(visibleProp, visibleProp.getExpandRatio());
153                }
154                if (visibleProp.getConverter() != null) {
155                    m_fileTable.setConverter(visibleProp, visibleProp.getConverter());
156                }
157            }
158        }
159
160        /**
161         * Adds a new column.<p>
162         *
163         * @param prop the column
164         *
165         * @return this object
166         */
167        public ColumnBuilder column(CmsResourceTableProperty prop) {
168
169            column(prop, 0);
170            return this;
171        }
172
173        /**
174         * Adds a new column.<p<
175         *
176         * @param prop the column
177         * @param flags the flags for the column
178         *
179         * @return this object
180         */
181        public ColumnBuilder column(CmsResourceTableProperty prop, int flags) {
182
183            ColumnEntry entry = new ColumnEntry();
184            entry.setColumn(prop);
185            entry.setFlags(flags);
186            m_columnEntries.add(entry);
187            return this;
188        }
189    }
190
191    /**
192     * Contains the data for the given column, along with some flags to control visibility/collapsed status.<p>
193     *
194     */
195    public static class ColumnEntry {
196
197        /** The column. */
198        private CmsResourceTableProperty m_column;
199
200        /** The flags. */
201        private int m_flags;
202
203        /**
204         * Returns the column.<p>
205         *
206         * @return the column
207         */
208        public CmsResourceTableProperty getColumn() {
209
210            return m_column;
211        }
212
213        /**
214         * Returns the collapsed.<p>
215         *
216         * @return the collapsed
217         */
218        public boolean isCollapsed() {
219
220            return (m_flags & COLLAPSED) != 0;
221        }
222
223        /**
224         * Returns the visible.<p>
225         *
226         * @return the visible
227         */
228        public boolean isVisible() {
229
230            return 0 == (m_flags & INVISIBLE);
231        }
232
233        /**
234         * Sets the column.<p>
235         *
236         * @param column the column to set
237         */
238        public void setColumn(CmsResourceTableProperty column) {
239
240            m_column = column;
241        }
242
243        /**
244         * Sets the flags.<p>
245         *
246         * @param flags the flags to set
247         */
248        public void setFlags(int flags) {
249
250            m_flags = flags;
251        }
252
253    }
254
255    /**
256     * Default description generator for table entries.
257     */
258    public static class DefaultItemDescriptionGenerator implements ItemDescriptionGenerator {
259
260        /** Serial version id.*/
261        private static final long serialVersionUID = 1L;
262
263        /**
264         * @see com.vaadin.v7.ui.AbstractSelect.ItemDescriptionGenerator#generateDescription(com.vaadin.ui.Component, java.lang.Object, java.lang.Object)
265         */
266        @SuppressWarnings("synthetic-access")
267        public String generateDescription(Component source, Object itemId, Object propertyId) {
268
269            Table table = (Table)source;
270            try {
271                if ((propertyId != null) && (itemId != null)) {
272                    Property prop = table.getContainerDataSource().getItem(itemId).getItemProperty(propertyId);
273                    Converter<String, Object> converter = table.getConverter(propertyId);
274                    if (CmsResourceTableProperty.PROPERTY_RESOURCE_NAME == propertyId) {
275                        // when working with the explorer, tool tips constantly showing up when
276                        // hovering over the file name accidentally seems more annoying than useful
277                        return null;
278                    } else if ((converter != null) && String.class.equals(converter.getPresentationType())) {
279                        return converter.convertToPresentation(
280                            prop.getValue(),
281                            String.class,
282                            A_CmsUI.get().getLocale());
283                    } else if (String.class.equals(prop.getType()) || ClassUtils.isPrimitiveOrWrapper(prop.getType())) {
284                        Object value = prop.getValue();
285                        if (value != null) {
286                            return CmsEncoder.escapeXml("" + value);
287                        }
288                    }
289                }
290            } catch (Exception e) {
291                LOG.warn(e.getLocalizedMessage(), e);
292            }
293            return null;
294        }
295    }
296
297    /**
298     * Provides item property values for additional table columns.<p>
299     */
300    public static interface I_ResourcePropertyProvider {
301
302        /**
303         * Adds the property values to the given item.<p>
304         *
305         * @param resourceItem the resource item
306         * @param cms the cms context
307         * @param resource the resource
308         * @param locale  the workplace locale
309         */
310        void addItemProperties(Item resourceItem, CmsObject cms, CmsResource resource, Locale locale);
311    }
312
313    /**
314     * Extending the indexed container to make the number of un-filtered items available.<p>
315     */
316    protected static class ItemContainer extends IndexedContainer {
317
318        /** The serial version id. */
319        private static final long serialVersionUID = -2033722658471550506L;
320
321        /**
322         * @see com.vaadin.v7.data.util.IndexedContainer#getSortableContainerPropertyIds()
323         */
324        @Override
325        public Collection<?> getSortableContainerPropertyIds() {
326
327            if (getItemSorter() instanceof I_CmsItemSorter) {
328                return ((I_CmsItemSorter)getItemSorter()).getSortableContainerPropertyIds(this);
329            } else {
330                return super.getSortableContainerPropertyIds();
331            }
332        }
333
334        /**
335         * Returns the number of items in the container, not considering any filters.<p>
336         *
337         * @return the number of items
338         */
339        protected int getItemCount() {
340
341            return getAllItemIds().size();
342        }
343    }
344
345    /** Flag to mark columns as initially collapsed.*/
346    public static final int COLLAPSED = 1;
347
348    /** Flag to mark columns as invisible. */
349    public static final int INVISIBLE = 2;
350
351    /** The logger instance for this class. */
352    private static final Log LOG = CmsLog.getLog(CmsResourceTable.class);
353
354    /** Serial version id. */
355    private static final long serialVersionUID = 1L;
356
357    /** The resource data container. */
358    protected ItemContainer m_container = new ItemContainer();
359
360    /** The table used to display the resource data. */
361    protected Table m_fileTable = new Table();
362
363    /** Property provider for additional columns. */
364    protected List<I_ResourcePropertyProvider> m_propertyProviders;
365
366    /**
367     * Creates a new instance.<p>
368     *
369     * This constructor does *not* set up the columns of the table; use the ColumnBuilder inner class for this.
370     */
371    public CmsResourceTable() {
372
373        m_propertyProviders = new ArrayList<I_ResourcePropertyProvider>();
374        m_fileTable.setContainerDataSource(m_container);
375        setCompositionRoot(m_fileTable);
376        m_fileTable.setRowHeaderMode(RowHeaderMode.HIDDEN);
377        m_fileTable.setItemDescriptionGenerator(new DefaultItemDescriptionGenerator());
378    }
379
380    /**
381     * Static helper method to initialize the 'standard' properties of a data item from a given resource.<p>
382     * @param resourceItem the resource item to fill
383     * @param cms the CMS context
384     * @param resource the resource
385     * @param locale the locale
386     */
387    public static void fillItemDefault(Item resourceItem, CmsObject cms, CmsResource resource, Locale locale) {
388
389        if (resource == null) {
390            LOG.error("Error rendering item for 'null' resource");
391            return;
392        }
393
394        if (resourceItem == null) {
395            LOG.error("Error rendering 'null' item for resource " + resource.getRootPath());
396            return;
397        }
398        if (cms == null) {
399            cms = A_CmsUI.getCmsObject();
400            LOG.warn("CmsObject was 'null', using thread local CmsObject");
401        }
402        CmsResourceUtil resUtil = new CmsResourceUtil(cms, resource);
403        Map<String, CmsProperty> resourceProps = null;
404        try {
405            List<CmsProperty> props = cms.readPropertyObjects(resource, false);
406            resourceProps = new HashMap<String, CmsProperty>();
407            for (CmsProperty prop : props) {
408                resourceProps.put(prop.getName(), prop);
409            }
410        } catch (CmsException e1) {
411            LOG.debug("Unable to read properties for resource '" + resource.getRootPath() + "'.", e1);
412        }
413        I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(resource);
414        if (resourceItem.getItemProperty(PROPERTY_TYPE_ICON) != null) {
415            resourceItem.getItemProperty(PROPERTY_TYPE_ICON).setValue(
416                new CmsResourceIcon(resUtil, resource.getState(), true));
417        }
418
419        if (resourceItem.getItemProperty(PROPERTY_PROJECT) != null) {
420            Label projectFlag = null;
421            switch (resUtil.getProjectState().getMode()) {
422                case 1:
423                    projectFlag = new Label(
424                        new CmsCssIcon(OpenCmsTheme.ICON_PROJECT_CURRENT).getHtml(resUtil.getLockedInProjectName()),
425                        ContentMode.HTML);
426                    break;
427                case 2:
428                    projectFlag = new Label(
429                        new CmsCssIcon(OpenCmsTheme.ICON_PROJECT_OTHER).getHtml(resUtil.getLockedInProjectName()),
430                        ContentMode.HTML);
431                    break;
432                case 5:
433                    projectFlag = new Label(
434                        new CmsCssIcon(OpenCmsTheme.ICON_PUBLISH).getHtml(resUtil.getLockedInProjectName()),
435                        ContentMode.HTML);
436                    break;
437                default:
438            }
439            resourceItem.getItemProperty(PROPERTY_PROJECT).setValue(projectFlag);
440        }
441
442        if (resourceItem.getItemProperty(PROPERTY_INSIDE_PROJECT) != null) {
443            resourceItem.getItemProperty(PROPERTY_INSIDE_PROJECT).setValue(Boolean.valueOf(resUtil.isInsideProject()));
444        }
445
446        if (resourceItem.getItemProperty(PROPERTY_RELEASED_NOT_EXPIRED) != null) {
447            resourceItem.getItemProperty(PROPERTY_RELEASED_NOT_EXPIRED).setValue(
448                Boolean.valueOf(resUtil.isReleasedAndNotExpired()));
449        }
450
451        if (resourceItem.getItemProperty(PROPERTY_RESOURCE_NAME) != null) {
452            resourceItem.getItemProperty(PROPERTY_RESOURCE_NAME).setValue(resource.getName());
453        }
454
455        if (resourceItem.getItemProperty(PROPERTY_SITE_PATH) != null) {
456            resourceItem.getItemProperty(PROPERTY_SITE_PATH).setValue(cms.getSitePath(resource));
457        }
458
459        if ((resourceItem.getItemProperty(PROPERTY_TITLE) != null) && (resourceProps != null)) {
460            resourceItem.getItemProperty(PROPERTY_TITLE).setValue(
461                resourceProps.containsKey(CmsPropertyDefinition.PROPERTY_TITLE)
462                ? resourceProps.get(CmsPropertyDefinition.PROPERTY_TITLE).getValue()
463                : "");
464        }
465        boolean inNavigation = false;
466        if ((resourceItem.getItemProperty(PROPERTY_NAVIGATION_TEXT) != null) && (resourceProps != null)) {
467            resourceItem.getItemProperty(PROPERTY_NAVIGATION_TEXT).setValue(
468                resourceProps.containsKey(CmsPropertyDefinition.PROPERTY_NAVTEXT)
469                ? resourceProps.get(CmsPropertyDefinition.PROPERTY_NAVTEXT).getValue()
470                : "");
471            inNavigation = resourceProps.containsKey(CmsPropertyDefinition.PROPERTY_NAVTEXT);
472        }
473
474        if ((resourceItem.getItemProperty(PROPERTY_NAVIGATION_POSITION) != null) && (resourceProps != null)) {
475            try {
476                Float navPos = resourceProps.containsKey(CmsPropertyDefinition.PROPERTY_NAVPOS)
477                ? Float.valueOf(resourceProps.get(CmsPropertyDefinition.PROPERTY_NAVPOS).getValue())
478                : (inNavigation ? Float.valueOf(Float.MAX_VALUE) : null);
479                resourceItem.getItemProperty(PROPERTY_NAVIGATION_POSITION).setValue(navPos);
480                inNavigation = navPos != null;
481            } catch (Exception e) {
482                LOG.debug("Error evaluating navPos property", e);
483            }
484        }
485
486        if (resourceItem.getItemProperty(PROPERTY_IN_NAVIGATION) != null) {
487            if (inNavigation
488                && (resourceProps != null)
489                && resourceProps.containsKey(CmsPropertyDefinition.PROPERTY_NAVINFO)
490                && CmsClientSitemapEntry.HIDDEN_NAVIGATION_ENTRY.equals(
491                    resourceProps.get(CmsPropertyDefinition.PROPERTY_NAVINFO).getValue())) {
492                inNavigation = false;
493            }
494            resourceItem.getItemProperty(PROPERTY_IN_NAVIGATION).setValue(Boolean.valueOf(inNavigation));
495        }
496
497        if ((resourceItem.getItemProperty(PROPERTY_COPYRIGHT) != null) && (resourceProps != null)) {
498            resourceItem.getItemProperty(PROPERTY_COPYRIGHT).setValue(
499                resourceProps.containsKey(CmsPropertyDefinition.PROPERTY_COPYRIGHT)
500                ? resourceProps.get(CmsPropertyDefinition.PROPERTY_COPYRIGHT).getValue()
501                : "");
502        }
503
504        if ((resourceItem.getItemProperty(PROPERTY_CACHE) != null) && (resourceProps != null)) {
505            resourceItem.getItemProperty(PROPERTY_CACHE).setValue(
506                resourceProps.containsKey(CmsPropertyDefinition.PROPERTY_CACHE)
507                ? resourceProps.get(CmsPropertyDefinition.PROPERTY_CACHE).getValue()
508                : "");
509        }
510
511        if (resourceItem.getItemProperty(PROPERTY_RESOURCE_TYPE) != null) {
512            resourceItem.getItemProperty(PROPERTY_RESOURCE_TYPE).setValue(
513                CmsWorkplaceMessages.getResourceTypeName(locale, type.getTypeName()));
514        }
515
516        if (resourceItem.getItemProperty(PROPERTY_INTERNAL_RESOURCE_TYPE) != null) {
517            resourceItem.getItemProperty(PROPERTY_INTERNAL_RESOURCE_TYPE).setValue(type.getTypeName());
518        }
519
520        if (resourceItem.getItemProperty(PROPERTY_IS_FOLDER) != null) {
521            resourceItem.getItemProperty(PROPERTY_IS_FOLDER).setValue(Boolean.valueOf(resource.isFolder()));
522        }
523
524        if (resourceItem.getItemProperty(PROPERTY_SIZE) != null) {
525            if (resource.isFile()) {
526                resourceItem.getItemProperty(PROPERTY_SIZE).setValue(Integer.valueOf(resource.getLength()));
527            }
528        }
529
530        if (resourceItem.getItemProperty(PROPERTY_PERMISSIONS) != null) {
531            resourceItem.getItemProperty(PROPERTY_PERMISSIONS).setValue(resUtil.getPermissionString());
532        }
533
534        if (resourceItem.getItemProperty(PROPERTY_DATE_MODIFIED) != null) {
535            resourceItem.getItemProperty(PROPERTY_DATE_MODIFIED).setValue(Long.valueOf(resource.getDateLastModified()));
536        }
537
538        if (resourceItem.getItemProperty(PROPERTY_USER_MODIFIED) != null) {
539            resourceItem.getItemProperty(PROPERTY_USER_MODIFIED).setValue(resUtil.getUserLastModified());
540        }
541
542        if (resourceItem.getItemProperty(PROPERTY_DATE_CREATED) != null) {
543            resourceItem.getItemProperty(PROPERTY_DATE_CREATED).setValue(Long.valueOf(resource.getDateCreated()));
544        }
545
546        if (resourceItem.getItemProperty(PROPERTY_USER_CREATED) != null) {
547            resourceItem.getItemProperty(PROPERTY_USER_CREATED).setValue(resUtil.getUserCreated());
548        }
549
550        if (resourceItem.getItemProperty(PROPERTY_DATE_RELEASED) != null) {
551            long release = resource.getDateReleased();
552            if (release != CmsResource.DATE_RELEASED_DEFAULT) {
553                resourceItem.getItemProperty(PROPERTY_DATE_RELEASED).setValue(Long.valueOf(release));
554            } else {
555                resourceItem.getItemProperty(PROPERTY_DATE_RELEASED).setValue(null);
556            }
557        }
558
559        if (resourceItem.getItemProperty(PROPERTY_DATE_EXPIRED) != null) {
560            long expire = resource.getDateExpired();
561            if (expire != CmsResource.DATE_EXPIRED_DEFAULT) {
562                resourceItem.getItemProperty(PROPERTY_DATE_EXPIRED).setValue(Long.valueOf(expire));
563            } else {
564                resourceItem.getItemProperty(PROPERTY_DATE_EXPIRED).setValue(null);
565            }
566        }
567
568        if (resourceItem.getItemProperty(PROPERTY_STATE_NAME) != null) {
569            resourceItem.getItemProperty(PROPERTY_STATE_NAME).setValue(resUtil.getStateName());
570        }
571
572        if (resourceItem.getItemProperty(PROPERTY_STATE) != null) {
573            resourceItem.getItemProperty(PROPERTY_STATE).setValue(resource.getState());
574        }
575
576        if (resourceItem.getItemProperty(PROPERTY_USER_LOCKED) != null) {
577            resourceItem.getItemProperty(PROPERTY_USER_LOCKED).setValue(resUtil.getLockedByName());
578        }
579    }
580
581    /**
582     * Gets the CSS style name for the given resource state.<p>
583     *
584     * @param state the resource state
585     * @return the CSS style name
586     */
587    public static String getStateStyle(CmsResourceState state) {
588
589        String stateStyle = "";
590        if (state != null) {
591            if (state.isDeleted()) {
592                stateStyle = OpenCmsTheme.STATE_DELETED;
593            } else if (state.isNew()) {
594                stateStyle = OpenCmsTheme.STATE_NEW;
595            } else if (state.isChanged()) {
596                stateStyle = OpenCmsTheme.STATE_CHANGED;
597            }
598        }
599        return stateStyle;
600    }
601
602    /**
603     * Adds a property provider.<p>
604     *
605     * @param provider the property provider
606     */
607    public void addPropertyProvider(I_ResourcePropertyProvider provider) {
608
609        m_propertyProviders.add(provider);
610    }
611
612    /**
613     * Clears the value selection.<p>
614     */
615    public void clearSelection() {
616
617        m_fileTable.setValue(Collections.emptySet());
618    }
619
620    /**
621     * Fills the resource table.<p>
622     *
623     * @param cms the current CMS context
624     * @param resources the resources which should be displayed in the table
625     */
626    public void fillTable(CmsObject cms, List<CmsResource> resources) {
627
628        fillTable(cms, resources, true);
629    }
630
631    /**
632     * Fills the resource table.<p>
633     *
634     * @param cms the current CMS context
635     * @param resources the resources which should be displayed in the table
636     * @param clearFilter <code>true</code> to clear the search filter
637     */
638    public void fillTable(CmsObject cms, List<CmsResource> resources, boolean clearFilter) {
639
640        fillTable(cms, resources, clearFilter, true);
641    }
642
643    /**
644     * Fills the resource table.<p>
645     *
646     * @param cms the current CMS context
647     * @param resources the resources which should be displayed in the table
648     * @param clearFilter <code>true</code> to clear the search filter
649     * @param sort <code>true</code> to sort the table entries
650     */
651    public void fillTable(CmsObject cms, List<CmsResource> resources, boolean clearFilter, boolean sort) {
652
653        fillTable(cms, resources, clearFilter, true, false);
654    }
655
656    /**
657     * Fills the resource table.<p>
658     *
659     * @param cms the current CMS context
660     * @param resources the resources which should be displayed in the table
661     * @param clearFilter <code>true</code> to clear the search filter
662     * @param sort <code>true</code> to sort the table entries
663     * @param distinctResources whether to only show distinct resources
664     */
665    public void fillTable(
666        CmsObject cms,
667        List<CmsResource> resources,
668        boolean clearFilter,
669        boolean sort,
670        boolean distinctResources) {
671
672        Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms);
673        m_container.removeAllItems();
674        if (clearFilter) {
675            m_container.removeAllContainerFilters();
676        }
677        if (distinctResources) {
678            Map<String, String> ids = new HashMap<String, String>();
679            for (CmsResource resource : resources) {
680                String id = resource.getStructureId().getStringValue();
681                if (!ids.containsKey(id)) {
682                    fillItem(cms, resource, wpLocale);
683                    ids.put(id, "");
684                }
685            }
686        } else {
687            for (CmsResource resource : resources) {
688                fillItem(cms, resource, wpLocale);
689            }
690        }
691        if (sort) {
692            m_fileTable.sort();
693        }
694        clearSelection();
695    }
696
697    /**
698     * Gets structure ids of resources for current folder in current sort order.<p>
699     *
700     * @return the structure ids of the current folder contents
701     */
702    @SuppressWarnings("unchecked")
703    public List<CmsUUID> getAllIds() {
704
705        return itemIdsToUUIDs((List<String>)m_fileTable.getContainerDataSource().getItemIds());
706    }
707
708    /**
709     * Returns the number of currently visible items.<p>
710     *
711     * @return the number of currentliy visible items
712     */
713    public int getItemCount() {
714
715        return m_container.getItemCount();
716    }
717
718    /**
719     * Returns the structure id to the given string item id.<p>
720     *
721     * @param itemId the item id
722     *
723     * @return the structure id
724     */
725    public CmsUUID getUUIDFromItemID(String itemId) {
726
727        return new CmsUUID(itemId);
728    }
729
730    /**
731     * Returns if the column with the given property id is visible and not collapsed.<p>
732     *
733     * @param propertyId the property id
734     *
735     * @return <code>true</code> if the column is visible
736     */
737    public boolean isColumnVisible(CmsResourceTableProperty propertyId) {
738
739        return Arrays.asList(m_fileTable.getVisibleColumns()).contains(propertyId)
740            && !m_fileTable.isColumnCollapsed(propertyId);
741    }
742
743    /**
744     * Removes a property provider.<p>
745     *
746     * @param provider the provider to remove
747     */
748    public void removePropertyProvider(I_ResourcePropertyProvider provider) {
749
750        m_propertyProviders.remove(provider);
751    }
752
753    /**
754     * Selects all resources.<p>
755     */
756    public void selectAll() {
757
758        m_fileTable.setValue(m_fileTable.getItemIds());
759    }
760
761    /**
762     * Sets the list of collapsed columns.<p>
763     *
764     * @param collapsedColumns the list of collapsed columns
765     */
766    public void setCollapsedColumns(Object... collapsedColumns) {
767
768        Set<Object> collapsedSet = Sets.newHashSet();
769        for (Object collapsed : collapsedColumns) {
770            collapsedSet.add(collapsed);
771        }
772        for (Object key : m_fileTable.getVisibleColumns()) {
773            m_fileTable.setColumnCollapsed(key, collapsedSet.contains(key));
774        }
775    }
776
777    /**
778     * Sets the table drag mode.<p>
779     *
780     * @param dragMode the drag mode
781     */
782    public void setDragMode(TableDragMode dragMode) {
783
784        m_fileTable.setDragMode(dragMode);
785    }
786
787    /**
788     * Sets the table drop handler.<p>
789     *
790     * @param handler the drop handler
791     */
792    public void setDropHandler(DropHandler handler) {
793
794        m_fileTable.setDropHandler(handler);
795    }
796
797    /**
798     * Selects an given object in table.<p>
799     *
800     * @param o object to be selected.
801     */
802    public void setValue(Set<String> o) {
803
804        m_fileTable.setValue(o);
805    }
806
807    /**
808     * Fills the file item data.<p>
809     *
810     * @param cms the cms context
811     * @param resource the resource
812     * @param locale the workplace locale
813     */
814    protected void fillItem(CmsObject cms, CmsResource resource, Locale locale) {
815
816        Item resourceItem = m_container.getItem(resource.getStructureId().toString());
817        if (resourceItem == null) {
818            resourceItem = m_container.addItem(resource.getStructureId().toString());
819        }
820        fillItemDefault(resourceItem, cms, resource, locale);
821        for (I_ResourcePropertyProvider provider : m_propertyProviders) {
822            provider.addItemProperties(resourceItem, cms, resource, locale);
823        }
824    }
825
826    /**
827     * Transforms the given item ids into UUIDs.<p>
828     *
829     * @param itemIds the item ids
830     *
831     * @return the UUIDs
832     */
833    protected List<CmsUUID> itemIdsToUUIDs(Collection<String> itemIds) {
834
835        List<CmsUUID> ids = new ArrayList<CmsUUID>();
836        for (String itemId : itemIds) {
837            if (itemId != null) {
838                ids.add(getUUIDFromItemID(itemId));
839            }
840        }
841        return ids;
842    }
843}