/* * File : $Source: /alkacon/cvs/alkacon/com.alkacon.opencms.documentcenter/src/com/alkacon/opencms/documentcenter/NewDocumentsTree.java,v $ * Date : $Date: 2010/03/19 15:31:13 $ * Version: $Revision: 1.3 $ * * This file is part of the Alkacon OpenCms Add-On Module Package * * Copyright (c) 2010 Alkacon Software GmbH (http://www.alkacon.com) * * The Alkacon OpenCms Add-On Module Package is free software: * you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Alkacon OpenCms Add-On Module Package is distributed * in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with the Alkacon OpenCms Add-On Module Package. * If not, see http://www.gnu.org/licenses/. * * For further information about Alkacon Software GmbH, please see the * company website: http://www.alkacon.com. * * For further information about OpenCms, please see the * project website: http://www.opencms.org. */ package com.alkacon.opencms.v8.documentcenter; import org.opencms.file.CmsObject; import org.opencms.file.CmsResource; import org.opencms.file.CmsResourceFilter; import org.opencms.main.CmsException; import org.opencms.main.CmsLog; import org.opencms.util.CmsUUID; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.GregorianCalendar; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.StringTokenizer; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; /** * Helper class which provides static methods for the new documents functions of the document management.<p> * * @author Andreas Zahner * @author Michael Emmerich * * @version $Revision: 1.3 $ * * @since 6.0.0 */ public final class NewDocumentsTree { /** Session key prefix. */ protected static final String C_SESSION_KEY_PARAMS = NewDocumentsTree.class.getName() + ".param."; /** Session key for search all. */ public static final String C_DOCUMENT_SEARCH_PARAM_ALL = C_SESSION_KEY_PARAMS + "all"; /** Session key for categorylist. */ public static final String C_DOCUMENT_SEARCH_PARAM_CATEGORYLIST = C_SESSION_KEY_PARAMS + "categoryList"; /** Session key for enddate. */ public static final String C_DOCUMENT_SEARCH_PARAM_ENDDATE = C_SESSION_KEY_PARAMS + "endDate"; /** Session key for site. */ public static final String C_DOCUMENT_SEARCH_PARAM_SITE = C_SESSION_KEY_PARAMS + "site"; /** Session key for startdate. */ public static final String C_DOCUMENT_SEARCH_PARAM_STARTDATE = C_SESSION_KEY_PARAMS + "startDate"; /** The log object for this class. */ private static final Log LOG = CmsLog.getLog(NewDocumentsTree.class); /** * Hide public constructor.<p> */ private NewDocumentsTree() { //noop } /** * Creates an HTML list with checkboxes for all given categories.<p> * * @param categories list with the categories (LgtCategory) * @param attributes optional attributes for the input tags * @return the HTML code for a category input list */ public static String buildCategoryList(List<CmsCategory> categories, String attributes) { StringBuffer retValue = new StringBuffer(128); Iterator<CmsCategory> i = categories.iterator(); int counter = 0; while (i.hasNext()) { CmsCategory curCat = i.next(); if (!"".equals(curCat.getCmsResource())) { retValue.append("<input type=\"checkbox\" name=\"cat" + counter + "\" id=\"cat" + counter + "\" value=\"" + curCat.getCmsResource() + "\""); if (attributes != null) { retValue.append(" " + attributes); } retValue.append("> "); retValue.append(curCat.getTitle() + "<br>\n"); counter++; } } // clear objects to release memory i = null; return retValue.toString(); } /** * Builds the HTML code for a select box of days.<p> * * @param timeMillis the time in milliseconds which should be preselected * @param fieldName the prefix of the name attribute * @param attributes optional additional attributes of the select tag * @param localeString the current locale String * @return the HTML code for a select box of days */ public static String buildSelectDay(long timeMillis, String fieldName, String attributes, String localeString) { StringBuffer retValue = new StringBuffer(512); Locale locale = new Locale(localeString); Calendar cal = new GregorianCalendar(locale); cal.setTimeInMillis(timeMillis); retValue.append("<select name=\"" + fieldName + "day\""); if (attributes != null) { retValue.append(" " + attributes); } retValue.append(">\n"); for (int i = 1; i < 32; i++) { retValue.append("\t<option value=\"" + i + "\""); if (cal.get(Calendar.DAY_OF_MONTH) == i) { retValue.append(" selected=\"selected\""); } retValue.append(">" + i + "</option>\n"); } retValue.append("</select>\n"); return retValue.toString(); } /** * Builds the HTML code for a select box of months.<p> * * @param timeMillis the time in milliseconds which should be preselected * @param fieldName the prefix of the name attribute * @param attributes optional additional attributes of the select tag * @param localeString the current locale String * @return the HTML code for a select box of months */ public static String buildSelectMonth(long timeMillis, String fieldName, String attributes, String localeString) { StringBuffer retValue = new StringBuffer(512); Locale locale = new Locale(localeString); Calendar cal = new GregorianCalendar(locale); cal.setTimeInMillis(timeMillis); Calendar calTemp = new GregorianCalendar(locale); calTemp.setTimeInMillis(timeMillis); // set day to 2 to avoid display errors for days 29, 30 and 31 calTemp.set(Calendar.DAY_OF_MONTH, 2); DateFormat df = new SimpleDateFormat("MMMM", locale); retValue.append("<select name=\"" + fieldName + "month\""); if (attributes != null) { retValue.append(" " + attributes); } retValue.append(">\n"); for (int i = 0; i < 12; i++) { calTemp.set(Calendar.MONTH, i); retValue.append("\t<option value=\"" + (i + 1) + "\""); if (cal.get(Calendar.MONTH) == i) { retValue.append(" selected=\"selected\""); } retValue.append(">" + df.format(calTemp.getTime()) + "</option>\n"); } retValue.append("</select>\n"); return retValue.toString(); } /** * Builds the HTML code for a select box of years.<p> * * @param timeMillis the time in milliseconds which should be preselected * @param fieldName the prefix of the name attribute * @param attributes optional additional attributes of the select tag * @param localeString the current locale String * @param startyear the year to start with * @param endyear the last year to display in the selection * @return the HTML code for a select box of years */ public static String buildSelectYear( long timeMillis, String fieldName, String attributes, String localeString, int startyear, int endyear) { StringBuffer retValue = new StringBuffer(512); Locale locale = new Locale(localeString); Calendar cal = new GregorianCalendar(locale); cal.setTimeInMillis(timeMillis); if (startyear > endyear) { startyear = endyear; } retValue.append("<select name=\"" + fieldName + "year\""); if (attributes != null) { retValue.append(" " + attributes); } retValue.append(">\n"); for (int i = startyear; i <= endyear; i++) { retValue.append("\t<option value=\"" + i + "\""); if (cal.get(Calendar.YEAR) == i) { retValue.append(" selected=\"selected\""); } retValue.append(">" + i + "</option>\n"); } retValue.append("</select>\n"); return retValue.toString(); } /** * Returns a list of resources which contains no linked entries.<p> * * Links on the same resource entry are deleted from the list of resources. * This method has to be used after calling the method CmsObject.getResourcesInTimeRange(String, long, long); * * @param resources the list of resources which may contain links * @return a filtered list of resources */ public static List<CmsResource> filterLinkedResources(List<CmsResource> resources) { List<CmsResource> filteredResources = new ArrayList<CmsResource>(); Set<CmsUUID> addedResources = new HashSet<CmsUUID>(); long currentTime = System.currentTimeMillis(); Iterator<CmsResource> i = resources.iterator(); while (i.hasNext()) { CmsResource currentResource = i.next(); // filter those documents that are folders or outside the release and expire window if (currentResource.isFolder() || (currentResource.getDateReleased() > currentTime) || (currentResource.getDateExpired() < currentTime)) { // skip folders and resources outside time range continue; } if (CmsDocumentFactory.isIgnoredDocument(currentResource.getRootPath(), true)) { // this resource is ignored, skip it before checking the resource id continue; } CmsUUID resId = currentResource.getResourceId(); if (!addedResources.contains(resId)) { // add resource to return list and ID to set addedResources.add(resId); filteredResources.add(currentResource); } } // clear objects to release memory i = null; addedResources = null; resources = null; return filteredResources; } /** * Returns a String which holds the selected categories for the result page of the new documents query.<p> * * @param cms the CmsObject * @param request the HttpServletRequest * @param messageAll the localized message String used when all categories were selected * @return String with comma separated selected categories or localized "all" message */ public static String getCategories(CmsObject cms, HttpServletRequest request, String messageAll) { StringBuffer retValue = new StringBuffer(128); // get the current user's HHTP session //HttpSession session = ((HttpServletRequest)cms.getRequestContext().getRequest().getOriginalRequest()).getSession(); HttpSession session = request.getSession(); // get the required parameters String paramAll = (String)session.getAttribute(C_DOCUMENT_SEARCH_PARAM_ALL); if ("true".equals(paramAll)) { return messageAll; } else { List<String> categories = getCategoryList((String)session.getAttribute(C_DOCUMENT_SEARCH_PARAM_CATEGORYLIST)); Iterator<String> i = categories.iterator(); while (i.hasNext()) { String path = i.next(); try { retValue.append(cms.readPropertyObject(path, CmsCategory.CATEGORY_TITLE, false).getValue()); } catch (CmsException e) { // noop } if (i.hasNext()) { retValue.append(", "); } } // clear objects to release memory categories = null; i = null; } return retValue.toString(); } /** * Builds a list of the categories which were selected in the form.<p> * * @param allCategories String with all selected category paths * @return List with all selected categories (holds String objects with absolute paths) */ public static List<String> getCategoryList(String allCategories) { ArrayList<String> categories = new ArrayList<String>(); // get the indiviadual category paths from the token StringTokenizer T = new StringTokenizer(allCategories, CategoryTree.C_LIST_SEPARATOR); while (T.hasMoreTokens()) { String curToken = T.nextToken(); if (!"".equals(curToken.trim())) { // add the category to the list categories.add(curToken); } } return categories; } /** * Returns a list of new resources in the specified folder or category folder depending on the request parameters.<p> * * @param cms the CmsObject to perform some operations * @param request the HttpServletRequest to get the needed request parameters * @return the list of new resources */ public static List<CmsResource> getNewResources(CmsObject cms, HttpServletRequest request) { // get the current user's HHTP session HttpSession session = request.getSession(); String startFolder = (String)request.getAttribute(CmsDocumentFrontend.ATTR_FULLPATH); // get the required parameters String paramAll = (String)session.getAttribute(C_DOCUMENT_SEARCH_PARAM_ALL); String paramStartDate = (String)session.getAttribute(C_DOCUMENT_SEARCH_PARAM_STARTDATE); String paramEndDate = (String)session.getAttribute(C_DOCUMENT_SEARCH_PARAM_ENDDATE); // parse the date Strings to long long startDate = Long.parseLong(paramStartDate); long endDate = Long.parseLong(paramEndDate); // create list of categories if selected List<String> selectedCategoryList = new ArrayList<String>(); paramAll = (paramAll == null) ? "false" : paramAll; if (!"true".equals(paramAll)) { // search individual categories selectedCategoryList = getCategoryList((String)session.getAttribute(C_DOCUMENT_SEARCH_PARAM_CATEGORYLIST)); if (selectedCategoryList.size() == 0) { return new ArrayList<CmsResource>(0); } } String openedCategories = CategoryTree.getTreeInfo(cms, CategoryTree.C_USER_INFO_OPENED_CATEGORIES, request); List<String> openedCategoryList = CategoryTree.commaStringToList( openedCategories, CategoryTree.C_LIST_SEPARATOR); return getNewResourceList(cms, startFolder, startDate, endDate, selectedCategoryList, openedCategoryList); } /** * Creates a nice localized date String from the given String.<p> * * @param dateLongString the date as String representation of a long value * @param localeString the current locale String * @return nice formatted date string in long mode (e.g. 15. April 2003) */ public static String getNiceDate(String dateLongString, String localeString) { Locale locale = new Locale(localeString.toLowerCase()); DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, locale); Calendar cal = new GregorianCalendar(locale); try { cal.setTimeInMillis(Long.parseLong(dateLongString)); } catch (Exception e) { //noop } return df.format(cal.getTime()); } /** * Creates a nice localized date String from the given day, month and year Strings.<p> * * @param day the number of the day as String * @param month the number of the month as String * @param year the number of the year as String * @param localeString the current locale String * @return nice formatted date string in long mode (e.g. 15. April 2003) */ public static String getNiceDate(String day, String month, String year, String localeString) { Locale locale = new Locale(localeString.toLowerCase()); DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, locale); Calendar cal = new GregorianCalendar(locale); try { cal.set(Integer.parseInt(year), Integer.parseInt(month) - 1, Integer.parseInt(day)); } catch (Exception e) { // noop } return df.format(cal.getTime()); } /** * Creates a list of new resources of the specified folder and filters the unwanted resources.<p> * * If the parameter categoryFolders is an empty list, all new resources are returned, otherwise * only those resources which are in a subfolder specified by the list.<p> * @param cms the CmsObject * @param startFolder the root folder * @param startDate the start date in milliseconds * @param endDate the end date in milliseconds * @param selectedCategories list with selected categories/folders * @param openedCategories list with opened categories/folders * @return list of new resources */ private static List<CmsResource> getNewResourceList( CmsObject cms, String startFolder, long startDate, long endDate, List<String> selectedCategories, List<String> openedCategories) { List<CmsResource> searchResult = null; List<CmsResource> foundResources = null; Set<CmsUUID> addedResources = null; if (LOG.isDebugEnabled()) { StringBuffer buf = new StringBuffer(); for (int i = 0, n = selectedCategories.size(); i < n; i++) { buf.append(selectedCategories.get(i)); if (i < (n - 1)) { buf.append(", "); } } LOG.debug("################ INPUT VALUES FOR NEW DOCUMENTS SEARCH"); LOG.debug("startDate : " + startDate + " " + new java.util.Date(startDate).toString()); LOG.debug("endDate : " + endDate + " " + new java.util.Date(endDate).toString()); LOG.debug("startFolder : " + startFolder); LOG.debug("categories : " + buf.toString()); } try { // get all resources in the site root which are in the time range CmsResourceFilter filter = CmsResourceFilter.IGNORE_EXPIRATION; filter = filter.addRequireLastModifiedAfter(startDate); filter = filter.addRequireLastModifiedBefore(endDate); foundResources = cms.readResources(startFolder, filter); } catch (CmsException e) { if (LOG.isErrorEnabled()) { LOG.error("Error reading resources in time range " + new java.util.Date(startDate).toString() + " - " + new java.util.Date(endDate).toString() + " below folder " + startFolder, e); } foundResources = Collections.emptyList(); } if (selectedCategories.size() == 0) { // return all found resources with filtered links searchResult = filterLinkedResources(foundResources); } else { addedResources = new HashSet<CmsUUID>(); searchResult = new ArrayList<CmsResource>(); long currentTime = System.currentTimeMillis(); for (int i = 0, n = foundResources.size(); i < n; i++) { // analyze each resource if it has to be included in the search result CmsResource resource = foundResources.get(i); // filter those documents that are folders or outside the release and expire window if (resource.isFolder() || (resource.getDateReleased() > currentTime) || (resource.getDateExpired() < currentTime)) { // skip folders and resources outside time range continue; } String resourceName = cms.getRequestContext().removeSiteRoot(resource.getRootPath()); String parentFolder = CmsResource.getParentFolder(resourceName); boolean addToResult = false; if (!selectedCategories.contains(parentFolder) && openedCategories.contains(parentFolder)) { // skip resources that are inside an opened, but un-selected category/folder continue; } // check if the parent folder of the resource is one of the selected categories/folders addToResult = selectedCategories.contains(parentFolder); if (!addToResult) { // check if the resource is inside a collapsed sub-tree // of a selected category int openedCategoryCount = 0; while (!"/".equals(parentFolder)) { if (openedCategories.contains(parentFolder)) { openedCategoryCount++; } if (selectedCategories.contains(parentFolder) && (openedCategoryCount == 0)) { // we found a selected parent category, // and it's sub-tree is collapsed addToResult = true; break; } parentFolder = CmsResource.getParentFolder(parentFolder); } } if (!addToResult) { // continue with the next resource continue; } if (CmsDocumentFactory.isIgnoredDocument(resourceName, true)) { // this resource is ignored, skip it before checking the resource id continue; } // check if the resource is a sibling that has already been added to the search result CmsUUID resourceId = resource.getResourceId(); if (!addedResources.contains(resourceId)) { // add resource to the result addedResources.add(resourceId); searchResult.add(resource); } } } return searchResult; } }