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.config.parser; 029 030import org.opencms.file.CmsObject; 031import org.opencms.jsp.search.config.CmsSearchConfigurationCommon; 032import org.opencms.jsp.search.config.I_CmsSearchConfiguration; 033import org.opencms.jsp.search.config.I_CmsSearchConfigurationCommon; 034import org.opencms.jsp.search.config.I_CmsSearchConfigurationDidYouMean; 035import org.opencms.jsp.search.config.I_CmsSearchConfigurationFacetField; 036import org.opencms.jsp.search.config.I_CmsSearchConfigurationFacetQuery; 037import org.opencms.jsp.search.config.I_CmsSearchConfigurationFacetRange; 038import org.opencms.jsp.search.config.I_CmsSearchConfigurationGeoFilter; 039import org.opencms.jsp.search.config.I_CmsSearchConfigurationHighlighting; 040import org.opencms.jsp.search.config.I_CmsSearchConfigurationPagination; 041import org.opencms.jsp.search.config.I_CmsSearchConfigurationSorting; 042import org.opencms.main.CmsLog; 043import org.opencms.main.OpenCms; 044import org.opencms.search.solr.CmsSolrIndex; 045import org.opencms.util.CmsPair; 046 047import java.util.Collections; 048import java.util.Map; 049 050import org.apache.commons.logging.Log; 051 052/** Search configuration parser reading a configuration containing a plain Solr query. 053 * Only fl might be added additionally. */ 054public class CmsPlainQuerySearchConfigurationParser implements I_CmsSearchConfigurationParser { 055 056 /** Logger for the class. */ 057 protected static final Log LOG = CmsLog.getLog(CmsPlainQuerySearchConfigurationParser.class); 058 059 /** The default return fields. */ 060 private static final String DEFAULT_FL = "id,path"; 061 062 /** The whole query string. */ 063 protected String m_queryString; 064 065 /** The optional base configuration that should be changed by the JSON configuration. */ 066 private I_CmsSearchConfiguration m_baseConfig; 067 068 /** Constructor taking the JSON as String. 069 * @param query The query that is passed to Solr. 070 */ 071 public CmsPlainQuerySearchConfigurationParser(String query) { 072 073 this(query, null); 074 } 075 076 /** Constructor taking the JSON as String. 077 * @param query The query that is passed to Solr (additional Solr params). 078 * @param baseConfig A base configuration that is adjusted by the JSON configuration string. 079 */ 080 public CmsPlainQuerySearchConfigurationParser(String query, I_CmsSearchConfiguration baseConfig) { 081 082 if ((null != query) && !(query.startsWith("fl=") || query.contains("&fl="))) { 083 query = query + "&fl=" + DEFAULT_FL; 084 } 085 m_queryString = query; 086 m_baseConfig = baseConfig; 087 088 } 089 090 /** 091 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parseCommon(CmsObject) 092 */ 093 public I_CmsSearchConfigurationCommon parseCommon(CmsObject cms) { 094 095 String queryString = m_queryString; 096 CmsPair<String, String> idxExtract = extractParam(queryString, "index"); 097 CmsPair<String, String> coreExtract = extractParam(idxExtract.getFirst(), "core"); 098 CmsPair<String, String> maxResultsExtract = extractParam(coreExtract.getFirst(), "maxresults"); 099 String resString = maxResultsExtract.getSecond(); 100 String indexName = idxExtract.getSecond(); 101 if (null != indexName) { 102 indexName = indexName.trim(); 103 } 104 if (null == indexName) { 105 indexName = cms.getRequestContext().getCurrentProject().isOnlineProject() 106 ? CmsSolrIndex.DEFAULT_INDEX_NAME_ONLINE 107 : CmsSolrIndex.DEFAULT_INDEX_NAME_OFFLINE; 108 } 109 Integer maxResNum = null; 110 if (null != resString) { 111 try { 112 maxResNum = Integer.valueOf(resString); 113 } catch (NumberFormatException e) { 114 if (LOG.isErrorEnabled()) { 115 LOG.error("Ignoring param \"maxresults=" + resString + "\" since its not a valid integer.", e); 116 } 117 } 118 } 119 if (null == maxResNum) { 120 try { 121 CmsSolrIndex idx = OpenCms.getSearchManager().getIndexSolr(indexName); 122 if (null != idx) { 123 maxResNum = Integer.valueOf(idx.getMaxProcessedResults()); 124 } else { 125 maxResNum = Integer.valueOf(CmsSolrIndex.MAX_RESULTS_UNLIMITED); 126 } 127 } catch (Throwable t) { 128 // This is ok, it's allowed to have an external other index here. 129 LOG.debug( 130 "Parsing plain search configuration for none-CmsSolrIndex " 131 + indexName 132 + ". Setting max processed results to unlimited."); 133 maxResNum = Integer.valueOf(CmsSolrIndex.MAX_RESULTS_UNLIMITED); 134 } 135 } 136 137 return new CmsSearchConfigurationCommon( 138 null, 139 null, 140 null, 141 null, 142 Boolean.TRUE, 143 Boolean.TRUE, 144 null, 145 indexName, 146 coreExtract.getSecond(), 147 maxResultsExtract.getFirst(), 148 null, 149 null, 150 null, 151 maxResNum.intValue()); 152 } 153 154 /** 155 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parseDidYouMean() 156 */ 157 public I_CmsSearchConfigurationDidYouMean parseDidYouMean() { 158 159 return null != m_baseConfig ? m_baseConfig.getDidYouMeanConfig() : null; 160 } 161 162 /** 163 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parseFieldFacets() 164 */ 165 public Map<String, I_CmsSearchConfigurationFacetField> parseFieldFacets() { 166 167 return null != m_baseConfig ? m_baseConfig.getFieldFacetConfigs() : Collections.emptyMap(); 168 } 169 170 /** 171 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parseGeoFilter() 172 */ 173 @Override 174 public I_CmsSearchConfigurationGeoFilter parseGeoFilter() { 175 176 return null; 177 } 178 179 /** 180 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parseHighlighter() 181 */ 182 public I_CmsSearchConfigurationHighlighting parseHighlighter() { 183 184 return null != m_baseConfig ? m_baseConfig.getHighlighterConfig() : null; 185 } 186 187 /** 188 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parsePagination() 189 */ 190 public I_CmsSearchConfigurationPagination parsePagination() { 191 192 return null != m_baseConfig ? m_baseConfig.getPaginationConfig() : null; 193 } 194 195 /** 196 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parseQueryFacet() 197 */ 198 public I_CmsSearchConfigurationFacetQuery parseQueryFacet() { 199 200 return null != m_baseConfig ? m_baseConfig.getQueryFacetConfig() : null; 201 } 202 203 /** 204 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parseRangeFacets() 205 */ 206 public Map<String, I_CmsSearchConfigurationFacetRange> parseRangeFacets() { 207 208 return null != m_baseConfig ? m_baseConfig.getRangeFacetConfigs() : Collections.emptyMap(); 209 } 210 211 /** 212 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parseSorting() 213 */ 214 public I_CmsSearchConfigurationSorting parseSorting() { 215 216 return null != m_baseConfig ? m_baseConfig.getSortConfig() : null; 217 } 218 219 /** 220 * Extracts the value of a parameter from a query string. 221 * 222 * For example, extractParam("a=foo&b=bar", "a") will return CmsPair("b=bar", "foo"). 223 * @param params the parameter string. 224 * @param paramKey the key of the parameter to extract the value for. 225 * @return a pair of "params without the extracted parameter" and the value of the extracted parameter. 226 */ 227 CmsPair<String, String> extractParam(String params, String paramKey) { 228 229 String extract = null; 230 int beginIdx = params.indexOf(paramKey + "="); 231 if (beginIdx >= 0) { 232 String sub = params.substring(beginIdx + paramKey.length() + 1); 233 int endIdx = sub.indexOf("&"); 234 if (endIdx >= 0) { 235 extract = sub.substring(0, endIdx); 236 params = params.substring(0, beginIdx) + sub.substring(endIdx + 1); 237 } else { 238 extract = sub; 239 params = beginIdx > 0 ? params.substring(0, beginIdx - 1) : ""; // cut trailing '&' 240 } 241 } 242 return new CmsPair<>(params, extract); 243 244 } 245}