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.json.JSONArray; 032import org.opencms.json.JSONException; 033import org.opencms.json.JSONObject; 034import org.opencms.jsp.search.config.CmsSearchConfigurationCommon; 035import org.opencms.jsp.search.config.CmsSearchConfigurationDidYouMean; 036import org.opencms.jsp.search.config.CmsSearchConfigurationFacetField; 037import org.opencms.jsp.search.config.CmsSearchConfigurationFacetQuery; 038import org.opencms.jsp.search.config.CmsSearchConfigurationFacetQuery.CmsFacetQueryItem; 039import org.opencms.jsp.search.config.CmsSearchConfigurationFacetRange; 040import org.opencms.jsp.search.config.CmsSearchConfigurationGeoFilter; 041import org.opencms.jsp.search.config.CmsSearchConfigurationHighlighting; 042import org.opencms.jsp.search.config.CmsSearchConfigurationPagination; 043import org.opencms.jsp.search.config.CmsSearchConfigurationSortOption; 044import org.opencms.jsp.search.config.CmsSearchConfigurationSorting; 045import org.opencms.jsp.search.config.I_CmsSearchConfiguration; 046import org.opencms.jsp.search.config.I_CmsSearchConfigurationCommon; 047import org.opencms.jsp.search.config.I_CmsSearchConfigurationDidYouMean; 048import org.opencms.jsp.search.config.I_CmsSearchConfigurationFacet; 049import org.opencms.jsp.search.config.I_CmsSearchConfigurationFacetField; 050import org.opencms.jsp.search.config.I_CmsSearchConfigurationFacetQuery; 051import org.opencms.jsp.search.config.I_CmsSearchConfigurationFacetQuery.I_CmsFacetQueryItem; 052import org.opencms.jsp.search.config.I_CmsSearchConfigurationFacetRange; 053import org.opencms.jsp.search.config.I_CmsSearchConfigurationGeoFilter; 054import org.opencms.jsp.search.config.I_CmsSearchConfigurationHighlighting; 055import org.opencms.jsp.search.config.I_CmsSearchConfigurationPagination; 056import org.opencms.jsp.search.config.I_CmsSearchConfigurationSortOption; 057import org.opencms.jsp.search.config.I_CmsSearchConfigurationSorting; 058import org.opencms.main.CmsLog; 059import org.opencms.main.OpenCms; 060import org.opencms.search.solr.CmsSolrIndex; 061 062import java.util.ArrayList; 063import java.util.Collections; 064import java.util.HashMap; 065import java.util.Iterator; 066import java.util.LinkedHashMap; 067import java.util.LinkedList; 068import java.util.List; 069import java.util.Map; 070import java.util.Objects; 071 072import org.apache.commons.logging.Log; 073 074/** Search configuration parser reading JSON. */ 075public class CmsJSONSearchConfigurationParser implements I_CmsSearchConfigurationParser { 076 077 /** Logger for the class. */ 078 protected static final Log LOG = CmsLog.getLog(CmsJSONSearchConfigurationParser.class); 079 080 /** The keys that can be used in the JSON object */ 081 /** JSON keys for common options. */ 082 /** A JSON key. */ 083 public static final String JSON_KEY_QUERYPARAM = "queryparam"; 084 /** A JSON key. */ 085 public static final String JSON_KEY_LAST_QUERYPARAM = "lastqueryparam"; 086 /** A JSON key. */ 087 public static final String JSON_KEY_ESCAPE_QUERY_CHARACTERS = "escapequerychars"; 088 /** A JSON key. */ 089 public static final String JSON_KEY_RELOADED_PARAM = "reloadedparam"; 090 /** A JSON key. */ 091 public static final String JSON_KEY_SEARCH_FOR_EMPTY_QUERY = "searchforemptyquery"; 092 /** A JSON key. */ 093 public static final String JSON_KEY_IGNORE_QUERY = "ignorequery"; 094 /** A JSON key. */ 095 public static final String JSON_KEY_IGNORE_RELEASE_DATE = "ignoreReleaseDate"; 096 /** A JSON key. */ 097 public static final String JSON_KEY_MAX_RETURNED_RESULTS = "maxReturnedResults"; 098 /** A JSON key. */ 099 public static final String JSON_KEY_IGNORE_EXPIRATION_DATE = "ignoreExpirationDate"; 100 /** A JSON key. */ 101 public static final String JSON_KEY_QUERY_MODIFIER = "querymodifier"; 102 /** A JSON key. */ 103 public static final String JSON_KEY_PAGEPARAM = "pageparam"; 104 /** A JSON key. */ 105 public static final String JSON_KEY_INDEX = "index"; 106 /** A JSON key. */ 107 public static final String JSON_KEY_CORE = "core"; 108 /** A JSON key. */ 109 public static final String JSON_KEY_EXTRASOLRPARAMS = "extrasolrparams"; 110 /** A JSON key. */ 111 public static final String JSON_KEY_ADDITIONAL_PARAMETERS = "additionalrequestparams"; 112 /** A JSON key. */ 113 public static final String JSON_KEY_ADDITIONAL_PARAMETERS_PARAM = "param"; 114 /** A JSON key. */ 115 public static final String JSON_KEY_ADDITIONAL_PARAMETERS_SOLRQUERY = "solrquery"; 116 /** A JSON key. */ 117 public static final String JSON_KEY_PAGESIZE = "pagesize"; 118 /** A JSON key. */ 119 public static final String JSON_KEY_PAGENAVLENGTH = "pagenavlength"; 120 /** JSON keys for facet configuration. */ 121 /** The JSON key for the sub-node with all field facet configurations. */ 122 public static final String JSON_KEY_FIELD_FACETS = "fieldfacets"; 123 /** The JSON key for the sub-node with all field facet configurations. */ 124 public static final String JSON_KEY_RANGE_FACETS = "rangefacets"; 125 /** The JSON key for the sub-node with the query facet configuration. */ 126 public static final String JSON_KEY_QUERY_FACET = "queryfacet"; 127 /** JSON keys for a single facet. */ 128 /** A JSON key. */ 129 public static final String JSON_KEY_FACET_LIMIT = "limit"; 130 /** A JSON key. */ 131 public static final String JSON_KEY_FACET_MINCOUNT = "mincount"; 132 /** A JSON key. */ 133 public static final String JSON_KEY_FACET_LABEL = "label"; 134 /** A JSON key. */ 135 public static final String JSON_KEY_FACET_FIELD = "field"; 136 /** A JSON key. */ 137 public static final String JSON_KEY_FACET_NAME = "name"; 138 /** A JSON key. */ 139 public static final String JSON_KEY_FACET_PREFIX = "prefix"; 140 /** A JSON key. */ 141 public static final String JSON_KEY_FACET_ORDER = "order"; 142 /** A JSON key. */ 143 public static final String JSON_KEY_FACET_FILTERQUERYMODIFIER = "filterquerymodifier"; 144 /** A JSON key. */ 145 public static final String JSON_KEY_FACET_ISANDFACET = "isAndFacet"; 146 /** A JSON key. */ 147 public static final String JSON_KEY_FACET_IGNOREALLFACETFILTERS = "ignoreAllFacetFilters"; 148 /** A JSON key. */ 149 public static final String JSON_KEY_FACET_EXCLUDETAGS = "excludeTags"; 150 /** A JSON key. */ 151 public static final String JSON_KEY_FACET_PRESELECTION = "preselection"; 152 /** A JSON key. */ 153 public static final String JSON_KEY_RANGE_FACET_RANGE = "range"; 154 /** A JSON key. */ 155 public static final String JSON_KEY_RANGE_FACET_START = "start"; 156 /** A JSON key. */ 157 public static final String JSON_KEY_RANGE_FACET_END = "end"; 158 /** A JSON key. */ 159 public static final String JSON_KEY_RANGE_FACET_GAP = "gap"; 160 /** A JSON key. */ 161 public static final String JSON_KEY_RANGE_FACET_OTHER = "other"; 162 /** A JSON key. */ 163 public static final String JSON_KEY_RANGE_FACET_HARDEND = "hardend"; 164 /** A JSON key. */ 165 public static final String JSON_KEY_RANGE_FACET_METHOD = "method"; 166 /** A JSON key. */ 167 public static final String JSON_KEY_QUERY_FACET_QUERY = "queryitems"; 168 /** A JSON key. */ 169 public static final String JSON_KEY_QUERY_FACET_QUERY_QUERY = "query"; 170 /** A JSON key. */ 171 public static final String JSON_KEY_QUERY_FACET_QUERY_LABEL = "label"; 172 173 /** JSON keys for sort options. */ 174 /** A JSON key. */ 175 public static final String JSON_KEY_SORTPARAM = "sortby"; 176 /** The JSON key for the default sort option, should hold the name paramvalue for the default option. */ 177 public static final String JSON_KEY_DEFAULT_SORT_OPTION = "defaultSortOption"; 178 /** The JSON key for the sub-node with all search option configurations. */ 179 public static final String JSON_KEY_SORTOPTIONS = "sortoptions"; 180 /** JSON keys for a single search option. */ 181 /** A JSON key. */ 182 public static final String JSON_KEY_SORTOPTION_LABEL = "label"; 183 /** A JSON key. */ 184 public static final String JSON_KEY_SORTOPTION_PARAMVALUE = "paramvalue"; 185 /** A JSON key. */ 186 public static final String JSON_KEY_SORTOPTION_SOLRVALUE = "solrvalue"; 187 /** JSON keys for the highlighting configuration. */ 188 /** The JSON key for the subnode of all highlighting configuration. */ 189 public static final String JSON_KEY_HIGHLIGHTER = "highlighter"; 190 /** A JSON key. */ 191 public static final String JSON_KEY_HIGHLIGHTER_FIELD = "field"; 192 /** A JSON key. */ 193 public static final String JSON_KEY_HIGHLIGHTER_SNIPPETS = "snippets"; 194 /** A JSON key. */ 195 public static final String JSON_KEY_HIGHLIGHTER_FRAGSIZE = "fragsize"; 196 /** A JSON key. */ 197 public static final String JSON_KEY_HIGHLIGHTER_ALTERNATE_FIELD = "alternateField"; 198 /** A JSON key. */ 199 public static final String JSON_KEY_HIGHLIGHTER_MAX_LENGTH_ALTERNATE_FIELD = "maxAlternateFieldLength"; 200 /** A JSON key. */ 201 public static final String JSON_KEY_HIGHLIGHTER_SIMPLE_PRE = "simple.pre"; 202 /** A JSON key. */ 203 public static final String JSON_KEY_HIGHLIGHTER_SIMPLE_POST = "simple.post"; 204 /** A JSON key. */ 205 public static final String JSON_KEY_HIGHLIGHTER_FORMATTER = "formatter"; 206 /** A JSON key. */ 207 public static final String JSON_KEY_HIGHLIGHTER_FRAGMENTER = "fragmenter"; 208 /** A JSON key. */ 209 public static final String JSON_KEY_HIGHLIGHTER_FASTVECTORHIGHLIGHTING = "useFastVectorHighlighting"; 210 211 /** JSON keys for "Did you mean ...?" */ 212 /** A JSON key. */ 213 public static final String JSON_KEY_DIDYOUMEAN = "didYouMean"; 214 /** The JSON key for the subnode of all "Did you mean?" configuration. */ 215 /** A JSON key. */ 216 public static final String JSON_KEY_DIDYOUMEAN_QUERYPARAM = "didYouMeanQueryParam"; 217 /** A JSON key. */ 218 public static final String JSON_KEY_DIDYOUMEAN_COLLATE = "didYouMeanCollate"; 219 /** A JSON key. */ 220 public static final String JSON_KEY_DIDYOUMEAN_COUNT = "didYouMeanCount"; 221 222 /** JSON keys for the Geo filter. */ 223 public static final String JSON_KEY_GEO_FILTER = "geofilter"; 224 /** A JSON key. */ 225 public static final String JSON_KEY_GEO_FILTER_COORDINATES = "coordinates"; 226 /** A JSON key. */ 227 public static final String JSON_KEY_GEO_FILTER_COORDINATES_PARAM = "coordinatesparam"; 228 /** A JSON key. */ 229 public static final String JSON_KEY_GEO_FILTER_FIELD_NAME = "fieldName"; 230 /** A JSON key. */ 231 public static final String JSON_KEY_GEO_FILTER_RADIUS = "radius"; 232 /** A JSON key. */ 233 public static final String JSON_KEY_GEO_FILTER_RADIUS_PARAM = "radiusparam"; 234 /** A JSON key. */ 235 public static final String JSON_KEY_GEO_FILTER_UNITS = "units"; 236 /** A JSON key. */ 237 public static final String JSON_KEY_GEO_FILTER_UNITS_PARAM = "unitsparam"; 238 239 /** The default values. */ 240 /** A JSON key. */ 241 public static final String DEFAULT_QUERY_PARAM = "q"; 242 /** A JSON key. */ 243 public static final String DEFAULT_LAST_QUERY_PARAM = "lq"; 244 /** A JSON key. */ 245 public static final String DEFAULT_RELOADED_PARAM = "reloaded"; 246 247 /** The whole JSON file. */ 248 protected JSONObject m_configObject; 249 250 /** The optional base configuration that should be changed by the JSON configuration. */ 251 private I_CmsSearchConfiguration m_baseConfig; 252 253 /** Constructor taking the JSON as JSONObject. 254 * @param jsonObject The JSON that should be evaluated as JSONObject. 255 */ 256 public CmsJSONSearchConfigurationParser(JSONObject jsonObject) { 257 258 m_configObject = jsonObject; 259 260 } 261 262 /** Constructor taking the JSON as String. 263 * @param json The JSON that should be parsed as String. 264 * @throws JSONException Thrown if parsing fails. 265 */ 266 public CmsJSONSearchConfigurationParser(String json) 267 throws JSONException { 268 269 init(json, null); 270 } 271 272 /** Constructor taking the JSON as String. 273 * @param json The JSON that should be parsed as String. 274 * @param baseConfig A base configuration that is adjusted by the JSON configuration string. 275 * @throws JSONException Thrown if parsing fails. 276 */ 277 public CmsJSONSearchConfigurationParser(String json, I_CmsSearchConfiguration baseConfig) 278 throws JSONException { 279 280 init(json, baseConfig); 281 } 282 283 /** Helper for reading a mandatory String value list - throwing an Exception if parsing fails. 284 * @param json The JSON object where the list should be read from. 285 * @param key The key of the value to read. 286 * @return The value from the JSON. 287 * @throws JSONException thrown when parsing fails. 288 */ 289 protected static List<String> parseMandatoryStringValues(JSONObject json, String key) throws JSONException { 290 291 List<String> list = null; 292 JSONArray array = json.getJSONArray(key); 293 list = new ArrayList<String>(array.length()); 294 for (int i = 0; i < array.length(); i++) { 295 try { 296 String entry = array.getString(i); 297 list.add(entry); 298 } catch (JSONException e) { 299 LOG.info(Messages.get().getBundle().key(Messages.LOG_OPTIONAL_STRING_ENTRY_UNPARSABLE_1, key), e); 300 } 301 } 302 return list; 303 } 304 305 /** Helper for reading an optional Boolean value - returning <code>null</code> if parsing fails. 306 * @param json The JSON object where the value should be read from. 307 * @param key The key of the value to read. 308 * @return The value from the JSON, or <code>null</code> if the value does not exist, or is no Boolean. 309 */ 310 protected static Boolean parseOptionalBooleanValue(JSONObject json, String key) { 311 312 try { 313 return Boolean.valueOf(json.getBoolean(key)); 314 } catch (JSONException e) { 315 LOG.info(Messages.get().getBundle().key(Messages.LOG_OPTIONAL_BOOLEAN_MISSING_1, key), e); 316 return null; 317 } 318 } 319 320 /** Helper for reading an optional Integer value - returning <code>null</code> if parsing fails. 321 * @param json The JSON object where the value should be read from. 322 * @param key The key of the value to read. 323 * @return The value from the JSON, or <code>null</code> if the value does not exist, or is no Integer. 324 */ 325 protected static Integer parseOptionalIntValue(JSONObject json, String key) { 326 327 try { 328 return Integer.valueOf(json.getInt(key)); 329 } catch (JSONException e) { 330 LOG.info(Messages.get().getBundle().key(Messages.LOG_OPTIONAL_INTEGER_MISSING_1, key), e); 331 return null; 332 } 333 } 334 335 /** Helper for reading an optional String value - returning <code>null</code> if parsing fails. 336 * @param json The JSON object where the value should be read from. 337 * @param key The key of the value to read. 338 * @return The value from the JSON, or <code>null</code> if the value does not exist. 339 */ 340 protected static String parseOptionalStringValue(JSONObject json, String key) { 341 342 try { 343 return json.getString(key); 344 } catch (JSONException e) { 345 LOG.info(Messages.get().getBundle().key(Messages.LOG_OPTIONAL_STRING_MISSING_1, key), e); 346 return null; 347 } 348 } 349 350 /** Helper for reading an optional String value list - returning <code>null</code> if parsing fails for the whole list, otherwise just skipping unparsable entries. 351 * @param json The JSON object where the list should be read from. 352 * @param key The key of the value to read. 353 * @return The value from the JSON, or <code>null</code> if the value does not exist. 354 */ 355 protected static List<String> parseOptionalStringValues(JSONObject json, String key) { 356 357 List<String> list = null; 358 try { 359 list = parseMandatoryStringValues(json, key); 360 } catch (JSONException e) { 361 LOG.info(Messages.get().getBundle().key(Messages.LOG_OPTIONAL_STRING_LIST_MISSING_1, key), e); 362 return null; 363 } 364 return list; 365 } 366 367 /** 368 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parseCommon(CmsObject) 369 */ 370 @Override 371 public I_CmsSearchConfigurationCommon parseCommon(CmsObject cms) { 372 373 String indexName = getIndex(cms); 374 375 return new CmsSearchConfigurationCommon( 376 getQueryParam(), 377 getLastQueryParam(), 378 getEscapeQueryChars(), 379 getFirstCallParam(), 380 getSearchForEmptyQuery(), 381 getIgnoreQuery(), 382 getQueryModifier(), 383 indexName, 384 getCore(), 385 getExtraSolrParams(), 386 getAdditionalParameters(), 387 getIgnoreReleaseDate(), 388 getIgnoreExpirationDate(), 389 getMaxReturnedResults(indexName)); 390 } 391 392 /** 393 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parseDidYouMean() 394 */ 395 public I_CmsSearchConfigurationDidYouMean parseDidYouMean() { 396 397 try { 398 JSONObject didYouMean = m_configObject.getJSONObject(JSON_KEY_DIDYOUMEAN); 399 String param = parseOptionalStringValue(didYouMean, JSON_KEY_DIDYOUMEAN_QUERYPARAM); 400 // default to the normal query param 401 if (null == param) { 402 param = getQueryParam(); 403 } 404 Boolean collate = parseOptionalBooleanValue(didYouMean, JSON_KEY_DIDYOUMEAN_COLLATE); 405 Integer count = parseOptionalIntValue(didYouMean, JSON_KEY_DIDYOUMEAN_COUNT); 406 return new CmsSearchConfigurationDidYouMean(param, collate, count); 407 408 } catch (JSONException e) { 409 if (null == m_baseConfig) { 410 if (LOG.isInfoEnabled()) { 411 LOG.info(Messages.get().getBundle().key(Messages.LOG_NO_HIGHLIGHTING_CONFIG_0), e); 412 } 413 return null; 414 } else { 415 return m_baseConfig.getDidYouMeanConfig(); 416 } 417 } 418 419 } 420 421 /** 422 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parseFieldFacets() 423 */ 424 @Override 425 public Map<String, I_CmsSearchConfigurationFacetField> parseFieldFacets() { 426 427 Map<String, I_CmsSearchConfigurationFacetField> facetConfigs = new LinkedHashMap<String, I_CmsSearchConfigurationFacetField>(); 428 try { 429 JSONArray fieldFacets = m_configObject.getJSONArray(JSON_KEY_FIELD_FACETS); 430 for (int i = 0; i < fieldFacets.length(); i++) { 431 432 I_CmsSearchConfigurationFacetField config = parseFieldFacet(fieldFacets.getJSONObject(i)); 433 if (config != null) { 434 facetConfigs.put(config.getName(), config); 435 } 436 } 437 } catch (JSONException e) { 438 if (null == m_baseConfig) { 439 if (LOG.isInfoEnabled()) { 440 LOG.info(Messages.get().getBundle().key(Messages.LOG_NO_FACET_CONFIG_0), e); 441 } 442 } else { 443 facetConfigs = m_baseConfig.getFieldFacetConfigs(); 444 } 445 } 446 return facetConfigs; 447 } 448 449 /** 450 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parseGeoFilter() 451 */ 452 @Override 453 public I_CmsSearchConfigurationGeoFilter parseGeoFilter() { 454 455 try { 456 JSONObject geoFilter = m_configObject.getJSONObject(JSON_KEY_GEO_FILTER); 457 String coordinates = parseOptionalStringValue(geoFilter, JSON_KEY_GEO_FILTER_COORDINATES); 458 String coordinatesParam = parseOptionalStringValue(geoFilter, JSON_KEY_GEO_FILTER_COORDINATES_PARAM); 459 String fieldName = parseOptionalStringValue(geoFilter, JSON_KEY_GEO_FILTER_FIELD_NAME); 460 String radius = parseOptionalStringValue(geoFilter, JSON_KEY_GEO_FILTER_RADIUS); 461 String radiusParam = parseOptionalStringValue(geoFilter, JSON_KEY_GEO_FILTER_RADIUS_PARAM); 462 String units = parseOptionalStringValue(geoFilter, JSON_KEY_GEO_FILTER_UNITS); 463 String unitsParam = parseOptionalStringValue(geoFilter, JSON_KEY_GEO_FILTER_UNITS_PARAM); 464 return new CmsSearchConfigurationGeoFilter( 465 coordinates, 466 coordinatesParam, 467 fieldName, 468 radius, 469 radiusParam, 470 units, 471 unitsParam); 472 } catch (JSONException e) { 473 if (null == m_baseConfig) { 474 if (LOG.isInfoEnabled()) { 475 LOG.info(Messages.get().getBundle().key(Messages.LOG_NO_GEOFILTER_CONFIG_0), e); 476 } 477 return null; 478 } else { 479 return m_baseConfig.getGeoFilterConfig(); 480 } 481 } 482 } 483 484 /** 485 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parseHighlighter() 486 */ 487 @Override 488 public I_CmsSearchConfigurationHighlighting parseHighlighter() { 489 490 try { 491 JSONObject highlighter = m_configObject.getJSONObject(JSON_KEY_HIGHLIGHTER); 492 String field = highlighter.getString(JSON_KEY_HIGHLIGHTER_FIELD); 493 Integer snippets = parseOptionalIntValue(highlighter, JSON_KEY_HIGHLIGHTER_SNIPPETS); 494 Integer fragsize = parseOptionalIntValue(highlighter, JSON_KEY_HIGHLIGHTER_FRAGSIZE); 495 String alternateField = parseOptionalStringValue(highlighter, JSON_KEY_HIGHLIGHTER_ALTERNATE_FIELD); 496 Integer maxAlternateFieldLength = parseOptionalIntValue( 497 highlighter, 498 JSON_KEY_HIGHLIGHTER_MAX_LENGTH_ALTERNATE_FIELD); 499 String pre = parseOptionalStringValue(highlighter, JSON_KEY_HIGHLIGHTER_SIMPLE_PRE); 500 String post = parseOptionalStringValue(highlighter, JSON_KEY_HIGHLIGHTER_SIMPLE_POST); 501 String formatter = parseOptionalStringValue(highlighter, JSON_KEY_HIGHLIGHTER_FORMATTER); 502 String fragmenter = parseOptionalStringValue(highlighter, JSON_KEY_HIGHLIGHTER_FRAGMENTER); 503 Boolean useFastVectorHighlighting = parseOptionalBooleanValue( 504 highlighter, 505 JSON_KEY_HIGHLIGHTER_FASTVECTORHIGHLIGHTING); 506 return new CmsSearchConfigurationHighlighting( 507 field, 508 snippets, 509 fragsize, 510 alternateField, 511 maxAlternateFieldLength, 512 pre, 513 post, 514 formatter, 515 fragmenter, 516 useFastVectorHighlighting); 517 } catch (JSONException e) { 518 if (null == m_baseConfig) { 519 if (LOG.isInfoEnabled()) { 520 LOG.info(Messages.get().getBundle().key(Messages.LOG_NO_HIGHLIGHTING_CONFIG_0), e); 521 } 522 return null; 523 } else { 524 return m_baseConfig.getHighlighterConfig(); 525 } 526 } 527 } 528 529 /** 530 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parsePagination() 531 */ 532 @Override 533 public I_CmsSearchConfigurationPagination parsePagination() { 534 535 return CmsSearchConfigurationPagination.create(getPageParam(), getPageSizes(), getPageNavLength()); 536 } 537 538 /** 539 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parseQueryFacet() 540 */ 541 @Override 542 public I_CmsSearchConfigurationFacetQuery parseQueryFacet() { 543 544 try { 545 JSONObject queryFacetObject = m_configObject.getJSONObject(JSON_KEY_QUERY_FACET); 546 try { 547 List<I_CmsFacetQueryItem> queries = parseFacetQueryItems(queryFacetObject); 548 String label = parseOptionalStringValue(queryFacetObject, JSON_KEY_FACET_LABEL); 549 Boolean isAndFacet = parseOptionalBooleanValue(queryFacetObject, JSON_KEY_FACET_ISANDFACET); 550 List<String> preselection = parseOptionalStringValues(queryFacetObject, JSON_KEY_FACET_PRESELECTION); 551 Boolean ignoreAllFacetFilters = parseOptionalBooleanValue( 552 queryFacetObject, 553 JSON_KEY_FACET_IGNOREALLFACETFILTERS); 554 List<String> excludeTags = parseOptionalStringValues(queryFacetObject, JSON_KEY_FACET_EXCLUDETAGS); 555 return new CmsSearchConfigurationFacetQuery( 556 queries, 557 label, 558 isAndFacet, 559 preselection, 560 ignoreAllFacetFilters, 561 excludeTags); 562 } catch (JSONException e) { 563 LOG.error( 564 Messages.get().getBundle().key( 565 Messages.ERR_QUERY_FACET_MANDATORY_KEY_MISSING_1, 566 JSON_KEY_QUERY_FACET_QUERY), 567 e); 568 return null; 569 } 570 } catch (JSONException e) { 571 // nothing to do, configuration is optional 572 return null != m_baseConfig ? m_baseConfig.getQueryFacetConfig() : null; 573 } 574 } 575 576 /** 577 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parseRangeFacets() 578 */ 579 public Map<String, I_CmsSearchConfigurationFacetRange> parseRangeFacets() { 580 581 Map<String, I_CmsSearchConfigurationFacetRange> facetConfigs = new LinkedHashMap<String, I_CmsSearchConfigurationFacetRange>(); 582 try { 583 JSONArray rangeFacets = m_configObject.getJSONArray(JSON_KEY_RANGE_FACETS); 584 for (int i = 0; i < rangeFacets.length(); i++) { 585 586 I_CmsSearchConfigurationFacetRange config = parseRangeFacet(rangeFacets.getJSONObject(i)); 587 if (config != null) { 588 facetConfigs.put(config.getName(), config); 589 } 590 } 591 } catch (JSONException e) { 592 if (null == m_baseConfig) { 593 if (LOG.isInfoEnabled()) { 594 LOG.info(Messages.get().getBundle().key(Messages.LOG_NO_FACET_CONFIG_0), e); 595 } 596 } else { 597 facetConfigs = m_baseConfig.getRangeFacetConfigs(); 598 } 599 } 600 return facetConfigs; 601 602 } 603 604 /** 605 * @see org.opencms.jsp.search.config.parser.I_CmsSearchConfigurationParser#parseSorting() 606 */ 607 @Override 608 public I_CmsSearchConfigurationSorting parseSorting() { 609 610 List<I_CmsSearchConfigurationSortOption> options = getSortOptions(); 611 String defaultOptionParamValue = parseOptionalStringValue(m_configObject, JSON_KEY_DEFAULT_SORT_OPTION); 612 I_CmsSearchConfigurationSortOption defaultSortOption = null; 613 if (null != defaultOptionParamValue) { 614 Iterator<I_CmsSearchConfigurationSortOption> optIterator = options.iterator(); 615 while ((null == defaultSortOption) && optIterator.hasNext()) { 616 I_CmsSearchConfigurationSortOption opt = optIterator.next(); 617 if (Objects.equals(opt.getParamValue(), defaultOptionParamValue)) { 618 defaultSortOption = opt; 619 } 620 } 621 } 622 if ((null == defaultSortOption) && !options.isEmpty()) { 623 defaultSortOption = options.get(0); 624 } 625 return CmsSearchConfigurationSorting.create(getSortParam(), options, defaultSortOption); 626 } 627 628 /** Returns a map with additional request parameters, mapping the parameter names to Solr query parts. 629 * @return A map with additional request parameters, mapping the parameter names to Solr query parts. 630 */ 631 protected Map<String, String> getAdditionalParameters() { 632 633 Map<String, String> result; 634 try { 635 JSONArray additionalParams = m_configObject.getJSONArray(JSON_KEY_ADDITIONAL_PARAMETERS); 636 result = new HashMap<String, String>(additionalParams.length()); 637 for (int i = 0; i < additionalParams.length(); i++) { 638 try { 639 JSONObject currentParam = additionalParams.getJSONObject(i); 640 String param = currentParam.getString(JSON_KEY_ADDITIONAL_PARAMETERS_PARAM); 641 String solrQuery = parseOptionalStringValue(currentParam, JSON_KEY_ADDITIONAL_PARAMETERS_SOLRQUERY); 642 result.put(param, solrQuery); 643 } catch (JSONException e) { 644 LOG.error(Messages.get().getBundle().key(Messages.ERR_ADDITIONAL_PARAMETER_CONFIG_WRONG_0), e); 645 continue; 646 } 647 } 648 } catch (JSONException e) { 649 LOG.info(Messages.get().getBundle().key(Messages.LOG_ADDITIONAL_PARAMETER_CONFIG_NOT_PARSED_0), e); 650 return null != m_baseConfig 651 ? m_baseConfig.getGeneralConfig().getAdditionalParameters() 652 : new HashMap<String, String>(); 653 } 654 return result; 655 } 656 657 /** Returns the configured Solr core, or <code>null</code> if no core is configured. 658 * @return The configured Solr core, or <code>null</code> if no core is configured. 659 */ 660 protected String getCore() { 661 662 try { 663 return m_configObject.getString(JSON_KEY_CORE); 664 } catch (JSONException e) { 665 if (null == m_baseConfig) { 666 if (LOG.isInfoEnabled()) { 667 LOG.info(Messages.get().getBundle().key(Messages.LOG_NO_CORE_SPECIFIED_0), e); 668 } 669 return null; 670 } else { 671 return m_baseConfig.getGeneralConfig().getSolrCore(); 672 } 673 } 674 } 675 676 /** 677 * Returns the flag, indicating if the characters in the query string that are commands to Solr should be escaped. 678 * @return the flag, indicating if the characters in the query string that are commands to Solr should be escaped. 679 */ 680 protected Boolean getEscapeQueryChars() { 681 682 Boolean isEscape = parseOptionalBooleanValue(m_configObject, JSON_KEY_ESCAPE_QUERY_CHARACTERS); 683 return (null == isEscape) && (m_baseConfig != null) 684 ? Boolean.valueOf(m_baseConfig.getGeneralConfig().getEscapeQueryChars()) 685 : isEscape; 686 } 687 688 /** Returns the configured extra parameters that should be given to Solr, or the empty string if no parameters are configured. 689 * @return The configured extra parameters that should be given to Solr, or the empty string if no parameters are configured. 690 */ 691 protected String getExtraSolrParams() { 692 693 try { 694 return m_configObject.getString(JSON_KEY_EXTRASOLRPARAMS); 695 } catch (JSONException e) { 696 if (null == m_baseConfig) { 697 if (LOG.isInfoEnabled()) { 698 LOG.info(Messages.get().getBundle().key(Messages.LOG_NO_EXTRA_PARAMETERS_0), e); 699 } 700 return ""; 701 } else { 702 return m_baseConfig.getGeneralConfig().getExtraSolrParams(); 703 } 704 } 705 } 706 707 /** Returns the configured request parameter for the last query, or the default parameter if no core is configured. 708 * @return The configured request parameter for the last query, or the default parameter if no core is configured. 709 */ 710 protected String getFirstCallParam() { 711 712 String param = parseOptionalStringValue(m_configObject, JSON_KEY_RELOADED_PARAM); 713 if (param == null) { 714 return null != m_baseConfig ? m_baseConfig.getGeneralConfig().getReloadedParam() : DEFAULT_RELOADED_PARAM; 715 } else { 716 return param; 717 } 718 } 719 720 /** Returns a flag indicating if also expired resources should be found. 721 * @return A flag indicating if also expired resources should be found. 722 */ 723 protected Boolean getIgnoreExpirationDate() { 724 725 Boolean isIgnoreExpirationDate = parseOptionalBooleanValue(m_configObject, JSON_KEY_IGNORE_EXPIRATION_DATE); 726 return (null == isIgnoreExpirationDate) && (m_baseConfig != null) 727 ? Boolean.valueOf(m_baseConfig.getGeneralConfig().getIgnoreExpirationDate()) 728 : isIgnoreExpirationDate; 729 } 730 731 /** Returns a flag indicating if the query given by the parameters should be ignored. 732 * @return A flag indicating if the query given by the parameters should be ignored. 733 */ 734 protected Boolean getIgnoreQuery() { 735 736 Boolean isIgnoreQuery = parseOptionalBooleanValue(m_configObject, JSON_KEY_IGNORE_QUERY); 737 return (null == isIgnoreQuery) && (m_baseConfig != null) 738 ? Boolean.valueOf(m_baseConfig.getGeneralConfig().getIgnoreQueryParam()) 739 : isIgnoreQuery; 740 } 741 742 /** Returns a flag indicating if also unreleased resources should be found. 743 * @return A flag indicating if also unreleased resources should be found. 744 */ 745 protected Boolean getIgnoreReleaseDate() { 746 747 Boolean isIgnoreReleaseDate = parseOptionalBooleanValue(m_configObject, JSON_KEY_IGNORE_RELEASE_DATE); 748 return (null == isIgnoreReleaseDate) && (m_baseConfig != null) 749 ? Boolean.valueOf(m_baseConfig.getGeneralConfig().getIgnoreReleaseDate()) 750 : isIgnoreReleaseDate; 751 } 752 753 /** Returns the configured Solr index, or <code>null</code> if no core is configured. 754 * @param cms the current context. 755 * @return The configured Solr index, or <code>null</code> if no core is configured. 756 */ 757 protected String getIndex(CmsObject cms) { 758 759 String indexName = null; 760 try { 761 indexName = m_configObject.getString(JSON_KEY_INDEX); 762 } catch (JSONException e) { 763 if (null == m_baseConfig) { 764 if (LOG.isInfoEnabled()) { 765 LOG.info(Messages.get().getBundle().key(Messages.LOG_NO_INDEX_SPECIFIED_0), e); 766 } 767 } else { 768 indexName = m_baseConfig.getGeneralConfig().getSolrIndex(); 769 } 770 } 771 return null != indexName 772 ? indexName 773 : (cms.getRequestContext().getCurrentProject().isOnlineProject() 774 ? CmsSolrIndex.DEFAULT_INDEX_NAME_ONLINE 775 : CmsSolrIndex.DEFAULT_INDEX_NAME_OFFLINE); 776 } 777 778 /** Returns the configured request parameter for the last query, or the default parameter if no core is configured. 779 * @return The configured request parameter for the last query, or the default parameter if no core is configured. 780 */ 781 protected String getLastQueryParam() { 782 783 String param = parseOptionalStringValue(m_configObject, JSON_KEY_LAST_QUERYPARAM); 784 if (param == null) { 785 return null != m_baseConfig 786 ? m_baseConfig.getGeneralConfig().getLastQueryParam() 787 : DEFAULT_LAST_QUERY_PARAM; 788 } else { 789 return param; 790 } 791 } 792 793 /** Returns the number of maximally returned results, or <code>null</code> if the indexes default should be used. 794 * @param indexName the name of the index to search in. 795 * @return The number of maximally returned results, or <code>null</code> if the indexes default should be used. 796 */ 797 protected int getMaxReturnedResults(String indexName) { 798 799 Integer maxReturnedResults = parseOptionalIntValue(m_configObject, JSON_KEY_MAX_RETURNED_RESULTS); 800 if (null != maxReturnedResults) { 801 return maxReturnedResults.intValue(); 802 } else if (m_baseConfig != null) { 803 return m_baseConfig.getGeneralConfig().getMaxReturnedResults(); 804 } else { 805 try { 806 CmsSolrIndex idx = OpenCms.getSearchManager().getIndexSolr(indexName); 807 if (null != idx) { 808 return idx.getMaxProcessedResults(); 809 } 810 } catch (Throwable t) { 811 // This is ok, it's allowed to have an external other index here. 812 LOG.debug( 813 "Parsing JSON search configuration for none-CmsSolrIndex " 814 + indexName 815 + ". Setting max processed results to unlimited."); 816 } 817 return CmsSolrIndex.MAX_RESULTS_UNLIMITED; 818 } 819 } 820 821 /** Returns the configured length of the "Google"-like page navigation, or the default parameter if no core is configured. 822 * @return The configured length of the "Google"-like page navigation, or the default parameter if no core is configured. 823 */ 824 protected Integer getPageNavLength() { 825 826 return parseOptionalIntValue(m_configObject, JSON_KEY_PAGENAVLENGTH); 827 } 828 829 /** Returns the configured request parameter for the current page, or the default parameter if no core is configured. 830 * @return The configured request parameter for the current page, or the default parameter if no core is configured. 831 */ 832 protected String getPageParam() { 833 834 return parseOptionalStringValue(m_configObject, JSON_KEY_PAGEPARAM); 835 } 836 837 /** Returns the configured page sizes, or the default page size if no core is configured. 838 * @return The configured page sizes, or the default page size if no core is configured. 839 */ 840 protected List<Integer> getPageSizes() { 841 842 if (m_configObject.has(JSON_KEY_PAGESIZE)) { 843 try { 844 return Collections.singletonList(Integer.valueOf(m_configObject.getInt(JSON_KEY_PAGESIZE))); 845 } catch (JSONException e) { 846 List<Integer> result = null; 847 String pageSizesString = null; 848 try { 849 pageSizesString = m_configObject.getString(JSON_KEY_PAGESIZE); 850 String[] pageSizesArray = pageSizesString.split("-"); 851 if (pageSizesArray.length > 0) { 852 result = new ArrayList<>(pageSizesArray.length); 853 for (int i = 0; i < pageSizesArray.length; i++) { 854 result.add(Integer.valueOf(pageSizesArray[i])); 855 } 856 } 857 return result; 858 } catch (NumberFormatException | JSONException e1) { 859 LOG.warn( 860 Messages.get().getBundle().key(Messages.LOG_PARSING_PAGE_SIZES_FAILED_1, pageSizesString), 861 e); 862 } 863 } 864 } 865 if (null == m_baseConfig) { 866 if (LOG.isInfoEnabled()) { 867 LOG.info(Messages.get().getBundle().key(Messages.LOG_NO_PAGESIZE_SPECIFIED_0)); 868 } 869 return null; 870 } else { 871 return m_baseConfig.getPaginationConfig().getPageSizes(); 872 } 873 } 874 875 /** Returns the optional query modifier. 876 * @return the optional query modifier. 877 */ 878 protected String getQueryModifier() { 879 880 String queryModifier = parseOptionalStringValue(m_configObject, JSON_KEY_QUERY_MODIFIER); 881 return (null == queryModifier) && (null != m_baseConfig) 882 ? m_baseConfig.getGeneralConfig().getQueryModifier() 883 : queryModifier; 884 } 885 886 /** Returns the configured request parameter for the query string, or the default parameter if no core is configured. 887 * @return The configured request parameter for the query string, or the default parameter if no core is configured. 888 */ 889 protected String getQueryParam() { 890 891 String param = parseOptionalStringValue(m_configObject, JSON_KEY_QUERYPARAM); 892 if (param == null) { 893 return null != m_baseConfig ? m_baseConfig.getGeneralConfig().getQueryParam() : DEFAULT_QUERY_PARAM; 894 } else { 895 return param; 896 } 897 } 898 899 /** Returns a flag, indicating if search should be performed using a wildcard if the empty query is given. 900 * @return A flag, indicating if search should be performed using a wildcard if the empty query is given. 901 */ 902 protected Boolean getSearchForEmptyQuery() { 903 904 Boolean isSearchForEmptyQuery = parseOptionalBooleanValue(m_configObject, JSON_KEY_SEARCH_FOR_EMPTY_QUERY); 905 return (isSearchForEmptyQuery == null) && (null != m_baseConfig) 906 ? Boolean.valueOf(m_baseConfig.getGeneralConfig().getSearchForEmptyQueryParam()) 907 : isSearchForEmptyQuery; 908 } 909 910 /** Returns the list of the configured sort options, or the empty list if no sort options are configured. 911 * @return The list of the configured sort options, or the empty list if no sort options are configured. 912 */ 913 protected List<I_CmsSearchConfigurationSortOption> getSortOptions() { 914 915 List<I_CmsSearchConfigurationSortOption> options = new LinkedList<I_CmsSearchConfigurationSortOption>(); 916 try { 917 JSONArray sortOptions = m_configObject.getJSONArray(JSON_KEY_SORTOPTIONS); 918 for (int i = 0; i < sortOptions.length(); i++) { 919 I_CmsSearchConfigurationSortOption option = parseSortOption(sortOptions.getJSONObject(i)); 920 if (option != null) { 921 options.add(option); 922 } 923 } 924 } catch (JSONException e) { 925 if (null == m_baseConfig) { 926 if (LOG.isInfoEnabled()) { 927 LOG.info(Messages.get().getBundle().key(Messages.LOG_NO_SORT_CONFIG_0), e); 928 } 929 } else { 930 options = m_baseConfig.getSortConfig().getSortOptions(); 931 } 932 } 933 return options; 934 } 935 936 /** Returns the configured request parameter for the sort option, or the default parameter if no core is configured. 937 * @return The configured request parameter for the sort option, or the default parameter if no core is configured. 938 */ 939 protected String getSortParam() { 940 941 return parseOptionalStringValue(m_configObject, JSON_KEY_SORTPARAM); 942 } 943 944 /** Initialization that parses the String to a JSON object. 945 * @param configString The JSON as string. 946 * @param baseConfig The optional basic search configuration to overwrite (partly) by the JSON configuration. 947 * @throws JSONException thrown if parsing fails. 948 */ 949 protected void init(String configString, I_CmsSearchConfiguration baseConfig) throws JSONException { 950 951 m_configObject = new JSONObject(configString); 952 m_baseConfig = baseConfig; 953 } 954 955 /** Parses a single query item for the query facet. 956 * @param item JSON object of the query item. 957 * @return the parsed query item, or <code>null</code> if parsing failed. 958 */ 959 protected I_CmsFacetQueryItem parseFacetQueryItem(JSONObject item) { 960 961 String query; 962 try { 963 query = item.getString(JSON_KEY_QUERY_FACET_QUERY_QUERY); 964 } catch (JSONException e) { 965 // TODO: Log 966 return null; 967 } 968 String label = parseOptionalStringValue(item, JSON_KEY_QUERY_FACET_QUERY_LABEL); 969 return new CmsFacetQueryItem(query, label); 970 } 971 972 /** Parses the list of query items for the query facet. 973 * @param queryFacetObject JSON object representing the node with the query facet. 974 * @return list of query options 975 * @throws JSONException if the list cannot be parsed. 976 */ 977 protected List<I_CmsFacetQueryItem> parseFacetQueryItems(JSONObject queryFacetObject) throws JSONException { 978 979 JSONArray items = queryFacetObject.getJSONArray(JSON_KEY_QUERY_FACET_QUERY); 980 List<I_CmsFacetQueryItem> result = new ArrayList<I_CmsFacetQueryItem>(items.length()); 981 for (int i = 0; i < items.length(); i++) { 982 I_CmsFacetQueryItem item = parseFacetQueryItem(items.getJSONObject(i)); 983 if (item != null) { 984 result.add(item); 985 } 986 } 987 return result; 988 } 989 990 /** Parses the field facet configurations. 991 * @param fieldFacetObject The JSON sub-node with the field facet configurations. 992 * @return The field facet configurations. 993 */ 994 protected I_CmsSearchConfigurationFacetField parseFieldFacet(JSONObject fieldFacetObject) { 995 996 try { 997 String field = fieldFacetObject.getString(JSON_KEY_FACET_FIELD); 998 String name = parseOptionalStringValue(fieldFacetObject, JSON_KEY_FACET_NAME); 999 String label = parseOptionalStringValue(fieldFacetObject, JSON_KEY_FACET_LABEL); 1000 Integer minCount = parseOptionalIntValue(fieldFacetObject, JSON_KEY_FACET_MINCOUNT); 1001 Integer limit = parseOptionalIntValue(fieldFacetObject, JSON_KEY_FACET_LIMIT); 1002 String prefix = parseOptionalStringValue(fieldFacetObject, JSON_KEY_FACET_PREFIX); 1003 String sorder = parseOptionalStringValue(fieldFacetObject, JSON_KEY_FACET_ORDER); 1004 I_CmsSearchConfigurationFacet.SortOrder order; 1005 try { 1006 order = I_CmsSearchConfigurationFacet.SortOrder.valueOf(sorder); 1007 } catch (Exception e) { 1008 order = null; 1009 } 1010 String filterQueryModifier = parseOptionalStringValue(fieldFacetObject, JSON_KEY_FACET_FILTERQUERYMODIFIER); 1011 Boolean isAndFacet = parseOptionalBooleanValue(fieldFacetObject, JSON_KEY_FACET_ISANDFACET); 1012 List<String> preselection = parseOptionalStringValues(fieldFacetObject, JSON_KEY_FACET_PRESELECTION); 1013 Boolean ignoreFilterAllFacetFilters = parseOptionalBooleanValue( 1014 fieldFacetObject, 1015 JSON_KEY_FACET_IGNOREALLFACETFILTERS); 1016 List<String> excludeTags = parseOptionalStringValues(fieldFacetObject, JSON_KEY_FACET_EXCLUDETAGS); 1017 return new CmsSearchConfigurationFacetField( 1018 field, 1019 name, 1020 minCount, 1021 limit, 1022 prefix, 1023 label, 1024 order, 1025 filterQueryModifier, 1026 isAndFacet, 1027 preselection, 1028 ignoreFilterAllFacetFilters, 1029 excludeTags); 1030 } catch (JSONException e) { 1031 LOG.error( 1032 Messages.get().getBundle().key(Messages.ERR_FIELD_FACET_MANDATORY_KEY_MISSING_1, JSON_KEY_FACET_FIELD), 1033 e); 1034 return null; 1035 } 1036 } 1037 1038 /** Parses the query facet configurations. 1039 * @param rangeFacetObject The JSON sub-node with the query facet configurations. 1040 * @return The query facet configurations. 1041 */ 1042 protected I_CmsSearchConfigurationFacetRange parseRangeFacet(JSONObject rangeFacetObject) { 1043 1044 try { 1045 String range = rangeFacetObject.getString(JSON_KEY_RANGE_FACET_RANGE); 1046 String name = parseOptionalStringValue(rangeFacetObject, JSON_KEY_FACET_NAME); 1047 String label = parseOptionalStringValue(rangeFacetObject, JSON_KEY_FACET_LABEL); 1048 Integer minCount = parseOptionalIntValue(rangeFacetObject, JSON_KEY_FACET_MINCOUNT); 1049 String start = rangeFacetObject.getString(JSON_KEY_RANGE_FACET_START); 1050 String end = rangeFacetObject.getString(JSON_KEY_RANGE_FACET_END); 1051 String gap = rangeFacetObject.getString(JSON_KEY_RANGE_FACET_GAP); 1052 List<String> sother = parseOptionalStringValues(rangeFacetObject, JSON_KEY_RANGE_FACET_OTHER); 1053 Boolean hardEnd = parseOptionalBooleanValue(rangeFacetObject, JSON_KEY_RANGE_FACET_HARDEND); 1054 I_CmsSearchConfigurationFacetRange.Method method = null; 1055 String methodStr = parseOptionalStringValue(rangeFacetObject, JSON_KEY_RANGE_FACET_METHOD); 1056 if (null != methodStr) { 1057 try { 1058 method = I_CmsSearchConfigurationFacetRange.Method.valueOf(methodStr); 1059 } catch (Exception e) { 1060 LOG.error(Messages.get().getBundle().key(Messages.ERR_INVALID_RANGE_METHOD_OPTION_1, methodStr), e); 1061 } 1062 } 1063 List<I_CmsSearchConfigurationFacetRange.Other> other = null; 1064 if (sother != null) { 1065 other = new ArrayList<I_CmsSearchConfigurationFacetRange.Other>(sother.size()); 1066 for (String so : sother) { 1067 try { 1068 I_CmsSearchConfigurationFacetRange.Other o = I_CmsSearchConfigurationFacetRange.Other.valueOf( 1069 so); 1070 other.add(o); 1071 } catch (Exception e) { 1072 LOG.error(Messages.get().getBundle().key(Messages.ERR_INVALID_OTHER_OPTION_1, so), e); 1073 } 1074 } 1075 } 1076 Boolean isAndFacet = parseOptionalBooleanValue(rangeFacetObject, JSON_KEY_FACET_ISANDFACET); 1077 List<String> preselection = parseOptionalStringValues(rangeFacetObject, JSON_KEY_FACET_PRESELECTION); 1078 Boolean ignoreAllFacetFilters = parseOptionalBooleanValue( 1079 rangeFacetObject, 1080 JSON_KEY_FACET_IGNOREALLFACETFILTERS); 1081 List<String> excludeTags = parseOptionalStringValues(rangeFacetObject, JSON_KEY_FACET_EXCLUDETAGS); 1082 return new CmsSearchConfigurationFacetRange( 1083 range, 1084 start, 1085 end, 1086 gap, 1087 other, 1088 hardEnd, 1089 method, 1090 name, 1091 minCount, 1092 label, 1093 isAndFacet, 1094 preselection, 1095 ignoreAllFacetFilters, 1096 excludeTags); 1097 } catch (JSONException e) { 1098 LOG.error( 1099 Messages.get().getBundle().key( 1100 Messages.ERR_RANGE_FACET_MANDATORY_KEY_MISSING_1, 1101 JSON_KEY_RANGE_FACET_RANGE 1102 + ", " 1103 + JSON_KEY_RANGE_FACET_START 1104 + ", " 1105 + JSON_KEY_RANGE_FACET_END 1106 + ", " 1107 + JSON_KEY_RANGE_FACET_GAP), 1108 e); 1109 return null; 1110 } 1111 1112 } 1113 1114 /** Returns a single sort option configuration as configured via the methods parameter, or null if the parameter does not specify a sort option. 1115 * @param json The JSON sort option configuration. 1116 * @return The sort option configuration, or null if the JSON could not be read. 1117 */ 1118 protected I_CmsSearchConfigurationSortOption parseSortOption(JSONObject json) { 1119 1120 try { 1121 String solrValue = json.getString(JSON_KEY_SORTOPTION_SOLRVALUE); 1122 String paramValue = parseOptionalStringValue(json, JSON_KEY_SORTOPTION_PARAMVALUE); 1123 paramValue = (paramValue == null) ? solrValue : paramValue; 1124 String label = parseOptionalStringValue(json, JSON_KEY_SORTOPTION_LABEL); 1125 label = (label == null) ? paramValue : label; 1126 return new CmsSearchConfigurationSortOption(label, paramValue, solrValue); 1127 } catch (JSONException e) { 1128 LOG.error( 1129 Messages.get().getBundle().key(Messages.ERR_SORT_OPTION_NOT_PARSABLE_1, JSON_KEY_SORTOPTION_SOLRVALUE), 1130 e); 1131 return null; 1132 } 1133 } 1134}