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 GmbH & Co. KG, 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.file.collectors;
029
030import org.opencms.file.CmsDataAccessException;
031import org.opencms.file.CmsObject;
032import org.opencms.file.CmsResource;
033import org.opencms.file.CmsResourceFilter;
034import org.opencms.file.I_CmsResource;
035import org.opencms.jsp.CmsJspNavBuilder;
036import org.opencms.jsp.CmsJspNavElement;
037import org.opencms.main.CmsException;
038import org.opencms.main.CmsIllegalArgumentException;
039import org.opencms.main.CmsLog;
040
041import java.util.ArrayList;
042import java.util.Arrays;
043import java.util.Collections;
044import java.util.HashMap;
045import java.util.List;
046import java.util.Map;
047
048import org.apache.commons.logging.Log;
049
050/**
051 * A default resource collector to generate some example list of resources from the VFS.<p>
052 *
053 * @since 6.0.0
054 */
055public class CmsDefaultResourceCollector extends A_CmsResourceCollector {
056
057    /** Static array of the collectors implemented by this class. */
058    private static final String[] COLLECTORS = {
059        "singleFile",
060        "allInFolder",
061        "allInFolderDateReleasedDesc",
062        "allInFolderNavPos",
063        "allInSubTree",
064        "allInSubTreeDateReleasedDesc",
065        "allInSubTreeNavPos"};
066
067    /** Array list for fast collector name lookup. */
068    private static final List<String> COLLECTORS_LIST = Collections.unmodifiableList(Arrays.asList(COLLECTORS));
069
070    /** The log object for this class. */
071    private static final Log LOG = CmsLog.getLog(CmsDefaultResourceCollector.class);
072
073    /**
074     * @see org.opencms.file.collectors.I_CmsResourceCollector#getCollectorNames()
075     */
076    public List<String> getCollectorNames() {
077
078        return COLLECTORS_LIST;
079    }
080
081    /**
082     * @see org.opencms.file.collectors.I_CmsResourceCollector#getCreateLink(org.opencms.file.CmsObject, java.lang.String, java.lang.String)
083     */
084    public String getCreateLink(CmsObject cms, String collectorName, String param)
085    throws CmsDataAccessException, CmsException {
086
087        // if action is not set, use default action
088        if (collectorName == null) {
089            collectorName = COLLECTORS[0];
090        }
091
092        switch (COLLECTORS_LIST.indexOf(collectorName)) {
093            case 0:
094                // "singleFile"
095                return null;
096            case 1:
097                // "allInFolder"
098            case 2:
099                // "allInFolderDateReleasedDesc"
100            case 3:
101                // "allInFolderNavPos"
102                return getCreateInFolder(cms, param);
103            case 4:
104                // "allInSubTree"
105            case 5:
106                // "allInSubTreeDateReleasedDesc"
107            case 6:
108                // "allInSubTreeNavPos"
109                return null;
110            default:
111                throw new CmsDataAccessException(
112                    Messages.get().container(Messages.ERR_COLLECTOR_NAME_INVALID_1, collectorName));
113        }
114    }
115
116    /**
117     * @see org.opencms.file.collectors.I_CmsResourceCollector#getCreateParam(org.opencms.file.CmsObject, java.lang.String, java.lang.String)
118     */
119    public String getCreateParam(CmsObject cms, String collectorName, String param) throws CmsDataAccessException {
120
121        // if action is not set, use default action
122        if (collectorName == null) {
123            collectorName = COLLECTORS[0];
124        }
125
126        switch (COLLECTORS_LIST.indexOf(collectorName)) {
127            case 0:
128                // "singleFile"
129                return null;
130            case 1:
131                // "allInFolder"
132            case 2:
133                // "allInFolderDateReleasedDesc"
134            case 3:
135                // "allInFolderNavPos"
136                return param;
137            case 4:
138                // "allInSubTree"
139            case 5:
140                // "allInSubTreeDateReleasedDesc"
141            case 6:
142                // "allInSubTreeNavPos"
143                return null;
144            default:
145                throw new CmsDataAccessException(
146                    Messages.get().container(Messages.ERR_COLLECTOR_NAME_INVALID_1, collectorName));
147        }
148    }
149
150    /**
151     * @see org.opencms.file.collectors.A_CmsResourceCollector#getCreateTypeId(org.opencms.file.CmsObject, java.lang.String, java.lang.String)
152     */
153    @Override
154    public int getCreateTypeId(CmsObject cms, String collectorName, String param) {
155
156        int result = -1;
157        if (param != null) {
158            result = new CmsCollectorData(param).getType();
159        }
160        return result;
161    }
162
163    /**
164     * @see org.opencms.file.collectors.I_CmsResourceCollector#getResults(org.opencms.file.CmsObject, java.lang.String, java.lang.String)
165     */
166    public List<CmsResource> getResults(CmsObject cms, String collectorName, String param)
167    throws CmsDataAccessException, CmsException {
168
169        return getResults(cms, collectorName, param, -1);
170    }
171
172    /**
173     * @see org.opencms.file.collectors.I_CmsResourceCollector#getResults(org.opencms.file.CmsObject, java.lang.String, java.lang.String)
174     */
175    public List<CmsResource> getResults(CmsObject cms, String collectorName, String param, int numResults)
176    throws CmsDataAccessException, CmsException {
177
178        // if action is not set use default
179        if (collectorName == null) {
180            collectorName = COLLECTORS[0];
181        }
182
183        switch (COLLECTORS_LIST.indexOf(collectorName)) {
184            case 0:
185                // "singleFile"
186                return getSingleFile(cms, param);
187            case 1:
188                // "allInFolder"
189                return getAllInFolder(cms, param, false, numResults);
190            case 2:
191                // "allInFolderDateReleasedDesc"
192                return allInFolderDateReleasedDesc(cms, param, false, numResults);
193            case 3:
194                // allInFolderNavPos"
195                return allInFolderNavPos(cms, param, false, numResults);
196            case 4:
197                // "allInSubTree"
198                return getAllInFolder(cms, param, true, numResults);
199            case 5:
200                // "allInSubTreeDateReleasedDesc"
201                return allInFolderDateReleasedDesc(cms, param, true, numResults);
202            case 6:
203                // "allInSubTreeNavPos"
204                return allInFolderNavPos(cms, param, true, numResults);
205            default:
206                throw new CmsDataAccessException(
207                    Messages.get().container(Messages.ERR_COLLECTOR_NAME_INVALID_1, collectorName));
208        }
209    }
210
211    /**
212     * Returns a List of all resources in the folder pointed to by the parameter
213     * sorted by the release date, descending.<p>
214     *
215     * @param cms the current CmsObject
216     * @param param the folder name to use
217     * @param tree if true, look in folder and all child folders, if false, look only in given folder
218     * @param numResults the number of results
219     *
220     * @return a List of all resources in the folder pointed to by the parameter
221     *      sorted by the release date, descending
222     *
223     * @throws CmsException if something goes wrong
224     */
225    protected List<CmsResource> allInFolderDateReleasedDesc(CmsObject cms, String param, boolean tree, int numResults)
226    throws CmsException {
227
228        CmsCollectorData data = new CmsCollectorData(param);
229        String foldername = CmsResource.getFolderPath(data.getFileName());
230
231        CmsResourceFilter filter = CmsResourceFilter.DEFAULT_FILES.addRequireType(data.getType()).addExcludeFlags(
232            CmsResource.FLAG_TEMPFILE);
233        if (data.isExcludeTimerange() && !cms.getRequestContext().getCurrentProject().isOnlineProject()) {
234            // include all not yet released and expired resources in an offline project
235            filter = filter.addExcludeTimerange();
236        }
237        List<CmsResource> result = cms.readResources(foldername, filter, tree);
238
239        Collections.sort(result, I_CmsResource.COMPARE_DATE_RELEASED);
240
241        return shrinkToFit(result, data.getCount(), numResults);
242    }
243
244    /**
245     * Collects all resources in a folder (or subtree) sorted by the NavPos property.<p>
246     *
247     * @param cms the current user's Cms object
248     * @param param the collector's parameter(s)
249     * @param readSubTree if true, collects all resources in the subtree
250     * @param numResults the number of results
251     * @return a List of Cms resources found by the collector
252     * @throws CmsException if something goes wrong
253     *
254     */
255    protected List<CmsResource> allInFolderNavPos(CmsObject cms, String param, boolean readSubTree, int numResults)
256    throws CmsException {
257
258        CmsCollectorData data = new CmsCollectorData(param);
259        String foldername = CmsResource.getFolderPath(data.getFileName());
260
261        CmsResourceFilter filter = CmsResourceFilter.DEFAULT_FILES.addRequireType(data.getType()).addExcludeFlags(
262            CmsResource.FLAG_TEMPFILE);
263        if (data.isExcludeTimerange() && !cms.getRequestContext().getCurrentProject().isOnlineProject()) {
264            // include all not yet released and expired resources in an offline project
265            filter = filter.addExcludeTimerange();
266        }
267        List<CmsResource> foundResources = cms.readResources(foldername, filter, readSubTree);
268
269        // the Cms resources are saved in a map keyed by their nav elements
270        // to save time sorting the resources by the value of their NavPos property
271        CmsJspNavBuilder navBuilder = new CmsJspNavBuilder(cms);
272        Map<CmsJspNavElement, CmsResource> navElementMap = new HashMap<CmsJspNavElement, CmsResource>();
273        for (int i = 0, n = foundResources.size(); i < n; i++) {
274
275            CmsResource resource = foundResources.get(i);
276            CmsJspNavElement navElement = navBuilder.getNavigationForResource(cms.getSitePath(resource));
277
278            // check if the resource has the NavPos property set or not
279            if ((navElement != null) && (navElement.getNavPosition() != Float.MAX_VALUE)) {
280                navElementMap.put(navElement, resource);
281            } else if (LOG.isInfoEnabled()) {
282                // printing a log messages makes it a little easier to identify
283                // resources having not the NavPos property set
284                LOG.info(
285                    Messages.get().getBundle().key(Messages.LOG_RESOURCE_WITHOUT_NAVPROP_1, cms.getSitePath(resource)));
286            }
287        }
288
289        // all found resources have the NavPos property set
290        // sort the nav. elements, and pull the found Cms resources
291        // from the map in the correct order into a list
292        // only resources with the NavPos property set are used here
293        List<CmsJspNavElement> navElementList = new ArrayList<CmsJspNavElement>(navElementMap.keySet());
294        List<CmsResource> result = new ArrayList<CmsResource>();
295
296        Collections.sort(navElementList);
297        for (int i = 0, n = navElementList.size(); i < n; i++) {
298
299            CmsJspNavElement navElement = navElementList.get(i);
300            result.add(navElementMap.get(navElement));
301        }
302
303        return shrinkToFit(result, data.getCount(), numResults);
304    }
305
306    /**
307     * Returns all resources in the folder pointed to by the parameter.<p>
308     *
309     * @param cms the current OpenCms user context
310     * @param param the folder name to use
311     * @param tree if true, look in folder and all child folders, if false, look only in given folder
312     * @param numResults the number of results
313     *
314     * @return all resources in the folder matching the given criteria
315     *
316     * @throws CmsException if something goes wrong
317     * @throws CmsIllegalArgumentException if the given param argument is not a link to a single file
318     *
319     */
320    protected List<CmsResource> getAllInFolder(CmsObject cms, String param, boolean tree, int numResults)
321    throws CmsException, CmsIllegalArgumentException {
322
323        CmsCollectorData data = new CmsCollectorData(param);
324        String foldername = CmsResource.getFolderPath(data.getFileName());
325
326        CmsResourceFilter filter = CmsResourceFilter.DEFAULT_FILES.addRequireType(data.getType()).addExcludeFlags(
327            CmsResource.FLAG_TEMPFILE);
328        if (data.isExcludeTimerange() && !cms.getRequestContext().getCurrentProject().isOnlineProject()) {
329            // include all not yet released and expired resources in an offline project
330            filter = filter.addExcludeTimerange();
331        }
332        List<CmsResource> result = cms.readResources(foldername, filter, tree);
333
334        Collections.sort(result, I_CmsResource.COMPARE_ROOT_PATH);
335        Collections.reverse(result);
336
337        return shrinkToFit(result, data.getCount(), numResults);
338    }
339
340    /**
341     * Returns a List containing the resources pointed to by the parameter.<p>
342     *
343     * @param cms the current CmsObject
344     * @param param the name of the file to load
345     *
346     * @return a List containing the resources pointed to by the parameter
347     *
348     * @throws CmsException if something goes wrong
349     */
350    protected List<CmsResource> getSingleFile(CmsObject cms, String param) throws CmsException {
351
352        if ((param == null) || (cms == null)) {
353            throw new CmsIllegalArgumentException(Messages.get().container(Messages.ERR_COLLECTOR_PARAM_SINGLE_FILE_0));
354        }
355
356        // create a list and return it
357        List<CmsResource> result = new ArrayList<CmsResource>(1);
358        if (cms.getRequestContext().getCurrentProject().isOnlineProject()) {
359            result.add(cms.readFile(param));
360        } else {
361            // ignore release and expiration date in offline projects to be able to preview file
362            result.add(cms.readFile(param, CmsResourceFilter.IGNORE_EXPIRATION));
363        }
364        return result;
365    }
366}