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.controller; 029 030import org.opencms.file.CmsObject; 031import org.opencms.i18n.CmsEncoder; 032import org.opencms.i18n.CmsLocaleManager; 033import org.opencms.jsp.search.config.I_CmsSearchConfigurationCommon; 034import org.opencms.jsp.search.state.CmsSearchStateCommon; 035import org.opencms.jsp.search.state.I_CmsSearchStateCommon; 036import org.opencms.search.solr.CmsSolrQuery; 037import org.opencms.util.CmsRequestUtil; 038 039import java.util.Arrays; 040import java.util.HashMap; 041import java.util.Map; 042import java.util.Map.Entry; 043import java.util.TimeZone; 044import java.util.regex.Pattern; 045 046import org.apache.solr.client.solrj.util.ClientUtils; 047import org.apache.solr.common.params.CommonParams; 048 049/** Search controller for the common search options. */ 050public class CmsSearchControllerCommon implements I_CmsSearchControllerCommon { 051 052 /** Value macro. */ 053 private static final String MACRO_VALUE = "value"; 054 /** Site root macro. */ 055 private static final String MACRO_SITE_ROOT = "site_root"; 056 /** Locale macro. */ 057 private static final String MACRO_LOCALE = "locale"; 058 /** Query macro. */ 059 private static final String MACRO_QUERY = "query"; 060 /** Configuration of common search options. */ 061 private final I_CmsSearchConfigurationCommon m_config; 062 /** State of the common search options. */ 063 private final I_CmsSearchStateCommon m_state; 064 065 /** Constructor taking the managed configuration. 066 * @param config The configuration to manage by the controller. 067 */ 068 public CmsSearchControllerCommon(final I_CmsSearchConfigurationCommon config) { 069 070 m_config = config; 071 m_state = new CmsSearchStateCommon(); 072 } 073 074 /** 075 * @see org.opencms.jsp.search.controller.I_CmsSearchController#addParametersForCurrentState(java.util.Map) 076 */ 077 @Override 078 public void addParametersForCurrentState(final Map<String, String[]> parameters) { 079 080 if (!m_state.getQuery().isEmpty()) { 081 parameters.put(m_config.getQueryParam(), new String[] {m_state.getQuery()}); 082 } 083 parameters.put(m_config.getReloadedParam(), null); 084 for (Entry<String, String> e : m_state.getAdditionalParameters().entrySet()) { 085 parameters.put(e.getKey(), new String[] {e.getValue()}); 086 } 087 } 088 089 /** 090 * @see org.opencms.jsp.search.controller.I_CmsSearchController#addQueryParts(CmsSolrQuery, CmsObject) 091 */ 092 @Override 093 public void addQueryParts(CmsSolrQuery query, CmsObject cms) { 094 095 String queryString = m_state.getQuery(); 096 if (!m_config.getIgnoreQueryParam()) { 097 if (m_config.getEscapeQueryChars()) { 098 queryString = ClientUtils.escapeQueryChars(queryString); 099 } 100 if (queryString.isEmpty() && m_config.getSearchForEmptyQueryParam()) { 101 queryString = "*"; 102 } 103 String modifiedQuery = m_config.getModifiedQuery(queryString); 104 if (modifiedQuery.startsWith("{!")) { 105 modifiedQuery = "{!tag=q " + modifiedQuery.substring(2); 106 } else { 107 modifiedQuery = "{!tag=q}" + modifiedQuery; 108 } 109 query.set("q", modifiedQuery); 110 } 111 112 if (m_config.getSolrIndex() != null) { 113 query.set("index", m_config.getSolrIndex()); 114 } 115 if (m_config.getSolrCore() != null) { 116 query.set("core", m_config.getSolrCore()); 117 } 118 119 if (!m_config.getExtraSolrParams().isEmpty()) { 120 String currentSiteRoot = null == cms ? null : cms.getRequestContext().getSiteRoot(); 121 if ((null != currentSiteRoot) && !currentSiteRoot.endsWith("/")) { 122 currentSiteRoot = currentSiteRoot + "/"; 123 } 124 String currentLocale = (null == cms 125 ? CmsLocaleManager.getDefaultLocale() 126 : cms.getRequestContext().getLocale()).toString(); 127 String extraParams = m_config.getExtraSolrParams(); 128 extraParams = resolveMacro(extraParams, MACRO_SITE_ROOT, currentSiteRoot); 129 extraParams = resolveMacro(extraParams, MACRO_LOCALE, currentLocale); 130 extraParams = resolveMacro(extraParams, MACRO_QUERY, queryString); 131 Map<String, String[]> extraParamsMap = CmsRequestUtil.createParameterMap(extraParams, true, null); 132 for (String key : extraParamsMap.keySet()) { 133 for (String value : Arrays.asList(extraParamsMap.get(key))) { 134 if (SET_VARIABLES.contains(key)) { 135 if (key.equals(CommonParams.FL)) { 136 query.setReturnFields(value); 137 } else { 138 query.set(key, value); 139 } 140 } else { 141 query.add(key, value); 142 } 143 } 144 } 145 } 146 for (String additionalParam : m_state.getAdditionalParameters().keySet()) { 147 String solrValue = m_config.getAdditionalParameters().get(additionalParam); 148 if (null != solrValue) { 149 String additionalParamString = resolveMacro( 150 solrValue, 151 MACRO_VALUE, 152 CmsEncoder.encode(m_state.getAdditionalParameters().get(additionalParam), null)); 153 Map<String, String[]> extraParamsMap = CmsRequestUtil.createParameterMap( 154 additionalParamString, 155 true, 156 null); 157 for (String key : extraParamsMap.keySet()) { 158 for (String value : Arrays.asList(extraParamsMap.get(key))) { 159 if (SET_VARIABLES.contains(key)) { 160 query.set(key, value); 161 } else { 162 query.add(key, value); 163 } 164 } 165 } 166 } 167 } 168 // Add timezone query parameter to allow for correct date/time handling if not already present. 169 if (!query.getMap().keySet().contains("TZ")) { 170 query.add("TZ", TimeZone.getDefault().getID()); 171 } 172 } 173 174 /** 175 * @see org.opencms.jsp.search.controller.I_CmsSearchControllerCommon#getConfig() 176 */ 177 @Override 178 public I_CmsSearchConfigurationCommon getConfig() { 179 180 return m_config; 181 } 182 183 /** 184 * @see org.opencms.jsp.search.controller.I_CmsSearchControllerCommon#getState() 185 */ 186 @Override 187 public I_CmsSearchStateCommon getState() { 188 189 return m_state; 190 } 191 192 /** 193 * @see org.opencms.jsp.search.controller.I_CmsSearchController#updateForQueryChange() 194 */ 195 @Override 196 public void updateForQueryChange() { 197 198 // Nothing to do 199 200 } 201 202 /** 203 * @see org.opencms.jsp.search.controller.I_CmsSearchController#updateFromRequestParameters(java.util.Map, boolean) 204 */ 205 @Override 206 public void updateFromRequestParameters(final Map<String, String[]> parameters, boolean isReloaded) { 207 208 m_state.setQuery(""); 209 210 if (parameters.containsKey(m_config.getQueryParam())) { 211 final String[] queryStrings = parameters.get(m_config.getQueryParam()); 212 if (queryStrings.length > 0) { 213 m_state.setQuery(queryStrings[0]); 214 } 215 } 216 if (parameters.containsKey(m_config.getLastQueryParam())) { 217 final String[] queryStrings = parameters.get(m_config.getLastQueryParam()); 218 if (queryStrings.length > 0) { 219 m_state.setLastQuery(queryStrings[0]); 220 } 221 } 222 // Set state for additional query parameters 223 Map<String, String> additionalParameters = new HashMap<String, String>( 224 m_config.getAdditionalParameters().size()); 225 for (String key : m_config.getAdditionalParameters().keySet()) { 226 if (parameters.containsKey(key) 227 && ((parameters.get(key).length > 0) && (parameters.get(key)[0].length() > 0))) { 228 additionalParameters.put(key, parameters.get(key)[0]); 229 } 230 } 231 m_state.setAdditionalParameters(additionalParameters); 232 } 233 234 /** 235 * Replaces the macro with the value, unless the value is <code>null</code>, then the macro is kept. 236 * 237 * @param string The String where the macros should be replaced. 238 * @param value The value used for the replacement. 239 * @param macroName The name of the macro to resolve. 240 * 241 * @return The original String with %(value) macros replaced. 242 */ 243 private String resolveMacro(final String string, final String macroName, final String value) { 244 245 return null != value ? string.replaceAll("\\%\\(" + Pattern.quote(macroName) + "\\)", value) : string; 246 } 247}