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