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