001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.jsp.search.controller; 029 030import org.opencms.file.CmsObject; 031import org.opencms.jsp.search.config.I_CmsSearchConfigurationFacetRange; 032import org.opencms.jsp.search.state.CmsSearchStateFacet; 033import org.opencms.jsp.search.state.I_CmsSearchStateFacet; 034import org.opencms.search.solr.CmsSolrQuery; 035 036import java.util.Iterator; 037import java.util.Map; 038 039/** Search controller for the field facet options. */ 040public class CmsSearchControllerFacetRange implements I_CmsSearchControllerFacetRange { 041 042 /** Configuration of the field facet options. */ 043 private final I_CmsSearchConfigurationFacetRange m_config; 044 /** State of the field facets. */ 045 private final I_CmsSearchStateFacet m_state; 046 047 /** Constructor taking the managed configuration. 048 * @param config The configuration to manage by the controller. 049 */ 050 public CmsSearchControllerFacetRange(final I_CmsSearchConfigurationFacetRange config) { 051 052 m_config = config; 053 m_state = new CmsSearchStateFacet(); 054 } 055 056 /** 057 * @see org.opencms.jsp.search.controller.I_CmsSearchController#addParametersForCurrentState(java.util.Map) 058 */ 059 @Override 060 public void addParametersForCurrentState(final Map<String, String[]> parameters) { 061 062 if (!m_state.getCheckedEntries().isEmpty()) { 063 parameters.put( 064 m_config.getParamKey(), 065 m_state.getCheckedEntries().toArray(new String[m_state.getCheckedEntries().size()])); 066 } 067 if (m_state.getIgnoreChecked()) { 068 parameters.put(m_config.getIgnoreMaxParamKey(), null); 069 } 070 071 } 072 073 /** 074 * @see org.opencms.jsp.search.controller.I_CmsSearchController#addQueryParts(CmsSolrQuery, CmsObject) 075 */ 076 @Override 077 public void addQueryParts(CmsSolrQuery query, CmsObject cms) { 078 079 addFacetPart(query); 080 addFilterQueryParts(query); 081 } 082 083 /** 084 * @see org.opencms.jsp.search.controller.I_CmsSearchControllerFacetRange#getConfig() 085 */ 086 @Override 087 public I_CmsSearchConfigurationFacetRange getConfig() { 088 089 return m_config; 090 } 091 092 /** 093 * @see org.opencms.jsp.search.controller.I_CmsSearchControllerFacetRange#getState() 094 */ 095 @Override 096 public I_CmsSearchStateFacet getState() { 097 098 return m_state; 099 } 100 101 /** 102 * @see org.opencms.jsp.search.controller.I_CmsSearchController#updateForQueryChange() 103 */ 104 @Override 105 public void updateForQueryChange() { 106 107 m_state.setIgnoreChecked(true); 108 109 } 110 111 /** 112 * @see org.opencms.jsp.search.controller.I_CmsSearchController#updateFromRequestParameters(java.util.Map, boolean) 113 */ 114 @Override 115 public void updateFromRequestParameters(final Map<String, String[]> parameters, boolean isReloaded) { 116 117 m_state.setUseLimit(!parameters.containsKey(m_config.getIgnoreMaxParamKey())); 118 119 if (isReloaded) { 120 // update checked fields 121 m_state.clearChecked(); 122 if (!m_state.getIgnoreChecked() && parameters.containsKey(m_config.getParamKey())) { 123 final String[] checked = parameters.get(m_config.getParamKey()); 124 for (int i = 0; i < checked.length; i++) { 125 String checkedEntry = checked[i]; 126 if ((null != checkedEntry) && !checkedEntry.isEmpty()) { 127 m_state.addChecked(checkedEntry); 128 } 129 } 130 131 } 132 } else { // use the preselection on first load 133 for (String checked : m_config.getPreSelection()) { 134 m_state.addChecked(checked); 135 } 136 } 137 } 138 139 /** Adds the query parts for the facet options, except the filter parts. 140 * @param query The query part that is extended with the facet options. 141 */ 142 protected void addFacetOptions(StringBuffer query) { 143 144 // start 145 appendFacetOption(query, "range.start", m_config.getStart()); 146 // end 147 appendFacetOption(query, "range.end", m_config.getEnd()); 148 // gap 149 appendFacetOption(query, "range.gap", m_config.getGap()); 150 // other 151 for (I_CmsSearchConfigurationFacetRange.Other o : m_config.getOther()) { 152 appendFacetOption(query, "range.other", o.toString()); 153 } 154 // hardend 155 appendFacetOption(query, "range.hardend", Boolean.toString(m_config.getHardEnd())); 156 // mincount 157 if (m_config.getMinCount() != null) { 158 appendFacetOption(query, "mincount", m_config.getMinCount().toString()); 159 } 160 } 161 162 /** Generate query part for the facet, without filters. 163 * @param query The query, where the facet part should be added 164 */ 165 protected void addFacetPart(CmsSolrQuery query) { 166 167 StringBuffer value = new StringBuffer(); 168 value.append("{!key=").append(m_config.getName()); 169 addFacetOptions(value); 170 if (!m_config.getIgnoreTags().isEmpty()) { 171 value.append(" ex=").append(m_config.getIgnoreTags()); 172 } 173 value.append("}"); 174 value.append(m_config.getRange()); 175 query.add("facet.range", value.toString()); 176 } 177 178 /** Adds filter parts to the query. 179 * @param query The query. 180 */ 181 protected void addFilterQueryParts(CmsSolrQuery query) { 182 183 if (!m_state.getCheckedEntries().isEmpty()) { 184 StringBuffer value = new StringBuffer(); 185 value.append("{!tag=").append(m_config.getName()).append('}'); 186 value.append(m_config.getRange()); 187 value.append(":("); 188 final Iterator<String> fieldIterator = m_state.getCheckedEntries().iterator(); 189 value.append(generateRange(fieldIterator.next())); 190 final String concater = m_config.getIsAndFacet() ? " AND " : " OR "; 191 while (fieldIterator.hasNext()) { 192 value.append(concater); 193 value.append(generateRange(fieldIterator.next())); 194 } 195 if (m_config.getHardEnd()) { 196 value.append(concater); 197 value.append("[" + m_config.getStart() + " TO " + m_config.getEnd() + "}"); 198 } 199 value.append(')'); 200 query.add("fq", value.toString()); 201 } 202 } 203 204 /** Appends the query part for the facet to the query string. 205 * @param query The current query string. 206 * @param name The name of the facet parameter, e.g. "limit", "order", .... 207 * @param value The value to set for the parameter specified by name. 208 */ 209 protected void appendFacetOption(StringBuffer query, final String name, final String value) { 210 211 query.append(" facet.").append(name).append("=").append(value); 212 } 213 214 /** 215 * Generates the range for the filter query with a given start value. 216 * @param startValue the facet item's value (start value of the range) 217 * @return the range as to put in the query 218 */ 219 private Object generateRange(String startValue) { 220 221 return "[" + startValue + " TO " + startValue + m_config.getGap() + "}"; 222 } 223 224}