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