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