1 // ==========================================================================
  2 // Papercube.adaptor
  3 //
  4 // License:  PaperCube is open source software released under 
  5 //           the MIT License (see license.js)
  6 // ==========================================================================
  7 
  8 require('core'); 
  9 
 10 /** @class Papercube.adaptor
 11 
 12   The adaptor object controls the interaction between Papercube and the server
 13   back end.
 14 
 15   Desired Actions:
 16 
 17   PAPERS
 18   searchPapers // summary info only
 19   getPaperDetails // returns {Array} paper details with authors
 20   getAllDataForPaper // reutnrs {Array} full paper details.
 21   
 22   AUTHORS:
 23   searchAuthors // summary info only
 24   getAuthorDetails // returns {Array} author details
 25 
 26   This list of actions will probably be modified, expanded, and reduced as the project develops.
 27 
 28   @extends SC.Server
 29   @author Peter Bergstrom
 30   @version 1.0
 31   @copyright 2008-2009 Peter Bergström.
 32   @static
 33 */
 34 
 35 Papercube.adaptor = SC.Server.create(
 36 /** @scope Papercube.adaptor */{
 37   
 38   /**
 39     The base API path is specified here and it will be automatically added to requests.
 40     
 41     @property {String}
 42     @default '/api/request.php'
 43   */
 44   base: '/api/request.php',
 45 
 46   /**
 47     This is the application prefix. It is used when loading data into the SC Store.
 48     
 49     @property {Array}
 50     @default ['Papercube']
 51   */
 52   prefix: ["Papercube"],
 53   
 54   /**
 55     This allows the tracking of which query result should be loaded from the SC Store. Many 
 56     requests could be in flight and you may want to match the latest request easily.
 57     
 58     @property {Integer}
 59     @default 0
 60   */
 61   requestIndex: 0,
 62   
 63   /**
 64     List of requests. 
 65     
 66     @property {Object}
 67   */
 68   requests: 
 69   {
 70      searchPapers: // summary info only
 71      {
 72  	 	   action: 'searchPapers',
 73  			 onSuccess: 'Papercube.adaptor.searchPapersSuccess', onError: 'Papercube.adaptor.handleError', onFailure: 'Papercube.adaptor.handleFailure'	
 74      },
 75      getPaperDetails: // returns {Array} paper details with authors
 76      {
 77  	 	   action: 'getPaperDetails',
 78  			 onSuccess: 'Papercube.adaptor.getPaperDetailsSuccess', onError: 'Papercube.adaptor.handleError', onFailure: 'Papercube.adaptor.handleFailure'	
 79      },
 80      getAllDataForPaper: // returns {Array} paper details with authors
 81      {
 82  	 	   action: 'getAllDataForPaper',
 83  			 onSuccess: 'Papercube.adaptor.getPaperDetailsSuccess', onError: 'Papercube.adaptor.handleError', onFailure: 'Papercube.adaptor.handleFailure'	
 84      },
 85      searchAuthors: // summary info only
 86      {
 87  	 	   action: 'searchAuthors', 
 88  			 onSuccess: 'Papercube.adaptor.searchAuthorsSuccess', onError: 'Papercube.adaptor.handleError', onFailure: 'Papercube.adaptor.handleFailure'	
 89      },
 90      getAuthorDetails: // returns {Array} author details
 91      {
 92  	 	   action: 'getAuthorDetails', 
 93  			 onSuccess: 'Papercube.adaptor.getAuthorDetailsSuccess', onError: 'Papercube.adaptor.handleError', onFailure: 'Papercube.adaptor.handleFailure'	
 94      }
 95   },
 96 
 97   /**
 98     Searches against a key and value in the database for papers. 
 99   
100     @param searchKey {string} The field key that is searched against.
101     @param searchValue {string} The field value that is search against.
102     @param sc {Integer} The searchCount parameter, it is used for determining what is shown in search list.
103     @param start {Integer} The start index.
104     @param limit {Integer} The limit.
105     
106     @returns {Boolean} Returns NO if there is an error.
107   */
108   searchPapers: function(searchKey, searchValue, sc, start, limit)
109   {
110     console.log("searchPapers@Papercube.adaptor");
111 
112     if(searchKey == null)
113     {
114       console.log("No searchKey specified, aborting!");
115       return NO;
116     }
117     var requestURL = "searchKey=" + encodeURIComponent(searchKey)  + "&searchValue="+ encodeURIComponent(searchValue)+"&queryStart="+start+"&queryLimit="+limit+"&sc="+sc;
118     this.request(this.requests.searchPapers, requestURL);
119   },
120 
121   
122   /** 
123     When the searchPapers action is successful, you want to display the results in the search list.
124     
125     @param response {Object} The response object from the AJAX request.
126   */
127   searchPapersSuccess: function(response)
128   {
129     console.log("searchPapersSuccess@Papercube.adaptor");
130     Papercube.searchController.displayResults();
131   },
132 
133   /**
134     Call back function for getPaperDetails.
135     @property {Function}
136   */
137   _getPaperDetailsCallback: null,
138 
139   /** 
140     Get the details of a given paper.
141     
142     @param guid {string} The guid parameter could also be an array of guids if desired.
143     @param callBack {Function} The callBack function is called when the request is successful.
144   */
145   getPaperDetails: function(guid, callBack)
146   {
147     console.log("getPaperDetails@Papercube.adaptor");
148     Papercube.adaptor._getPaperDetailsCallback = callBack;
149     
150     // If there are multiple requests, flatten the guids to be easily consumed by the server.
151     guid = this._handleMult(guid);
152 
153     this.request(this.requests.getPaperDetails, '', {guid: guid});
154   },
155   
156   /** 
157     Get the ALL details of a given paper.
158     
159     @param guid {string} The guid parameter could also be an array of guids if desired.
160     @param callBack {Function} The callBack function is called when the request is successful.
161   */
162   getAllDataForPaper: function(guid, callBack)
163   {
164     console.log("getAllDataForPaper@Papercube.adaptor");
165     Papercube.adaptor._getPaperDetailsCallback = callBack;
166     
167     // If there are multiple requests, flatten the guids to be easily consumed by the server.
168     guid = this._handleMult(guid);
169 
170     this.request(this.requests.getAllDataForPaper, '', {guid: guid});
171   },
172   
173   /** 
174     When the getPaperDetails action is successful, you want to display the results in the search list.
175     
176     @param response {Object} The response object from the AJAX request.
177   */
178   getPaperDetailsSuccess: function(response)
179   {
180     if(Papercube.adaptor._getPaperDetailsCallback)
181     {
182       Papercube.adaptor._getPaperDetailsCallback();
183     }
184   },
185 
186   /**
187     Searches against a key and value in the database for authors. 
188   
189     @param searchKey {string} The field key that is searched against.
190     @param searchValue {string} The field value that is search against.
191     @param sc {Integer} The searchCount parameter. Used for determining what is shown in search list.
192     @param start {Integer} The start index.
193     @param limit {Integer} The limit.
194 
195     @returns {Boolean} Returns NO if there is an error.
196   */
197   searchAuthors: function(searchKey, searchValue, sc, start, limit)
198   {
199     console.log("searchAuthors@Papercube.adaptor");
200 
201     var requestURL = '';
202 
203     if(searchKey == null)
204     {
205       console.log("No searchKey specified, aborting!");
206       return NO;
207     }
208     requestURL = "searchKey=" + encodeURIComponent(searchKey) +"&searchValue=" + encodeURIComponent(searchValue)+"&queryStart="+start+"&queryLimit="+limit+"&sc="+sc;
209     this.request(this.requests.searchAuthors, requestURL);
210   },
211   
212   /** 
213     When the searchAuthors action is successful, you want to display the results in the search list.
214     
215     @param response {Object} The response object from the AJAX request.
216   */
217   searchAuthorsSuccess: function(response)
218   {
219     console.log("searchAuthorsSuccess@Papercube.adaptor");
220     Papercube.searchController.displayResults();
221   },
222 
223   /**
224     Call back function for getAuthorDetails.
225     @property {Function}
226   */
227   _getAuthorDetailsCallBack: null,
228   
229   /** 
230     Get the details of a given author.
231     
232     @param guid {string} The guid parameter could also be an array of guids if desired.
233     @param callBack {Function} The callBack function is called when the request is successful.
234   */
235   getAuthorDetails: function(guid, callBack)
236   {
237     console.log("getAuthorDetails@Papercube.adaptor");
238 
239     // Register callback.
240     Papercube.adaptor._getAuthorDetailsCallBack = callBack;
241 
242     // If there are multiple requests, flatten the guids to be easily consumed by the server.
243     guid = this._handleMult(guid);
244     var requestURL = "guid="+guid;
245     this.request(this.requests.getAuthorDetails, requestURL);
246   },
247   
248   /** 
249     When the getAuthorDetails action is successful, you want to display the results in the search list.
250     
251     @param response {Object} The response object from the AJAX request.
252   */
253   getAuthorDetailsSuccess: function(response)
254   {
255     // Nothing to do here yet.
256     if(Papercube.adaptor._getAuthorDetailsCallBack)
257     {
258       Papercube.adaptor._getAuthorDetailsCallBack();
259     }
260   },
261 
262   /** 
263     Converts an array of guids to a comma separated string of guids, if it is not an array, it is just return as is.
264     
265     @param {Object|String} object The potential array of guids. 
266     
267     @returns {String} The guids string.
268   */
269   _handleMult: function(object)
270   {
271     if(typeof object == 'object')
272     {
273       object = object.join(',');
274     }
275     return object;
276   },
277   
278   /**
279     Create the request and call the server. 
280   
281     @param requestHash {Object} The request parameters.
282     @param url {string} The url for the request.
283     @param params {Object} The parameters for the request.
284   */
285   request: function(requestHash, url, params)
286   {
287     // Augment the URL with the base parameter.
288     var actionURL = this.base+"?action="+requestHash.action+"&"+url;
289 	  console.log(actionURL);
290 
291     // Call the server using Prototype. At this point, all requests are POSTs.
292     new Ajax.Request(actionURL,
293       {
294         parameters: params,
295         method:'post',
296         onSuccess: Papercube.adaptor.requestSuccess.bind(Papercube.adaptor, requestHash),
297         onError: Papercube.adaptor.requestError.bind(Papercube.adaptor, requestHash),
298         onFailure: Papercube.adaptor.requestFailure.bind(Papercube.adaptor, requestHash)
299       });
300   },
301   
302   /**
303     Generic success, parse the JSON and insert it into the SC Store, then pass it along to the custom success handler for the request.
304   
305     @param requestHash {Object} The request parameters.
306     @param transport {Object} The AJAX request object.
307 
308     @returns {Boolean} Returns NO if there is an error.
309   */
310   requestSuccess: function(requestHash, transport)
311   {
312     // Get the result and eval it. Then check the status of the response.
313     var resultText = transport.responseText;
314     var s = new Date().getTime();
315     
316     var json = eval('(' + resultText.replace(/[\n\r\t]/g) + ')'); // remove newlines and other baddies.
317     console.log("eval time: " + (new Date().getTime()-s));
318 
319     // Check the status of the response.
320     if(!this.evaluateStatus(json))
321     {
322       return NO;
323     }
324 
325     if(requestHash.action == "searchPapers" || requestHash.action == "searchAuthors")
326     {
327       var dLen = json.data.length;
328       var sc = Papercube.searchController._sc;
329       for(var i=0; i<dLen; i++)
330       {
331         json.data[i].sc = sc;
332       }
333     }
334     
335     // Import the records into SC Store.
336     var s = new Date().getTime();
337     this.importRecords(json.data);
338     console.log("import time: " + (new Date().getTime()-s));
339     
340     // Call the action's success handler.
341     eval(requestHash.onSuccess)(json.data);
342     
343     // Hide the request spinner.
344     // Papercube.searchController.set('showRequestSpinner', NO);
345   },
346 
347   /**
348     Generic error, then pass it along to the generic error handler for the request.
349   
350     @param requestHash {Object} The request parameters.
351     @param transport {Object} The AJAX request object.
352 
353     @returns {Boolean} Returns NO if there is an error.
354   */
355   requestError: function(transport, requestHash)
356   {
357     var resultText = transport.responseText;
358     var json = eval('(' + string.replace(/[\n\r\t]/g) + ')'); // remove newlines and other baddies.
359 
360     // Check the status of the response.
361     if(!this.evaluateStatus(json))
362     {
363       return NO;
364     }
365 
366     // Call the action's error handler.
367     eval(requestHash.onError)(json);
368 
369     // Hide request spinner.
370     Papercube.searchController.set('showRequestSpinner', NO);
371   },
372 
373   /**
374     Generic error handler.
375   
376     @param response {Object} The request response.
377     @param transport {Object} The AJAX request object.
378   */
379   handleError: function(response, result)
380   {
381     console.log("Server ERROR");
382   },
383 
384   /**
385     Generic failure, then pass it along to the generic failure handler for the request.
386   
387     @param requestHash {Object} The request parameters.
388     @param transport {Object} The AJAX request object.
389 
390     @returns {Boolean} Returns NO if there is an error.
391   */
392   requestFailure: function(requestHash, transport)
393   {
394     var resultText = transport.responseText;
395     var json = eval('(' + string.replace(/[\n\r\t]/g) + ')'); // remove newlines and other baddies.
396     // Check the status of the response.
397     if(!this.evaluateStatus(json))
398     {
399       return NO;
400     }
401 
402     // Call the action's failure handler.
403     eval(requestHash.onFailure)(json);
404 
405     // Hide request spinner.
406     // Papercube.searchController.set('showRequestSpinner', NO);
407   },
408   
409   /**
410     Generic failure handler.
411   
412     @param response {Object} The request response.
413     @param transport {Object} The AJAX request object.
414   */
415   handleFailure: function(response, result)
416   {
417     console.log("Server FAILURE");
418   },
419   
420   /**
421     Evaluate status of the response.
422   
423     @param json {Object} The request response JSON object.
424     
425     @returns {Boolean} Returns YES if NO error or returns NO if there is an error.
426   */
427   evaluateStatus: function(json)
428   {
429     switch(json.status)
430     {
431 	    case 0: 
432 		    console.log("API request error: " + json.error[0] + " - " + json.error[1]);
433 		    return NO;
434       default:
435         console.log("Success: " + json.status);
436         break;
437     }
438     return YES;
439   },
440 
441   /**
442     Import records into the SC Store.
443   
444     @param clientData {Object} Data that can be imported to the store.
445   */
446   importRecords: function(clientData)
447   {
448     // If there is client data, import it.
449     if(clientData && clientData.length > 0)
450     {
451       console.log("Importing " + clientData.length + " records");
452       this.refreshRecordsWithData(clientData,SC.Record,null,NO);
453     }
454   }
455 });
456