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.CmsProject; 033import org.opencms.file.CmsProperty; 034import org.opencms.file.CmsResource; 035import org.opencms.file.CmsResourceFilter; 036import org.opencms.main.CmsException; 037 038import java.util.ArrayList; 039import java.util.Arrays; 040import java.util.Collections; 041import java.util.Iterator; 042import java.util.List; 043 044/** 045 * A collector to fetch sorted XML contents in a folder or subtree based on their priority 046 * and date or title values.<p> 047 * 048 * The date or title information has to be stored as property for each resource.<p> 049 * 050 * @since 6.0.0 051 */ 052public class CmsPriorityResourceCollector extends A_CmsResourceCollector { 053 054 /** The standard priority value if no value was set on resource. */ 055 public static final int PRIORITY_STANDARD = 3; 056 057 /** The name of the channel property to read. */ 058 public static final String PROPERTY_CHANNEL = "collector.channel"; 059 060 /** The name of the priority property to read. */ 061 public static final String PROPERTY_PRIORITY = "collector.priority"; 062 063 /** Static array of the collectors implemented by this class. */ 064 private static final String[] COLLECTORS = { 065 "allInFolderPriorityDateAsc", 066 "allInSubTreePriorityDateAsc", 067 "allInFolderPriorityDateDesc", 068 "allInSubTreePriorityDateDesc", 069 "allInFolderPriorityTitleDesc", 070 "allInSubTreePriorityTitleDesc", 071 "allMappedToUriPriorityDateAsc", 072 "allMappedToUriPriorityDateDesc"}; 073 074 /** Array list for fast collector name lookup. */ 075 private static final List<String> COLLECTORS_LIST = Collections.unmodifiableList(Arrays.asList(COLLECTORS)); 076 077 /** 078 * @see org.opencms.file.collectors.I_CmsResourceCollector#getCollectorNames() 079 */ 080 public List<String> getCollectorNames() { 081 082 return COLLECTORS_LIST; 083 } 084 085 /** 086 * @see org.opencms.file.collectors.I_CmsResourceCollector#getCreateLink(org.opencms.file.CmsObject, java.lang.String, java.lang.String) 087 */ 088 public String getCreateLink(CmsObject cms, String collectorName, String param) throws CmsException { 089 090 // if action is not set, use default action 091 if (collectorName == null) { 092 collectorName = COLLECTORS[1]; 093 } 094 095 switch (COLLECTORS_LIST.indexOf(collectorName)) { 096 case 0: 097 case 2: 098 case 4: 099 // "allInFolderPriorityDateAsc", "allInFolderPriorityDateDesc" or "allInFolderPriorityTitleDesc" 100 return getCreateInFolder(cms, param); 101 case 1: 102 case 3: 103 case 5: 104 case 6: 105 case 7: 106 // "allInSubTreePriorityDateAsc", "allInSubTreePriorityDateDesc" or "allInSubTreePriorityTitleDesc" 107 // "allMappedToUriPriorityDateAsc", "allMappedToUriPriorityDateDesc" 108 return null; 109 default: 110 throw new CmsDataAccessException( 111 Messages.get().container(Messages.ERR_COLLECTOR_NAME_INVALID_1, collectorName)); 112 } 113 } 114 115 /** 116 * @see org.opencms.file.collectors.I_CmsResourceCollector#getCreateParam(org.opencms.file.CmsObject, java.lang.String, java.lang.String) 117 */ 118 public String getCreateParam(CmsObject cms, String collectorName, String param) throws CmsDataAccessException { 119 120 // if action is not set, use default action 121 if (collectorName == null) { 122 collectorName = COLLECTORS[1]; 123 } 124 125 switch (COLLECTORS_LIST.indexOf(collectorName)) { 126 case 0: 127 case 2: 128 case 4: 129 // "allInFolderPriorityDateAsc", "allInFolderPriorityDateDesc" or "allInFolderPriorityTitleDesc" 130 return param; 131 case 1: 132 case 3: 133 case 5: 134 case 6: 135 case 7: 136 // "allInSubTreePriorityDateAsc", "allInSubTreePriorityDateDesc" or "allInSubTreePriorityTitleDesc" 137 // "allMappedToUriPriorityDateAsc", "allMappedToUriPriorityDateDesc" 138 return null; 139 default: 140 throw new CmsDataAccessException( 141 Messages.get().container(Messages.ERR_COLLECTOR_NAME_INVALID_1, collectorName)); 142 } 143 } 144 145 /** 146 * @see org.opencms.file.collectors.A_CmsResourceCollector#getCreateTypeId(org.opencms.file.CmsObject, java.lang.String, java.lang.String) 147 */ 148 @Override 149 public int getCreateTypeId(CmsObject cms, String collectorName, String param) { 150 151 int result = -1; 152 if (param != null) { 153 result = new CmsCollectorData(param).getType(); 154 } 155 return result; 156 } 157 158 /** 159 * @see org.opencms.file.collectors.I_CmsResourceCollector#getResults(org.opencms.file.CmsObject, java.lang.String, java.lang.String) 160 */ 161 public List<CmsResource> getResults(CmsObject cms, String collectorName, String param) 162 throws CmsDataAccessException, CmsException { 163 164 return getResults(cms, collectorName, param, -1); 165 } 166 167 /** 168 * @see org.opencms.file.collectors.I_CmsResourceCollector#getResults(org.opencms.file.CmsObject, java.lang.String, java.lang.String) 169 */ 170 public List<CmsResource> getResults(CmsObject cms, String collectorName, String param, int numResults) 171 throws CmsException, CmsDataAccessException { 172 173 // if action is not set use default 174 if (collectorName == null) { 175 collectorName = COLLECTORS[0]; 176 } 177 178 switch (COLLECTORS_LIST.indexOf(collectorName)) { 179 180 case 0: 181 // "allInFolderPriorityDateAsc" 182 return allInFolderPriorityDate(cms, param, false, true, numResults); 183 case 1: 184 // "allInSubTreePriorityDateAsc" 185 return allInFolderPriorityDate(cms, param, true, true, numResults); 186 case 2: 187 // "allInFolderPriorityDateDesc" 188 return allInFolderPriorityDate(cms, param, false, false, numResults); 189 case 3: 190 // "allInSubTreePriorityDateDesc" 191 return allInFolderPriorityDate(cms, param, true, false, numResults); 192 case 4: 193 // "allInFolderPriorityTitleDesc" 194 return allInFolderPriorityTitle(cms, param, false, numResults); 195 case 5: 196 // "allInSubTreePriorityTitleDesc" 197 return allInFolderPriorityTitle(cms, param, true, numResults); 198 case 6: 199 // "allMappedToUriPriorityDateAsc" 200 return allMappedToUriPriorityDate(cms, param, true, numResults); 201 case 7: 202 // "allMappedToUriPriorityDateDesc" 203 return allMappedToUriPriorityDate(cms, param, false, numResults); 204 default: 205 throw new CmsDataAccessException( 206 Messages.get().container(Messages.ERR_COLLECTOR_NAME_INVALID_1, collectorName)); 207 } 208 209 } 210 211 /** 212 * Returns a list of all resource in a specified folder sorted by priority, then date ascending or descending.<p> 213 * 214 * @param cms the current OpenCms user context 215 * @param param the folder name to use 216 * @param tree if true, look in folder and all child folders, if false, look only in given folder 217 * @param asc if true, the date sort order is ascending, otherwise descending 218 * @param numResults the number of results 219 * 220 * @return all resources in the folder matching the given criteria 221 * 222 * @throws CmsException if something goes wrong 223 */ 224 protected List<CmsResource> allInFolderPriorityDate( 225 CmsObject cms, 226 String param, 227 boolean tree, 228 boolean asc, 229 int numResults) throws CmsException { 230 231 CmsCollectorData data = new CmsCollectorData(param); 232 String foldername = CmsResource.getFolderPath(data.getFileName()); 233 234 CmsResourceFilter filter = CmsResourceFilter.DEFAULT.addRequireType(data.getType()).addExcludeFlags( 235 CmsResource.FLAG_TEMPFILE); 236 if (data.isExcludeTimerange() && !cms.getRequestContext().getCurrentProject().isOnlineProject()) { 237 // include all not yet released and expired resources in an offline project 238 filter = filter.addExcludeTimerange(); 239 } 240 List<CmsResource> result = cms.readResources(foldername, filter, tree); 241 242 // create priority comparator to use to sort the resources 243 CmsPriorityDateResourceComparator comparator = new CmsPriorityDateResourceComparator(cms, asc); 244 Collections.sort(result, comparator); 245 246 return shrinkToFit(result, data.getCount(), numResults); 247 } 248 249 /** 250 * Returns a list of all resource in a specified folder sorted by priority descending, then Title ascending.<p> 251 * 252 * @param cms the current OpenCms user context 253 * @param param the folder name to use 254 * @param tree if true, look in folder and all child folders, if false, look only in given folder 255 * @param numResults the number of results 256 * 257 * @return all resources in the folder matching the given criteria 258 * 259 * @throws CmsException if something goes wrong 260 */ 261 protected List<CmsResource> allInFolderPriorityTitle(CmsObject cms, String param, boolean tree, int numResults) 262 throws CmsException { 263 264 CmsCollectorData data = new CmsCollectorData(param); 265 String foldername = CmsResource.getFolderPath(data.getFileName()); 266 267 CmsResourceFilter filter = CmsResourceFilter.DEFAULT.addRequireType(data.getType()).addExcludeFlags( 268 CmsResource.FLAG_TEMPFILE); 269 if (data.isExcludeTimerange() && !cms.getRequestContext().getCurrentProject().isOnlineProject()) { 270 // include all not yet released and expired resources in an offline project 271 filter = filter.addExcludeTimerange(); 272 } 273 List<CmsResource> result = cms.readResources(foldername, filter, tree); 274 275 // create priority comparator to use to sort the resources 276 CmsPriorityTitleResourceComparator comparator = new CmsPriorityTitleResourceComparator(cms); 277 Collections.sort(result, comparator); 278 279 return shrinkToFit(result, data.getCount(), numResults); 280 } 281 282 /** 283 * Returns a list of all resource from specified folder that have been mapped to 284 * the currently requested uri, sorted by priority, then date ascending or descending.<p> 285 * 286 * @param cms the current OpenCms user context 287 * @param param the folder name to use 288 * @param asc if true, the date sort order is ascending, otherwise descending 289 * @param numResults the number of results 290 * 291 * @return all resources in the folder matching the given criteria 292 * 293 * @throws CmsException if something goes wrong 294 */ 295 protected List<CmsResource> allMappedToUriPriorityDate(CmsObject cms, String param, boolean asc, int numResults) 296 throws CmsException { 297 298 CmsCollectorData data = new CmsCollectorData(param); 299 String foldername = CmsResource.getFolderPath(data.getFileName()); 300 301 CmsResourceFilter filter = CmsResourceFilter.DEFAULT.addRequireType(data.getType()).addExcludeFlags( 302 CmsResource.FLAG_TEMPFILE); 303 if (data.isExcludeTimerange() && !cms.getRequestContext().getCurrentProject().isOnlineProject()) { 304 // include all not yet released and expired resources in an offline project 305 filter = filter.addExcludeTimerange(); 306 } 307 308 List<CmsResource> result = cms.readResources(foldername, filter, true); 309 List<CmsResource> mapped = new ArrayList<CmsResource>(); 310 311 // sort out the resources mapped to the current page 312 Iterator<CmsResource> i = result.iterator(); 313 while (i.hasNext()) { 314 CmsResource res = i.next(); 315 // read all properties - reason: comparator will do this later anyway, so we just prefill the cache 316 CmsProperty prop = cms.readPropertyObject(res, PROPERTY_CHANNEL, false); 317 if (!prop.isNullProperty()) { 318 if (CmsProject.isInsideProject( 319 prop.getValueList(), 320 cms.getRequestContext().getSiteRoot() + cms.getRequestContext().getUri())) { 321 mapped.add(res); 322 } 323 } 324 } 325 326 if (mapped.isEmpty()) { 327 // nothing was mapped, no need for further processing 328 return mapped; 329 } 330 331 // create priority comparator to use to sort the resources 332 CmsPriorityDateResourceComparator comparator = new CmsPriorityDateResourceComparator(cms, asc); 333 Collections.sort(mapped, comparator); 334 335 return shrinkToFit(mapped, data.getCount(), numResults); 336 } 337}