Connection.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. define("dojox/atom/io/Connection", [
  2. "dojo/_base/kernel",
  3. "dojo/_base/xhr",
  4. "dojo/_base/window",
  5. "./model",
  6. "dojo/_base/declare"], function (dojo, xhrUtil, windowUtil, model) {
  7. return dojo.declare("dojox.atom.io.Connection",null,{
  8. // summary: This object implements a transport layer for working with ATOM feeds and ATOM publishing protocols.
  9. // description: This object implements a transport layer for working with ATOM feeds and ATOM publishing protocols.
  10. // Specifically, it provides a mechanism by which feeds can be fetched and entries can be fetched, created
  11. // deleted, and modified. It also provides access to the introspection data.
  12. constructor: function(/* Boolean */sync, /* Boolean */preventCache){
  13. // summary:
  14. // initializer
  15. this.sync = sync;
  16. this.preventCache = preventCache;
  17. },
  18. preventCache: false, //Flag to denote if the instance should use the xhr prevent cache mechanism
  19. alertsEnabled: false, //Flag to turn on alerts instead of throwing errors.
  20. getFeed: function(/*String*/url, /*Function*/callback, /*Function*/errorCallback, scope){
  21. // summary:
  22. // Function to obtain a s specific ATOM feed from a given ATOM Feed url.
  23. // description:
  24. // This function takes the URL for a specific ATOM feed and returns
  25. // the data from that feed to the caller through the use of a callback
  26. // handler.
  27. //
  28. // url: String
  29. // The URL of the ATOM feed to fetch.
  30. // callback:
  31. // Function
  32. // A function reference that will handle the feed when it has been retrieved.
  33. // The callback should accept two parameters: The feed object and the original complete DOM object.
  34. // scope: Object
  35. // The scope to use for all callbacks.
  36. //
  37. // returns:
  38. // Nothing. The return is handled through the callback handler.
  39. this._getXmlDoc(url, "feed", new model.Feed(), model._Constants.ATOM_NS, callback, /*handleDocumentRetrieved,*/ errorCallback, scope);
  40. },
  41. getService: function(url, callback, errorCallback, scope){
  42. // summary:
  43. // Function to retrieve an introspection document from the given URL.
  44. // description:
  45. // This function takes the URL for an ATOM item and feed and returns
  46. // the introspection document.
  47. //
  48. // url:
  49. // String
  50. // The URL of the ATOM document to obtain the introspection document of.
  51. // callback:
  52. // Function
  53. // A function reference that will handle the introspection document when it has been retrieved.
  54. // The callback should accept two parameters: The introspection document object and the original complete DOM object.
  55. //
  56. // returns:
  57. // Nothing. The return is handled through the callback handler.
  58. this._getXmlDoc(url, "service", new model.Service(url), model._Constants.APP_NS, callback, errorCallback, scope);
  59. },
  60. getEntry: function(url, callback, errorCallback, scope){
  61. // summary:
  62. // Function to retrieve a single entry from an ATOM feed from the given URL.
  63. // description:
  64. // This function takes the URL for an ATOM entry and returns the constructed dojox.atom.io.model.Entry object through
  65. // the specified callback.
  66. //
  67. // url:
  68. // String
  69. // The URL of the ATOM Entry document to parse.
  70. // callback:
  71. // Function
  72. // A function reference that will handle the Entry object obtained.
  73. // The callback should accept two parameters, the dojox.atom.io.model.Entry object and the original dom.
  74. //
  75. // returns:
  76. // Nothing. The return is handled through the callback handler.
  77. this._getXmlDoc(url, "entry", new model.Entry(), model._Constants.ATOM_NS, callback, errorCallback, scope);
  78. },
  79. _getXmlDoc: function(url, nodeName, newNode, namespace, callback, errorCallback, scope){
  80. // summary:
  81. // Internal Function to retrieve an XML document and pass the results to a callback.
  82. // description:
  83. // This internal function takes the URL for an XML document and and passes the
  84. // parsed contents to a specified callback.
  85. //
  86. // url:
  87. // String
  88. // The URL of the XML document to retrieve
  89. // callback:
  90. // Function
  91. // A function reference that will handle the retrieved XML data.
  92. // The callback should accept one parameter, the DOM of the parsed XML document.
  93. //
  94. // returns:
  95. // Nothing. The return is handled through the callback handler.
  96. if(!scope){
  97. scope = windowUtil.global;
  98. }
  99. var ae = this.alertsEnabled;
  100. var xhrArgs = {
  101. url: url,
  102. handleAs: "xml",
  103. sync: this.sync,
  104. preventCache: this.preventCache,
  105. load: function(data, args){
  106. var node = null;
  107. var evaldObj = data;
  108. var nodes;
  109. if(evaldObj){
  110. //find the first node of the appropriate name
  111. if(typeof(evaldObj.getElementsByTagNameNS)!= "undefined"){
  112. nodes = evaldObj.getElementsByTagNameNS(namespace,nodeName);
  113. if(nodes && nodes.length > 0){
  114. node = nodes.item(0);
  115. }else if(evaldObj.lastChild){
  116. // name_spaces can be used without declaration of atom (for example
  117. // gooogle feeds often returns iTunes name_space qualifiers on elements)
  118. // Treat this situation like name_spaces not enabled.
  119. node = evaldObj.lastChild;
  120. }
  121. }else if(typeof(evaldObj.getElementsByTagName)!= "undefined"){
  122. // Find the first eith the correct tag name and correct namespace.
  123. nodes = evaldObj.getElementsByTagName(nodeName);
  124. if(nodes && nodes.length > 0){
  125. for(var i=0; i<nodes.length; i++){
  126. if(nodes[i].namespaceURI == namespace){
  127. node = nodes[i];
  128. break;
  129. }
  130. }
  131. }else if(evaldObj.lastChild){
  132. node = evaldObj.lastChild;
  133. }
  134. }else if(evaldObj.lastChild){
  135. node = evaldObj.lastChild;
  136. }else{
  137. callback.call(scope, null, null, args);
  138. return;
  139. }
  140. newNode.buildFromDom(node);
  141. if(callback){
  142. callback.call(scope, newNode, evaldObj, args);
  143. }else if(ae){
  144. throw new Error("The callback value does not exist.");
  145. }
  146. }else{
  147. callback.call(scope, null, null, args);
  148. }
  149. }
  150. };
  151. if(this.user && this.user !== null){
  152. xhrArgs.user = this.user;
  153. }
  154. if(this.password && this.password !== null){
  155. xhrArgs.password = this.password;
  156. }
  157. if(errorCallback){
  158. xhrArgs.error = function(error, args){errorCallback.call(scope, error, args);};
  159. }else{
  160. xhrArgs.error = function(){
  161. throw new Error("The URL requested cannot be accessed");
  162. };
  163. }
  164. xhrUtil.get(xhrArgs);
  165. },
  166. updateEntry: function(entry, callback, errorCallback, retrieveUpdated, xmethod, scope){
  167. // summary:
  168. // Function to update a specific ATOM entry by putting the new changes via APP.
  169. // description:
  170. // This function takes a specific dojox.atom.io.model.Entry object and pushes the
  171. // changes back to the provider of the Entry.
  172. // The entry MUST have a link tag with rel="edit" for this to work.
  173. //
  174. // entry:
  175. // Object
  176. // The dojox.atom.io.model.Entry object to update.
  177. // callback:
  178. // Function
  179. // A function reference that will handle the results from the entry update.
  180. // The callback should accept two parameters: The first is an Entry object, and the second is the URL of that Entry
  181. // Either can be null, depending on the value of retrieveUpdated.
  182. // retrieveUpdated:
  183. // boolean
  184. // A boolean flag denoting if the entry that was updated should then be
  185. // retrieved and returned to the caller via the callback.
  186. // xmethod:
  187. // boolean
  188. // Whether to use POST for PUT/DELETE items and send the X-Method-Override header.
  189. // scope:
  190. // Object
  191. // The scope to use for all callbacks.
  192. //
  193. // returns:
  194. // Nothing. The return is handled through the callback handler.
  195. if(!scope){
  196. scope = windowUtil.global;
  197. }
  198. entry.updated = new Date();
  199. var url = entry.getEditHref();
  200. if(!url){
  201. throw new Error("A URL has not been specified for editing this entry.");
  202. }
  203. var self = this;
  204. var ae = this.alertsEnabled;
  205. var xhrArgs = {
  206. url: url,
  207. handleAs: "text",
  208. contentType: "text/xml",
  209. sync: this.sync,
  210. preventCache: this.preventCache,
  211. load: function(data, args){
  212. var location = null;
  213. if(retrieveUpdated){
  214. location = args.xhr.getResponseHeader("Location");
  215. if(!location){location = url;}
  216. //Function to handle the callback mapping of a getEntry after an update to return the
  217. //entry and location.
  218. var handleRetrieve = function(entry, dom, args){
  219. if(callback){
  220. callback.call(scope, entry, location, args);
  221. }else if(ae){
  222. throw new Error("The callback value does not exist.");
  223. }
  224. };
  225. self.getEntry(location,handleRetrieve);
  226. }else{
  227. if(callback){
  228. callback.call(scope, entry, args.xhr.getResponseHeader("Location"), args);
  229. }else if(ae){
  230. throw new Error("The callback value does not exist.");
  231. }
  232. }
  233. return data;
  234. }
  235. };
  236. if(this.user && this.user !== null){
  237. xhrArgs.user = this.user;
  238. }
  239. if(this.password && this.password !== null){
  240. xhrArgs.password = this.password;
  241. }
  242. if(errorCallback){
  243. xhrArgs.error = function(error, args){errorCallback.call(scope, error, args);};
  244. }else{
  245. xhrArgs.error = function(){
  246. throw new Error("The URL requested cannot be accessed");
  247. };
  248. }
  249. if(xmethod){
  250. xhrArgs.postData = entry.toString(true); //Set the content to send.
  251. xhrArgs.headers = {"X-Method-Override": "PUT"};
  252. xhrUtil.post(xhrArgs);
  253. }else{
  254. xhrArgs.putData = entry.toString(true); //Set the content to send.
  255. var xhr = xhrUtil.put(xhrArgs);
  256. }
  257. },
  258. addEntry: function(entry, url, callback, errorCallback, retrieveEntry, scope){
  259. // summary:
  260. // Function to add a new ATOM entry by posting the new entry via APP.
  261. // description:
  262. // This function takes a specific dojox.atom.io.model.Entry object and pushes the
  263. // changes back to the provider of the Entry.
  264. //
  265. // entry:
  266. // Object
  267. // The dojox.atom.io.model.Entry object to publish.
  268. // callback:
  269. // Function
  270. // A function reference that will handle the results from the entry publish.
  271. // The callback should accept two parameters: The first is an dojox.atom.io.model.Entry object, and the second is the location of the entry
  272. // Either can be null, depending on the value of retrieveUpdated.
  273. // retrieveEntry:
  274. // boolean
  275. // A boolean flag denoting if the entry that was created should then be
  276. // retrieved and returned to the caller via the callback.
  277. // scope:
  278. // Object
  279. // The scope to use for all callbacks.
  280. //
  281. // returns:
  282. // Nothing. The return is handled through the callback handler.
  283. if(!scope){
  284. scope = windowUtil.global;
  285. }
  286. entry.published = new Date();
  287. entry.updated = new Date();
  288. var feedUrl = entry.feedUrl;
  289. var ae = this.alertsEnabled;
  290. //Determine which URL to use for the post.
  291. if(!url && feedUrl){url = feedUrl;}
  292. if(!url){
  293. if(ae){
  294. throw new Error("The request cannot be processed because the URL parameter is missing.");
  295. }
  296. return;
  297. }
  298. var self = this;
  299. var xhrArgs = {
  300. url: url,
  301. handleAs: "text",
  302. contentType: "text/xml",
  303. sync: this.sync,
  304. preventCache: this.preventCache,
  305. postData: entry.toString(true),
  306. load: function(data, args){
  307. var location = args.xhr.getResponseHeader("Location");
  308. if(!location){
  309. location = url;
  310. }
  311. if(!args.retrieveEntry){
  312. if(callback){
  313. callback.call(scope, entry, location, args);
  314. }else if(ae){
  315. throw new Error("The callback value does not exist.");
  316. }
  317. }else{
  318. //Function to handle the callback mapping of a getEntry after an update to return the
  319. //entry and location.
  320. var handleRetrieve = function(entry, dom, args){
  321. if(callback){
  322. callback.call(scope, entry, location, args);
  323. }else if(ae){
  324. throw new Error("The callback value does not exist.");
  325. }
  326. };
  327. self.getEntry(location,handleRetrieve);
  328. }
  329. return data;
  330. }
  331. };
  332. if(this.user && this.user !== null){
  333. xhrArgs.user = this.user;
  334. }
  335. if(this.password && this.password !== null){
  336. xhrArgs.password = this.password;
  337. }
  338. if(errorCallback){
  339. xhrArgs.error = function(error, args){errorCallback.call(scope, error, args);};
  340. }else{
  341. xhrArgs.error = function(){
  342. throw new Error("The URL requested cannot be accessed");
  343. };
  344. }
  345. xhrUtil.post(xhrArgs);
  346. },
  347. deleteEntry: function(entry,callback,errorCallback,xmethod,scope){
  348. // summary:
  349. // Function to delete a specific ATOM entry via APP.
  350. // description:
  351. // This function takes a specific dojox.atom.io.model.Entry object and calls for a delete on the
  352. // service housing the ATOM Entry database.
  353. // The entry MUST have a link tag with rel="edit" for this to work.
  354. //
  355. // entry:
  356. // Object
  357. // The dojox.atom.io.model.Entry object to delete.
  358. // callback:
  359. // Function
  360. // A function reference that will handle the results from the entry delete.
  361. // The callback is called only if the delete is successful.
  362. //
  363. // returns:
  364. // Nothing. The return is handled through the callback handler.
  365. if(!scope){
  366. scope = windowUtil.global;
  367. }
  368. var url = null;
  369. if(typeof(entry) == "string"){
  370. url = entry;
  371. }else{
  372. url = entry.getEditHref();
  373. }
  374. if(!url){
  375. callback.call(scope, false, null);
  376. throw new Error("The request cannot be processed because the URL parameter is missing.");
  377. }
  378. var xhrArgs = {
  379. url: url,
  380. handleAs: "text",
  381. sync: this.sync,
  382. preventCache: this.preventCache,
  383. load: function(data, args){
  384. callback.call(scope, args);
  385. return data;
  386. }
  387. };
  388. if(this.user && this.user !== null){
  389. xhrArgs.user = this.user;
  390. }
  391. if(this.password && this.password !== null){
  392. xhrArgs.password = this.password;
  393. }
  394. if(errorCallback){
  395. xhrArgs.error = function(error, args){errorCallback.call(scope, error, args);};
  396. }else{
  397. xhrArgs.error = function(){
  398. throw new Error("The URL requested cannot be accessed");
  399. };
  400. }
  401. if(xmethod){
  402. xhrArgs.headers = {"X-Method-Override": "DELETE"};
  403. dhxr.post(xhrArgs);
  404. }else{
  405. xhrUtil.del(xhrArgs);
  406. }
  407. }
  408. });
  409. });