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 Map<String, String[]> extraParamsMap = CmsRequestUtil.createParameterMap( 128 m_config.getExtraSolrParams(), 129 true, 130 null); 131 for (String key : extraParamsMap.keySet()) { 132 for (String value : Arrays.asList(extraParamsMap.get(key))) { 133 value = resolveMacro(value, MACRO_SITE_ROOT, currentSiteRoot); 134 value = resolveMacro(value, MACRO_LOCALE, currentLocale); 135 value = resolveMacro(value, MACRO_QUERY, queryString); 136 if (SET_VARIABLES.contains(key)) { 137 if (key.equals(CommonParams.FL)) { 138 query.setReturnFields(value); 139 } else { 140 query.set(key, value); 141 } 142 } else { 143 query.add(key, value); 144 } 145 } 146 } 147 } 148 for (String additionalParam : m_state.getAdditionalParameters().keySet()) { 149 String solrValue = m_config.getAdditionalParameters().get(additionalParam); 150 if (null != solrValue) { 151 String additionalParamString = resolveMacro( 152 solrValue, 153 MACRO_VALUE, 154 CmsEncoder.encode(m_state.getAdditionalParameters().get(additionalParam), null)); 155 Map<String, String[]> extraParamsMap = CmsRequestUtil.createParameterMap( 156 additionalParamString, 157 true, 158 null); 159 for (String key : extraParamsMap.keySet()) { 160 for (String value : Arrays.asList(extraParamsMap.get(key))) { 161 if (SET_VARIABLES.contains(key)) { 162 query.set(key, value); 163 } else { 164 query.add(key, value); 165 } 166 } 167 } 168 } 169 } 170 // Add timezone query parameter to allow for correct date/time handling if not already present. 171 if (!query.getMap().keySet().contains("TZ")) { 172 query.add("TZ", TimeZone.getDefault().getID()); 173 } 174 } 175 176 /** 177 * @see org.opencms.jsp.search.controller.I_CmsSearchControllerCommon#getConfig() 178 */ 179 @Override 180 public I_CmsSearchConfigurationCommon getConfig() { 181 182 return m_config; 183 } 184 185 /** 186 * @see org.opencms.jsp.search.controller.I_CmsSearchControllerCommon#getState() 187 */ 188 @Override 189 public I_CmsSearchStateCommon getState() { 190 191 return m_state; 192 } 193 194 /** 195 * @see org.opencms.jsp.search.controller.I_CmsSearchController#updateForQueryChange() 196 */ 197 @Override 198 public void updateForQueryChange() { 199 200 // Nothing to do 201 202 } 203 204 /** 205 * @see org.opencms.jsp.search.controller.I_CmsSearchController#updateFromRequestParameters(java.util.Map, boolean) 206 */ 207 @Override 208 public void updateFromRequestParameters(final Map<String, String[]> parameters, boolean isReloaded) { 209 210 m_state.setQuery(""); 211 212 if (parameters.containsKey(m_config.getQueryParam())) { 213 final String[] queryStrings = parameters.get(m_config.getQueryParam()); 214 if (queryStrings.length > 0) { 215 m_state.setQuery(queryStrings[0]); 216 } 217 } 218 if (parameters.containsKey(m_config.getLastQueryParam())) { 219 final String[] queryStrings = parameters.get(m_config.getLastQueryParam()); 220 if (queryStrings.length > 0) { 221 m_state.setLastQuery(queryStrings[0]); 222 } 223 } 224 // Set state for additional query parameters 225 Map<String, String> additionalParameters = new HashMap<String, String>( 226 m_config.getAdditionalParameters().size()); 227 for (String key : m_config.getAdditionalParameters().keySet()) { 228 if (parameters.containsKey(key) 229 && ((parameters.get(key).length > 0) && (parameters.get(key)[0].length() > 0))) { 230 additionalParameters.put(key, parameters.get(key)[0]); 231 } 232 } 233 m_state.setAdditionalParameters(additionalParameters); 234 } 235 236 /** 237 * Replaces the macro with the value, unless the value is <code>null</code>, then the macro is kept. 238 * 239 * @param string The String where the macros should be replaced. 240 * @param value The value used for the replacement. 241 * @param macroName The name of the macro to resolve. 242 * 243 * @return The original String with %(value) macros replaced. 244 */ 245 private String resolveMacro(final String string, final String macroName, final String value) { 246 247 return null != value ? string.replaceAll("\\%\\(" + Pattern.quote(macroName) + "\\)", value) : string; 248 } 249}