1 // $Id$ 2 3 /** 4 * The ParameterStore, as its name suggests, stores Solr parameters. Widgets 5 * expose some of these parameters to the user. Whenever the user changes the 6 * values of these parameters, the state of the application changes. In order to 7 * allow the user to move back and forth between these states with the browser's 8 * Back and Forward buttons, and to bookmark these states, each state needs to 9 * be stored. The easiest method is to store the exposed parameters in the URL 10 * hash (see the <tt>ParameterHashStore</tt> class). However, you may implement 11 * your own storage method by extending this class. 12 * 13 * <p>For a list of possible parameters, please consult the links below.</p> 14 * 15 * @see http://wiki.apache.org/solr/CoreQueryParameters 16 * @see http://wiki.apache.org/solr/CommonQueryParameters 17 * @see http://wiki.apache.org/solr/SimpleFacetParameters 18 * @see http://wiki.apache.org/solr/HighlightingParameters 19 * @see http://wiki.apache.org/solr/MoreLikeThis 20 * @see http://wiki.apache.org/solr/SpellCheckComponent 21 * @see http://wiki.apache.org/solr/StatsComponent 22 * @see http://wiki.apache.org/solr/TermsComponent 23 * @see http://wiki.apache.org/solr/TermVectorComponent 24 * @see http://wiki.apache.org/solr/LocalParams 25 * 26 * @param properties A map of fields to set. Refer to the list of public fields. 27 * @class ParameterStore 28 */ 29 AjaxSolr.ParameterStore = AjaxSolr.Class.extend( 30 /** @lends AjaxSolr.ParameterStore.prototype */ 31 { 32 /** 33 * The names of the exposed parameters. Any parameters that your widgets 34 * expose to the user, directly or indirectly, should be listed here. 35 * 36 * @field 37 * @public 38 * @type String[] 39 * @default [] 40 */ 41 exposed: [], 42 43 /** 44 * The Solr parameters. 45 * 46 * @field 47 * @private 48 * @type Object 49 * @default {} 50 */ 51 params: {}, 52 53 /** 54 * A reference to the parameter store's manager. For internal use only. 55 * 56 * @field 57 * @private 58 * @type AjaxSolr.AbstractManager 59 */ 60 manager: null, 61 62 /** 63 * An abstract hook for child implementations. 64 * 65 * <p>This method should do any necessary one-time initializations.</p> 66 */ 67 init: function () {}, 68 69 /** 70 * Some Solr parameters may be specified multiple times. It is easiest to 71 * hard-code a list of such parameters. You may change the list by passing 72 * <code>{ multiple: /pattern/ }</code> as an argument to the constructor of 73 * this class or one of its children, e.g.: 74 * 75 * <p><code>new ParameterStore({ multiple: /pattern/ })</code> 76 * 77 * @param {String} name The name of the parameter. 78 * @returns {Boolean} Whether the parameter may be specified multiple times. 79 */ 80 isMultiple: function (name) { 81 return name.match(/^(?:bf|bq|facet\.date|facet\.date\.other|facet\.field|facet\.query|fq|pf|qf)$/); 82 }, 83 84 /** 85 * Returns a parameter. If the parameter doesn't exist, creates it. 86 * 87 * @param {String} name The name of the parameter. 88 * @returns {AjaxSolr.Parameter|AjaxSolr.Parameter[]} The parameter. 89 */ 90 get: function (name) { 91 if (this.params[name] === undefined) { 92 var param = new AjaxSolr.Parameter({ name: name }); 93 if (this.isMultiple(name)) { 94 this.params[name] = [ param ]; 95 } 96 else { 97 this.params[name] = param; 98 } 99 } 100 return this.params[name]; 101 }, 102 103 /** 104 * If the parameter may be specified multiple times, returns the values of 105 * all identically-named parameters. If the parameter may be specified only 106 * once, returns the value of that parameter. 107 * 108 * @param {String} name The name of the parameter. 109 * @returns {String[]|Number[]} The value(s) of the parameter. 110 */ 111 values: function (name) { 112 if (this.params[name] !== undefined) { 113 if (this.isMultiple(name)) { 114 var values = []; 115 for (var i = 0, l = this.params[name].length; i < l; i++) { 116 values.push(this.params[name][i].val()); 117 } 118 return values; 119 } 120 else { 121 return [ this.params[name].val() ]; 122 } 123 } 124 return []; 125 }, 126 127 /** 128 * If the parameter may be specified multiple times, adds the given parameter 129 * to the list of identically-named parameters, unless one already exists with 130 * the same value. If it may be specified only once, replaces the parameter. 131 * 132 * @param {String} name The name of the parameter. 133 * @param {AjaxSolr.Parameter} [param] The parameter. 134 * @returns {AjaxSolr.Parameter|Boolean} The parameter, or false. 135 */ 136 add: function (name, param) { 137 if (param === undefined) { 138 param = new AjaxSolr.Parameter({ name: name }); 139 } 140 if (this.isMultiple(name)) { 141 if (this.params[name] === undefined) { 142 this.params[name] = [ param ]; 143 } 144 else { 145 if (AjaxSolr.inArray(param.val(), this.values(name)) == -1) { 146 this.params[name].push(param); 147 } 148 else { 149 return false; 150 } 151 } 152 } 153 else { 154 this.params[name] = param; 155 } 156 return param; 157 }, 158 159 /** 160 * Deletes a parameter. 161 * 162 * @param {String} name The name of the parameter. 163 * @param {Number} [index] The index of the parameter. 164 */ 165 remove: function (name, index) { 166 if (index === undefined) { 167 delete this.params[name]; 168 } 169 else { 170 this.params[name].splice(index, 1); 171 if (this.params[name].length == 0) { 172 delete this.params[name]; 173 } 174 } 175 }, 176 177 /** 178 * Finds all parameters with matching values. 179 * 180 * @param {String} name The name of the parameter. 181 * @param {String|Number|String[]|Number[]|RegExp} value The value. 182 * @returns {String|Number[]} The indices of the parameters found. 183 */ 184 find: function (name, value) { 185 if (this.params[name] !== undefined) { 186 if (this.isMultiple(name)) { 187 var indices = []; 188 for (var i = 0, l = this.params[name].length; i < l; i++) { 189 if (AjaxSolr.equals(this.params[name][i].val(), value)) { 190 indices.push(i); 191 } 192 } 193 return indices.length ? indices : false; 194 } 195 else { 196 if (AjaxSolr.equals(this.params[name].val(), value)) { 197 return name; 198 } 199 } 200 } 201 return false; 202 }, 203 204 /** 205 * If the parameter may be specified multiple times, creates a parameter using 206 * the given name and value, and adds it to the list of identically-named 207 * parameters, unless one already exists with the same value. If it may be 208 * specified only once, replaces the parameter. 209 * 210 * @param {String} name The name of the parameter. 211 * @param {String|Number|String[]|Number[]} value The value. 212 * @returns {AjaxSolr.Parameter|Boolean} The parameter, or false. 213 */ 214 addByValue: function (name, value) { 215 if (this.isMultiple(name) && AjaxSolr.isArray(value)) { 216 var ret = []; 217 for (var i = 0, l = value.length; i < l; i++) { 218 ret.push(this.add(name, new AjaxSolr.Parameter({ name: name, value: value[i] }))); 219 } 220 return ret; 221 } 222 else { 223 return this.add(name, new AjaxSolr.Parameter({ name: name, value: value })) 224 } 225 }, 226 227 /** 228 * Deletes any parameter with a matching value. 229 * 230 * @param {String} name The name of the parameter. 231 * @param {String|Number|String[]|Number[]|RegExp} value The value. 232 * @returns {String|Number[]} The indices deleted. 233 */ 234 removeByValue: function (name, value) { 235 var indices = this.find(name, value); 236 if (indices) { 237 if (AjaxSolr.isArray(indices)) { 238 for (var i = indices.length - 1; i >= 0; i--) { 239 this.remove(name, indices[i]); 240 } 241 } 242 else { 243 this.remove(indices); 244 } 245 } 246 return indices; 247 }, 248 249 /** 250 * Returns the Solr parameters as a query string. 251 * 252 * <p>IE6 calls the default toString() if you write <tt>store.toString() 253 * </tt>. So, we need to choose another name for toString().</p> 254 */ 255 string: function () { 256 var params = []; 257 for (var name in this.params) { 258 if (this.isMultiple(name)) { 259 for (var i = 0, l = this.params[name].length; i < l; i++) { 260 params.push(this.params[name][i].string()); 261 } 262 } 263 else { 264 params.push(this.params[name].string()); 265 } 266 } 267 return AjaxSolr.compact(params).join('&'); 268 }, 269 270 /** 271 * Parses a query string into Solr parameters. 272 * 273 * @param {String} str The string to parse. 274 */ 275 parseString: function (str) { 276 var pairs = str.split('&'); 277 for (var i = 0, l = pairs.length; i < l; i++) { 278 if (pairs[i]) { // ignore leading, trailing, and consecutive &'s 279 var param = new AjaxSolr.Parameter(); 280 param.parseString(pairs[i]); 281 this.add(param.name, param); 282 } 283 } 284 }, 285 286 /** 287 * Returns the exposed parameters as a query string. 288 * 289 * @returns {String} A string representation of the exposed parameters. 290 */ 291 exposedString: function () { 292 var params = []; 293 for (var i = 0, l = this.exposed.length; i < l; i++) { 294 if (this.params[this.exposed[i]] !== undefined) { 295 if (this.isMultiple(this.exposed[i])) { 296 for (var j = 0, m = this.params[this.exposed[i]].length; j < m; j++) { 297 params.push(this.params[this.exposed[i]][j].string()); 298 } 299 } 300 else { 301 params.push(this.params[this.exposed[i]].string()); 302 } 303 } 304 } 305 return AjaxSolr.compact(params).join('&'); 306 }, 307 308 /** 309 * Resets the values of the exposed parameters. 310 */ 311 exposedReset: function () { 312 for (var i = 0, l = this.exposed.length; i < l; i++) { 313 this.remove(this.exposed[i]); 314 } 315 }, 316 317 /** 318 * Loads the values of exposed parameters from persistent storage. It is 319 * necessary, in most cases, to reset the values of exposed parameters before 320 * setting the parameters to the values in storage. This is to ensure that a 321 * parameter whose name is not present in storage is properly reset. 322 * 323 * @param {Boolean} [reset=true] Whether to reset the exposed parameters. 324 * before loading new values from persistent storage. Default: true. 325 */ 326 load: function (reset) { 327 if (reset === undefined) { 328 reset = true; 329 } 330 if (reset) { 331 this.exposedReset(); 332 } 333 this.parseString(this.storedString()); 334 }, 335 336 /** 337 * An abstract hook for child implementations. 338 * 339 * <p>Stores the values of the exposed parameters in persistent storage. This 340 * method should usually be called before each Solr request.</p> 341 */ 342 save: function () {}, 343 344 /** 345 * An abstract hook for child implementations. 346 * 347 * <p>Returns the string to parse from persistent storage.</p> 348 * 349 * @returns {String} The string from persistent storage. 350 */ 351 storedString: function () { 352 return ''; 353 } 354 }); 355