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.jsp.search.result; 029 030import org.opencms.i18n.CmsEncoder; 031import org.opencms.jsp.search.controller.I_CmsSearchControllerFacetField; 032import org.opencms.jsp.search.controller.I_CmsSearchControllerFacetQuery; 033import org.opencms.jsp.search.controller.I_CmsSearchControllerFacetRange; 034import org.opencms.main.CmsLog; 035import org.opencms.util.CmsCollectionsGenericWrapper; 036 037import java.util.Arrays; 038import java.util.Collection; 039import java.util.HashMap; 040import java.util.List; 041import java.util.Map; 042 043import org.apache.commons.collections.Transformer; 044import org.apache.commons.logging.Log; 045 046/** 047 * State parameter wrapper that allows to manipulate the request parameters representing the state 048 * of the current search. It can be used to generate links for an adjusted search. 049 */ 050public class CmsSearchStateParameters implements I_CmsSearchStateParameters { 051 052 /** Logger for the class. */ 053 protected static final Log LOG = CmsLog.getLog(CmsSearchStateParameters.class); 054 055 /** Map of request parameters, representing the search's state. */ 056 Map<String, String[]> m_params; 057 /** The result of the search. */ 058 I_CmsSearchResultWrapper m_result; 059 060 /** Map with page numbers as keys and the according state parameters as values. */ 061 Map<String, I_CmsSearchStateParameters> m_paginationMap; 062 /** Map from sort options to state parameters. */ 063 Map<String, I_CmsSearchStateParameters> m_sortingMap; 064 /** Map from facet names to state parameters without the filter queries for the facet. */ 065 Map<String, I_CmsSearchStateParameters> m_resetFacetMap; 066 /** Map from facet names to state parameters with parameters for ignoring the facet's limit added. */ 067 Map<String, I_CmsSearchStateParameters> m_ignoreLimitFacetMap; 068 /** Map new queries to state parameters with the query replaced by the new query. */ 069 Map<String, I_CmsSearchStateParameters> m_newQueryMap; 070 /** Map from facet names to state parameters with parameters for ignoring the facet's limit removed. */ 071 Map<String, I_CmsSearchStateParameters> m_respectLimitFacetMap; 072 /** Map from facet names to a map from facet items to state parameters with the item unchecked. */ 073 Map<String, Map<String, I_CmsSearchStateParameters>> m_uncheckFacetMap; 074 /** Map from facet names to a map from facet items to state parameters with the item checked. */ 075 Map<String, Map<String, I_CmsSearchStateParameters>> m_checkFacetMap; 076 /** Map from additional parameter names to the values. */ 077 Map<String, Map<String, I_CmsSearchStateParameters>> m_setAdditionalParamsMap; 078 /** Map from additional parameter names to the values. */ 079 Map<String, I_CmsSearchStateParameters> m_unsetAdditionalParamsMap; 080 081 /** Constructor for a state parameters object. 082 * @param result The search result, according to which the parameters are manipulated. 083 * @param params The original parameter set. 084 */ 085 public CmsSearchStateParameters(final I_CmsSearchResultWrapper result, final Map<String, String[]> params) { 086 087 m_params = params; 088 m_result = result; 089 } 090 091 /** Converts a parameter map to the parameter string. 092 * @param parameters the parameter map. 093 * @return the parameter string. 094 */ 095 public static String paramMapToString(final Map<String, String[]> parameters) { 096 097 final StringBuffer result = new StringBuffer(); 098 for (final String key : parameters.keySet()) { 099 String[] values = parameters.get(key); 100 if (null == values) { 101 result.append(key).append('&'); 102 } else { 103 for (final String value : parameters.get(key)) { 104 result.append(key).append('=').append(CmsEncoder.encode(value)).append('&'); 105 } 106 } 107 } 108 // remove last '&' 109 if (result.length() > 0) { 110 result.setLength(result.length() - 1); 111 } 112 return result.toString(); 113 } 114 115 /** 116 * @see org.opencms.jsp.search.result.I_CmsSearchStateParameters#getAddIgnoreFacetLimit() 117 */ 118 public Map<String, I_CmsSearchStateParameters> getAddIgnoreFacetLimit() { 119 120 if (m_ignoreLimitFacetMap == null) { 121 m_ignoreLimitFacetMap = CmsCollectionsGenericWrapper.createLazyMap(new Transformer() { 122 123 @Override 124 public Object transform(final Object facet) { 125 126 final Map<String, String[]> parameters = new HashMap<String, String[]>(m_params); 127 String facetParamKey = null; 128 try { 129 facetParamKey = m_result.getController().getFieldFacets().getFieldFacetController().get( 130 facet).getConfig().getIgnoreMaxParamKey(); 131 } catch (Exception e) { 132 // Facet did not exist 133 LOG.warn(Messages.get().getBundle().key(Messages.LOG_FACET_NOT_CONFIGURED_1, facet), e); 134 } 135 if ((facetParamKey != null) && !parameters.containsKey(facetParamKey)) { 136 parameters.put(facetParamKey, null); 137 } 138 return new CmsSearchStateParameters(m_result, parameters); 139 } 140 }); 141 } 142 return m_ignoreLimitFacetMap; 143 } 144 145 /** 146 * @see org.opencms.jsp.search.result.I_CmsSearchStateParameters#getCheckFacetItem() 147 */ 148 @Override 149 public Map<String, Map<String, I_CmsSearchStateParameters>> getCheckFacetItem() { 150 151 if (m_checkFacetMap == null) { 152 m_checkFacetMap = CmsCollectionsGenericWrapper.createLazyMap(new Transformer() { 153 154 @Override 155 public Object transform(final Object facet) { 156 157 Map<String, I_CmsSearchStateParameters> m_checkEntries = CmsCollectionsGenericWrapper.createLazyMap( 158 new Transformer() { 159 160 @Override 161 public Object transform(final Object facetItem) { 162 163 final Map<String, String[]> parameters = new HashMap<String, String[]>(m_params); 164 String facetParamKey = getFacetParamKey((String)facet); 165 if (facetParamKey != null) { // otherwise the facet was not configured, thus no item can be added 166 if (parameters.containsKey(facetParamKey)) { 167 String[] values = parameters.get(facetParamKey); 168 if (!Arrays.asList(values).contains(facetItem)) { 169 String[] newValues = new String[Arrays.asList(values).size() + 1]; 170 for (int i = 0; i < (values.length); i++) { 171 newValues[i] = values[i]; 172 } 173 newValues[values.length] = (String)facetItem; 174 parameters.put(facetParamKey, newValues); 175 } 176 } else { 177 parameters.put(facetParamKey, new String[] {(String)facetItem}); 178 } 179 180 } 181 return new CmsSearchStateParameters(m_result, parameters); 182 } 183 }); 184 return m_checkEntries; 185 } 186 }); 187 } 188 return m_checkFacetMap; 189 190 } 191 192 /** 193 * @see org.opencms.jsp.search.result.I_CmsSearchStateParameters#getNewQuery() 194 */ 195 @Override 196 public Map<String, I_CmsSearchStateParameters> getNewQuery() { 197 198 if (m_newQueryMap == null) { 199 m_newQueryMap = CmsCollectionsGenericWrapper.createLazyMap(new Transformer() { 200 201 @Override 202 public Object transform(final Object queryString) { 203 204 final Map<String, String[]> parameters = new HashMap<String, String[]>(m_params); 205 String queryKey = m_result.getController().getCommon().getConfig().getQueryParam(); 206 if (parameters.containsKey(queryKey)) { 207 parameters.remove(queryKey); 208 } 209 parameters.put(queryKey, new String[] {(String)queryString}); 210 return new CmsSearchStateParameters(m_result, parameters); 211 } 212 }); 213 } 214 return m_newQueryMap; 215 } 216 217 /** 218 * @see org.opencms.jsp.search.result.I_CmsSearchStateParameters#getRemoveIgnoreFacetLimit() 219 */ 220 public Map<String, I_CmsSearchStateParameters> getRemoveIgnoreFacetLimit() { 221 222 if (m_ignoreLimitFacetMap == null) { 223 m_ignoreLimitFacetMap = CmsCollectionsGenericWrapper.createLazyMap(new Transformer() { 224 225 @Override 226 public Object transform(final Object facet) { 227 228 final Map<String, String[]> parameters = new HashMap<String, String[]>(m_params); 229 String facetParamKey = null; 230 try { 231 facetParamKey = m_result.getController().getFieldFacets().getFieldFacetController().get( 232 facet).getConfig().getIgnoreMaxParamKey(); 233 } catch (Exception e) { 234 // Facet did not exist 235 LOG.warn(Messages.get().getBundle().key(Messages.LOG_FACET_NOT_CONFIGURED_1, facet), e); 236 } 237 if ((facetParamKey != null) && parameters.containsKey(facetParamKey)) { 238 parameters.remove(facetParamKey); 239 } 240 return new CmsSearchStateParameters(m_result, parameters); 241 } 242 }); 243 } 244 return m_ignoreLimitFacetMap; 245 } 246 247 /** 248 * @see org.opencms.jsp.search.result.I_CmsSearchStateParameters#getResetAllFacetStates() 249 */ 250 @Override 251 public I_CmsSearchStateParameters getResetAllFacetStates() { 252 253 final Map<String, String[]> parameters = new HashMap<String, String[]>(m_params); 254 // Remove selected entries from field facets 255 Collection<I_CmsSearchControllerFacetField> fieldFacets = m_result.getController().getFieldFacets().getFieldFacetControllers(); 256 for (I_CmsSearchControllerFacetField facet : fieldFacets) { 257 String facetParamKey = facet.getConfig().getParamKey(); 258 if (parameters.containsKey(facetParamKey)) { 259 parameters.remove(facetParamKey); 260 } 261 } 262 // Remove selected entries from range facets 263 Collection<I_CmsSearchControllerFacetRange> rangeFacets = m_result.getController().getRangeFacets().getRangeFacetControllers(); 264 for (I_CmsSearchControllerFacetRange facet : rangeFacets) { 265 String facetParamKey = facet.getConfig().getParamKey(); 266 if (parameters.containsKey(facetParamKey)) { 267 parameters.remove(facetParamKey); 268 } 269 } 270 // Remove selected entries from the query facet 271 I_CmsSearchControllerFacetQuery facet = m_result.getController().getQueryFacet(); 272 if (null != facet) { 273 String facetParamKey = facet.getConfig().getParamKey(); 274 if (parameters.containsKey(facetParamKey)) { 275 parameters.remove(facetParamKey); 276 } 277 } 278 return new CmsSearchStateParameters(m_result, parameters); 279 } 280 281 /** 282 * @see org.opencms.jsp.search.result.I_CmsSearchStateParameters#getResetFacetState() 283 */ 284 @Override 285 public Map<String, I_CmsSearchStateParameters> getResetFacetState() { 286 287 if (m_resetFacetMap == null) { 288 m_resetFacetMap = CmsCollectionsGenericWrapper.createLazyMap(new Transformer() { 289 290 @Override 291 public Object transform(final Object facet) { 292 293 final Map<String, String[]> parameters = new HashMap<String, String[]>(m_params); 294 String facetParamKey = getFacetParamKey((String)facet); 295 if ((facetParamKey != null) && parameters.containsKey(facetParamKey)) { 296 parameters.remove(facetParamKey); 297 } 298 return new CmsSearchStateParameters(m_result, parameters); 299 } 300 }); 301 } 302 return m_resetFacetMap; 303 } 304 305 /** 306 * @see org.opencms.jsp.search.result.I_CmsSearchStateParameters#getSetAdditionalParam() 307 */ 308 public Map<String, Map<String, I_CmsSearchStateParameters>> getSetAdditionalParam() { 309 310 if (m_setAdditionalParamsMap == null) { 311 m_setAdditionalParamsMap = CmsCollectionsGenericWrapper.createLazyMap(new Transformer() { 312 313 @Override 314 public Object transform(final Object param) { 315 316 Map<String, I_CmsSearchStateParameters> m_additionalParamsMap = CmsCollectionsGenericWrapper.createLazyMap( 317 new Transformer() { 318 319 @Override 320 public Object transform(final Object value) { 321 322 final Map<String, String[]> parameters = new HashMap<String, String[]>(m_params); 323 boolean validParam = m_result.getController().getCommon().getConfig().getAdditionalParameters().keySet().contains( 324 param); 325 if (validParam) { 326 parameters.put((String)param, new String[] {(String)value}); 327 } 328 return new CmsSearchStateParameters(m_result, parameters); 329 } 330 }); 331 return m_additionalParamsMap; 332 } 333 }); 334 } 335 return m_setAdditionalParamsMap; 336 } 337 338 /** 339 * @see org.opencms.jsp.search.result.I_CmsSearchStateParameters#getSetPage() 340 */ 341 @Override 342 public Map<String, I_CmsSearchStateParameters> getSetPage() { 343 344 if (m_paginationMap == null) { 345 m_paginationMap = CmsCollectionsGenericWrapper.createLazyMap(new Transformer() { 346 347 @Override 348 public Object transform(final Object page) { 349 350 final Map<String, String[]> parameters = new HashMap<String, String[]>(m_params); 351 parameters.put( 352 m_result.getController().getPagination().getConfig().getPageParam(), 353 new String[] {(String)page}); 354 return new CmsSearchStateParameters(m_result, parameters); 355 } 356 }); 357 } 358 return m_paginationMap; 359 } 360 361 /** 362 * @see org.opencms.jsp.search.result.I_CmsSearchStateParameters#getSetSortOption() 363 */ 364 @Override 365 public Map<String, I_CmsSearchStateParameters> getSetSortOption() { 366 367 if (m_sortingMap == null) { 368 m_sortingMap = CmsCollectionsGenericWrapper.createLazyMap(new Transformer() { 369 370 @Override 371 public Object transform(final Object sortOption) { 372 373 final Map<String, String[]> parameters = new HashMap<String, String[]>(m_params); 374 m_result.getController().addParametersForCurrentState(parameters); 375 parameters.put( 376 m_result.getController().getSorting().getConfig().getSortParam(), 377 new String[] {(String)sortOption}); 378 return new CmsSearchStateParameters(m_result, parameters); 379 } 380 }); 381 } 382 return m_sortingMap; 383 } 384 385 /** 386 * @see org.opencms.jsp.search.result.I_CmsSearchStateParameters#getUncheckFacetItem() 387 */ 388 @Override 389 public Map<String, Map<String, I_CmsSearchStateParameters>> getUncheckFacetItem() { 390 391 if (m_uncheckFacetMap == null) { 392 m_uncheckFacetMap = CmsCollectionsGenericWrapper.createLazyMap(new Transformer() { 393 394 @Override 395 public Object transform(final Object facet) { 396 397 Map<String, I_CmsSearchStateParameters> m_uncheckEntries = CmsCollectionsGenericWrapper.createLazyMap( 398 new Transformer() { 399 400 @Override 401 public Object transform(final Object facetItem) { 402 403 final Map<String, String[]> parameters = new HashMap<String, String[]>(m_params); 404 String facetParamKey = getFacetParamKey((String)facet); 405 if ((facetParamKey != null) && parameters.containsKey(facetParamKey)) { 406 String[] values = parameters.get(facetParamKey); 407 List<String> valueList = Arrays.asList(values); 408 String item = (String)facetItem; 409 if (valueList.contains(facetItem)) { 410 String[] newValues = new String[valueList.size() - 1]; 411 int i = 0; 412 for (String value : valueList) { 413 if (!value.equals(item)) { 414 newValues[i++] = value; 415 } 416 } 417 parameters.put(facetParamKey, newValues); 418 } 419 } 420 return new CmsSearchStateParameters(m_result, parameters); 421 } 422 }); 423 return m_uncheckEntries; 424 } 425 }); 426 } 427 return m_uncheckFacetMap; 428 } 429 430 /** 431 * @see org.opencms.jsp.search.result.I_CmsSearchStateParameters#getUnsetAdditionalParam() 432 */ 433 public Map<String, I_CmsSearchStateParameters> getUnsetAdditionalParam() { 434 435 if (m_unsetAdditionalParamsMap == null) { 436 m_unsetAdditionalParamsMap = CmsCollectionsGenericWrapper.createLazyMap(new Transformer() { 437 438 @Override 439 public Object transform(final Object param) { 440 441 final Map<String, String[]> parameters = new HashMap<String, String[]>(m_params); 442 boolean validParam = m_result.getController().getCommon().getConfig().getAdditionalParameters().keySet().contains( 443 param); 444 if (validParam && parameters.containsKey(param)) { 445 parameters.remove(param); 446 } 447 return new CmsSearchStateParameters(m_result, parameters); 448 } 449 }); 450 } 451 return m_unsetAdditionalParamsMap; 452 } 453 454 /** 455 * @see java.lang.Object#toString() 456 */ 457 @Override 458 public String toString() { 459 460 return paramMapToString(m_params); 461 } 462 463 /** 464 * Returns the parameter key of the facet with the given name. 465 * @param facet the facet's name. 466 * @return the parameter key for the facet. 467 */ 468 String getFacetParamKey(String facet) { 469 470 I_CmsSearchControllerFacetField fieldFacet = m_result.getController().getFieldFacets().getFieldFacetController().get( 471 facet); 472 if (fieldFacet != null) { 473 return fieldFacet.getConfig().getParamKey(); 474 } 475 I_CmsSearchControllerFacetRange rangeFacet = m_result.getController().getRangeFacets().getRangeFacetController().get( 476 facet); 477 if (rangeFacet != null) { 478 return rangeFacet.getConfig().getParamKey(); 479 } 480 I_CmsSearchControllerFacetQuery queryFacet = m_result.getController().getQueryFacet(); 481 if ((queryFacet != null) && queryFacet.getConfig().getName().equals(facet)) { 482 return queryFacet.getConfig().getParamKey(); 483 } 484 485 // Facet did not exist 486 LOG.warn(Messages.get().getBundle().key(Messages.LOG_FACET_NOT_CONFIGURED_1, facet), new Throwable()); 487 488 return null; 489 } 490 491}