1 // generated by build.sh for running on Node.js
  2 if (typeof jQuery === 'undefined') { // jQuery is defined in server code env.
  3     if (typeof process === 'object' && typeof process.versions === 'object') {
  4         var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
  5     }
  6 }
  7 ;(function () {
  8 var ctor = (function() {  // generated by build.sh for running on Node.js
  9 // Added to SDK by build script.
 10 // Object.keys() is defined in Javascript 1.8.5
 11 // This code will be used when the environment doen't support Object.keys()
 12 // For details refer to:
 13 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
 14 if (!Object.keys) {
 15   Object.keys = (function () {
 16     var hasOwnProperty = Object.prototype.hasOwnProperty,
 17         hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
 18         dontEnums = [
 19           'toString',
 20           'toLocaleString',
 21           'valueOf',
 22           'hasOwnProperty',
 23           'isPrototypeOf',
 24           'propertyIsEnumerable',
 25           'constructor'
 26         ],
 27         dontEnumsLength = dontEnums.length
 28 
 29     return function (obj) {
 30       if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object')
 31 
 32       var result = []
 33 
 34       for (var prop in obj) {
 35         if (hasOwnProperty.call(obj, prop)) result.push(prop)
 36       }
 37 
 38       if (hasDontEnumBug) {
 39         for (var i=0; i < dontEnumsLength; i++) {
 40           if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i])
 41         }
 42       }
 43       return result
 44     }
 45   })()
 46 };
 47 /**@license MIT-promiscuous library-©2013 Ruben Verborgh*/
 48 if(typeof Promise === 'undefined') {
 49   /**@license MIT-promiscuous-©Ruben Verborgh*/
 50   !function(n,t){function c(n,t){return(typeof t)[0]==n}function u(i,o){return o=function f(e,h,l,a,s,p){function y(n){return function(t){s&&(s=0,f(c,n,t))}}if(a=f.q,e!=c)return u(function(n,t){a.push({p:this,r:n,j:t,1:e,0:h})});if(l&&c(n,l)|c(t,l))try{s=l.then}catch(j){h=0,l=j}if(c(n,s))try{s.call(l,y(1),h=y(0))}catch(j){h(j)}else for(o=function(t,o){return c(n,t=h?t:o)?u(function(n,c){r(this,n,c,l,t)}):i},p=0;p<a.length;)s=a[p++],c(n,e=s[h])?r(s.p,s.r,s.j,l,e):(h?s.r:s.j)(l)},o.q=[],i.call(i={then:function(n,t){return o(n,t)},"catch":function(n){return o(0,n)}},function(n){o(c,1,n)},function(n){o(c,0,n)}),i}function r(u,r,i,o,f){setTimeout(function(){try{o=f(o),f=o&&c(t,o)|c(n,o)&&o.then,c(n,f)?o==u?i(TypeError()):f.call(o,r,i):r(o)}catch(e){i(e)}})}function i(n){return u(function(t){t(n)})}Promise=u,u.resolve=i,u.reject=function(n){return u(function(t,c){c(n)})},u.all=function(n){return u(function(t,c,u,r){r=[],u=n.length||t(r),n.map(function(n,o){i(n).then(function(n){r[o]=n,--u||t(r)},c)})})}}("f","o");
 51 }
 52 // Generated by CoffeeScript 1.8.0
 53 var KiiJQXHRWrapper, KiiJQueryHttpRequest, KiiRequest, KiiTiXHRWrapper, KiiTitaniumHttpRequest, KiiUtilities, KiiXHRWrapper, KiiXHRWrapperFactory, KiiXMLHttpRequest, root, _Kii, _KiiSocialConnect,
 54   __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
 55   __hasProp = {}.hasOwnProperty,
 56   __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
 57 
 58 root = ((typeof exports) !== "undefined") && (exports !== null) ? new Object() : this;
 59 
 60 root.KiiSocialNetworkName = {
 61   FACEBOOK: 1,
 62   TWITTER: 2,
 63   QQ: 3,
 64   GOOGLEPLUS: 4,
 65   RENREN: 5
 66 };
 67 
 68 root.KiiSite = {
 69   US: "https://api.kii.com/api",
 70   JP: "https://api-jp.kii.com/api",
 71   SG: "https://api-sg.kii.com/api",
 72   EU: "https://api-eu.kii.com/api"
 73 };
 74 
 75 root.KiiServerCodeEnvironmentVersion = {
 76   V0: "0",
 77   V6: "6"
 78 };
 79 
 80 
 81 /**
 82     @class The main SDK class
 83     @exports root.Kii as Kii
 84 
 85     This class must be initialized before any Kii SDK functions are performed. This class also allows the application to make some high-level user calls and access some application-wide data at any time using static methods.
 86  */
 87 
 88 root.Kii = (function() {
 89   var _additionalHeaders, _instance;
 90 
 91   function Kii() {}
 92 
 93   _instance = null;
 94 
 95   _additionalHeaders = null;
 96 
 97 
 98   /**
 99       Kii SDK Build Number
100       @returns {String} current build number of the SDK
101    */
102 
103   Kii.getBuildNumber = function() {
104     return "1";
105   };
106 
107 
108   /**
109       Kii SDK Version Number
110       @returns {String} current version number of the SDK
111    */
112 
113   Kii.getSDKVersion = function() {
114     return "2.4.19";
115   };
116 
117   Kii.getBaseURL = function() {
118     return _instance._baseURL;
119   };
120 
121 
122   /**
123       Retrieve the current app ID
124       @returns {String} The current app ID
125    */
126 
127   Kii.getAppID = function() {
128     return _instance._appID;
129   };
130 
131   Kii.getAdditionalHeaders = function() {
132     return _additionalHeaders;
133   };
134 
135   Kii.setAdditionalHeaders = function(additionalHeaders) {
136     return _additionalHeaders = additionalHeaders;
137   };
138 
139 
140   /**
141       Retrieve the current app key
142       @returns {String} The current app key
143    */
144 
145   Kii.getAppKey = function() {
146     return _instance._appKey;
147   };
148 
149   Kii.isLogging = function() {
150     return _instance._logging;
151   };
152 
153   Kii.setLogging = function(logging) {
154     _instance._logging = logging;
155     root.Kii.logger("Setting logging: " + logging);
156     return root.Kii.logger("Base URL: " + _instance._baseURL);
157   };
158 
159 
160   /** Set the access token lifetime in seconds.
161   
162   If you don't call this method or call it with 0, token won't be expired.
163   Call this method if you like the access token to be expired
164   after a certain period. Once called, token retrieved
165   by each future authentication will have the specified lifetime.
166   Note that, it will not update the lifetime of token received prior
167   calling this method. Once expired, you have to login again to renew the token.
168   @param expiresIn The life time of access token in seconds.
169   @throws {InvalidArgumentException} If specified expiresIn is negative.
170   @throws {IllegalStateException} If Kii has not been initialized
171   @example
172   Kii.setAccessTokenExpiration(3600);
173    */
174 
175   Kii.setAccessTokenExpiration = function(expiresIn) {
176     if (!_instance) {
177       throw new root.IllegalStateException('Kii is not initialized');
178     }
179     if (isNaN(parseInt(expiresIn, 10))) {
180       throw new root.InvalidArgumentException('expiresIn should be a number');
181     }
182     if (expiresIn < 0) {
183       throw new root.InvalidArgumentException('expiresIn should not negative number');
184     }
185     if (_instance) {
186       return _instance._expiresIn = expiresIn;
187     }
188   };
189 
190 
191   /** Returns access token lifetime in seconds.
192   
193   If access token lifetime has not set explicitly by {@link Kii.setAccessTokenExpiration(expiresIn)}, returns 0.
194   @return access token lifetime in seconds.
195   @throws {IllegalStateException} If Kii has not been initialized
196    */
197 
198   Kii.getAccessTokenExpiration = function() {
199     if (!_instance) {
200       throw new root.IllegalStateException('Kii is not initialized');
201     }
202     return _instance._expiresIn;
203   };
204 
205 
206   /** Initialize the Kii SDK with a specific URL
207   
208   Should be the first Kii SDK action your application makes.
209   @param String appID The application ID found in your Kii developer console
210   @param String appKey The application key found in your Kii developer console
211   @param KiiSite site Can be one of the constants KiiSite.US, KiiSite.JP, KiiSite.SG depending on your location.
212   @example
213   Kii.initializeWithSite("my-app-id", "my-app-key", KiiSite.JP);
214    */
215 
216   Kii.initializeWithSite = function(appID, appKey, site) {
217     _instance = new _Kii(appID, appKey, site);
218     return root.Kii.logger("Initialized " + appID + ", " + appKey + ", " + site);
219   };
220 
221 
222   /** Initialize the Kii SDK
223   
224   Should be the first Kii SDK action your application makes.
225   @param String appID The application ID found in your Kii developer console
226   @param String appKey The application key found in your Kii developer console
227   @example
228   Kii.initialize("my-app-id", "my-app-key");
229    */
230 
231   Kii.initialize = function(appID, appKey) {
232     return root.Kii.initializeWithSite(appID, appKey, root.KiiSite.US);
233   };
234 
235   Kii.logger = function(message) {
236     if (_instance._logging) {
237       return console.log(message);
238     }
239   };
240 
241 
242   /**
243       Creates a reference to a bucket for this app
244   
245       <br><br>The bucket will be created/accessed within this app's scope
246       @param String bucketName The name of the bucket the app should create/access
247       @returns {KiiBucket} A working KiiBucket object
248       @example
249       var bucket = Kii.bucketWithName("myBucket");
250    */
251 
252   Kii.bucketWithName = function(bucketName) {
253     var bucket;
254     bucket = new root.KiiBucket(bucketName, null);
255     return bucket;
256   };
257 
258 
259   /**
260       Creates a reference to a encrypted bucket for this app
261   
262       <br><br>The bucket will be created/accessed within this app's scope
263       @param String bucketName The name of the bucket the app should create/access
264       @returns {KiiEncryptedBucket} A working KiiEncryptedBucket object
265       @example
266       var bucket = Kii.encryptedBucketWithName("myBucket");
267    */
268 
269   Kii.encryptedBucketWithName = function(bucketName) {
270     var bucket;
271     bucket = new root.KiiEncryptedBucket(bucketName, null);
272     return bucket;
273   };
274 
275 
276   /**
277       Creates a reference to a group with the given name
278   
279       @param {String} groupName An application-specific group name
280       @returns {KiiGroup} A new KiiGroup reference
281       @example
282       var group = new Kii.groupWithName("myGroup");
283    */
284 
285   Kii.groupWithName = function(groupName) {
286     return new root.Kii.groupWithNameAndMembers(groupName, null);
287   };
288 
289 
290   /**
291       Creates a reference to a group with the given name and a list of default members
292   
293       @param {String} groupName An application-specific group name
294       @param {Array} members An array of KiiUser objects to add to the group
295       @returns {KiiGroup} A new KiiGroup reference
296       @example
297       var group = new KiiGroup.groupWithName("myGroup", members);
298    */
299 
300   Kii.groupWithNameAndMembers = function(groupName, members) {
301     return new root.KiiGroup.groupWithNameAndMembers(groupName, members);
302   };
303 
304   Kii.logOut = function() {
305     _instance._currentUser = null;
306     return root.KiiSocialConnect.logOutAll();
307   };
308 
309   Kii.loggedIn = function() {
310     return _instance._currentUser != null;
311   };
312 
313   Kii.getCurrentUser = function() {
314     var user;
315     if (_instance._currentUser != null) {
316       user = KiiUtilities._clone(_instance._currentUser);
317       return user;
318     } else {
319       return null;
320     }
321   };
322 
323   Kii.setCurrentUser = function(user) {
324     return _instance._currentUser = KiiUtilities._clone(user);
325   };
326 
327 
328   /** Authenticate as app admin.
329   <br><br>
330   <b>This api call must not placed on code which can be accessed by browser.
331   This api is intended to be used by server side code like Node.js.
332   If you use this api in code accessible by browser, your application id and application secret could be stolen.
333   Attacker will be act as appadmin and all the data in your application will be suffered.
334   </b>
335   @param {String} clientId assigned to your application.
336   @param {String} clientSecret assigned to your application.
337   @param {Object} [callbacks] The callback methods called when authentication succeeded/failed.
338   @param {Method} callbacks.success The callback method called when authentication succeeded.
339   @param {Method} callbacks.failure The callback method called when authentication failed.
340   @return {Promise} return promise object.
341       <ul>
342         <li>fulfill callback function: function(adminContext). adminContext is a KiiAppAdminContext instance.</li>
343         <li>reject callback function: function(error). error is an Error instance.
344           <ul>
345             <li>error.message</li>
346           </ul>
347         </li>
348       </ul>
349   @example
350   // example to use callbacks directly
351   Kii.authenticateAsAppAdmin("your client id", "your client secret", {
352       success: function(adminContext) {
353           // adminContext : KiiAppAdminContext instance
354           // Operate entities with adminContext.
355       },
356       failure: function(error, statusCode) {
357           // Authentication failed.
358       }
359   );
360   
361   // example to use Promise
362   Kii.authenticateAsAppAdmin("your client id", "your client secret").then(
363       function(adminContext) { // fulfill callback function
364           // adminContext : KiiAppAdminContext instance
365           // Operate entities with adminContext.
366   
367       },
368       function(error) { // reject callback function
369           // Authentication failed.
370           var errorString = error.message;
371       }
372   );
373    */
374 
375   Kii.authenticateAsAppAdmin = function(clientId, clientSecret, callbacks) {
376     return new Promise((function(_this) {
377       return function(resolve, reject) {
378         var authenticateAsAppAdminCallbacks;
379         authenticateAsAppAdminCallbacks = {
380           success: function() {
381             if (callbacks != null) {
382               callbacks.success.apply(callbacks, arguments);
383             }
384             return resolve(arguments[0]);
385           },
386           failure: function() {
387             if (callbacks != null) {
388               callbacks.failure.apply(callbacks, arguments);
389             }
390             return reject(KiiUtilities._Error(arguments[0]));
391           }
392         };
393         return _this._authenticateAsAppAdminUsingCallbacks(clientId, clientSecret, authenticateAsAppAdminCallbacks);
394       };
395     })(this));
396   };
397 
398   Kii._authenticateAsAppAdminUsingCallbacks = function(clientId, clientSecret, callbacks) {
399     var authCallbacks, request;
400     request = new KiiRequest("/oauth2/token", false);
401     request.setAnonymous(true);
402     request.setMethod("POST");
403     request.setData({
404       'client_id': clientId,
405       'client_secret': clientSecret
406     });
407     authCallbacks = {
408       success: (function(_this) {
409         return function(data) {
410           var admin, id, token;
411           token = data.access_token;
412           id = data.id;
413           root.Kii.logger("token: " + token);
414           root.Kii.logger("id: " + id);
415           admin = new root.KiiAppAdminContext({
416             token: token,
417             id: id
418           });
419           if (callbacks != null) {
420             return callbacks.success(admin);
421           }
422         };
423       })(this),
424       failure: (function(_this) {
425         return function(error, statusCode) {
426           root.Kii.logger("error: " + error);
427           root.Kii.logger("statusCode: " + statusCode);
428           if (callbacks != null) {
429             return callbacks.failure(error, statusCode);
430           }
431         };
432       })(this)
433     };
434     return request.execute(authCallbacks, false);
435   };
436 
437   Kii.authenticateAsAdminWithToken = function(token) {
438     return new root.KiiAppAdminContext({
439       token: token
440     });
441   };
442 
443 
444   /**
445   Instantiate KiiServerCodeEntry.
446   @param {String} entryName Name of the entry.
447   @param {String} [version] Version of the entry.
448   @param {KiiServerCodeEnvironmentVersion} [environmentVersion] Version of the Node.js. Currently, supported versions are 0 and 6.
449   @returns {KiiServerCodeEntry} KiiServerCodeEntry instance.
450   @throws {InvalidArgumentException} Thrown in the following cases: <br>
451   <li>entryName or version is not type of string </li>
452   <li>entryName or version is empty string </li>
453   <li>entryName is invalid string. Valid entryName pattern is "[a-zA-Z][_a-zA-Z0-9]*$".</li>
454   
455   @example
456       var entry = Kii.serverCodeEntryWithVersion("main", "gulsdf6ful8jvf8uq6fe7vjy6", KiiServerCodeEnvironmentVersion.V0);
457    */
458 
459   Kii.serverCodeEntry = function(entryName, version, environmentVersion) {
460     if (!KiiUtilities._validateServerCodeEntryName(entryName)) {
461       throw new root.InvalidArgumentException('entryName is invalid');
462     }
463     if (version && !KiiUtilities._validateServerCodeEnryVersion(version)) {
464       throw new root.InvalidArgumentException('version is invalid');
465     }
466     return new root.KiiServerCodeEntry(entryName, version, environmentVersion);
467   };
468 
469 
470   /**
471   @deprecated Use {@link Kii.serverCodeEntry} instead. Instantiate serverCodeEntryWithVersion with specified entry name and version.
472   @param {String} entryName Name of the entry.
473   @param {String} version Version of the entry.
474   @returns {KiiServerCodeEntry} KiiServerCodeEntry instance.
475   @throws {InvalidArgumentException} Thrown in the following cases: <br>
476   <li>entryName or version is not type of string </li>
477   <li>entryName or version is empty string </li>
478   <li>entryName is invalid string. Valid entryName pattern is "[a-zA-Z][_a-zA-Z0-9]*$".</li>
479   
480   @example
481       var entry = Kii.serverCodeEntryWithVersion("main", "gulsdf6ful8jvf8uq6fe7vjy6");
482    */
483 
484   Kii.serverCodeEntryWithVersion = function(entryName, version) {
485     if (!KiiUtilities._validateServerCodeEntryName(entryName)) {
486       throw new root.InvalidArgumentException('entryName is invalid');
487     }
488     if (!KiiUtilities._validateServerCodeEnryVersion(version)) {
489       throw new root.InvalidArgumentException('version is invalid');
490     }
491     return new root.KiiServerCodeEntry(entryName, version);
492   };
493 
494   Kii._setHttpRequestType = function(requestType) {
495     root.Kii.logger("Set http request as " + requestType);
496     return _instance._httpRequestType = requestType;
497   };
498 
499   Kii._getHttpRequestType = function() {
500     return _instance._httpRequestType;
501   };
502 
503   Kii._getKiiUtilities = function() {
504     return KiiUtilities;
505   };
506 
507 
508   /**
509   Instantiate topic belongs to application.
510   @param {String} topicName name of the topic. Must be a not empty string.
511   @return {KiiTopic} topic instance.
512    */
513 
514   Kii.topicWithName = function(topicName) {
515     var puri;
516     if (typeof topicName !== "string" || topicName === "") {
517       throw new root.InvalidArgumentException('topicName should not null or empty');
518     }
519     puri = "" + (root.Kii.getBaseURL()) + "/apps/" + (root.Kii.getAppID());
520     return new root.KiiTopic(puri, topicName);
521   };
522 
523 
524   /** Gets a list of topics in app scope
525   @param {Object} [callbacks] An object with callback methods defined
526   @param {Method} callbacks.success The callback method to call on a successful list request
527   @param {Method} callbacks.failure The callback method to call on a failed list request
528   @param {String} [paginationKey] You can specify the pagination key with the nextPaginationKey passed by callbacks.success or fullfill callback of promise. If empty string or no string object is provided, this API regards no paginationKey specified.
529   @return {Promise} return promise object.
530       <ul>
531         <li>fulfill callback function: function(params). params is Array instance.
532           <ul>
533             <li>params[0] is array of KiiTopic instances.</li>
534             <li>params[1] is string of nextPaginationKey.</li>
535           </ul>
536         </li>
537         <li>reject callback function: function(error). error is an Error instance.
538           <ul>
539             <li>error.message</li>
540           </ul>
541         </li>
542       </ul>
543   @example
544   // example to use callbacks directly
545   Kii.listTopics({
546       success: function(topicList, nextPaginationKey) {
547           // do something with the result
548           for(var i=0; i<topicList.length; i++){
549               var topic = topicList[i];
550           }
551           if (nextPaginationKey != null) {
552               Kii.listTopics({
553                   success: function(topicList, nextPaginationKey) {...},
554                   failure: function(anErrorString) {...}
555               }, nextPaginationKey);
556           }
557       },
558       failure: function(anErrorString) {
559           // do something with the error response
560       }
561   });
562   
563   // example to use promise
564   Kii.listTopics().then(
565       function(params) {
566           var topicList = params[0];
567           var nextPaginationKey = params[1];
568           // do something with the result
569           for(var i=0; i<topicList.length; i++){
570               var topic = topicList[i];
571           }
572           if (nextPaginationKey != null) {
573               Kii.listTopics(null, nextPaginationKey).then(
574                   function(params) {...},
575                   function(error) {...}
576               );
577           }
578       },
579       function(error) {
580           // do something with the error response
581       }
582   );
583    */
584 
585   Kii.listTopics = function(callbacks, paginationKey) {
586     return Kii._listTopics(callbacks, paginationKey);
587   };
588 
589   Kii._listTopics = function(callbacks, paginationKey, context) {
590     return new Promise(function(resolve, reject) {
591       var listTopicsCallbacks;
592       listTopicsCallbacks = {
593         success: function() {
594           if (callbacks != null) {
595             callbacks.success.apply(callbacks, arguments);
596           }
597           return resolve(arguments);
598         },
599         failure: function() {
600           if (callbacks != null) {
601             callbacks.failure.apply(callbacks, arguments);
602           }
603           return reject(arguments[0]);
604         }
605       };
606       return Kii._listTopicsUsingCallbacks(listTopicsCallbacks, paginationKey, context);
607     });
608   };
609 
610   Kii._listTopicsUsingCallbacks = function(callbacks, paginationKey, context) {
611     var listCallbacks, uri, wrapper;
612     uri = "" + (root.Kii.getBaseURL()) + "/apps/" + (root.Kii.getAppID()) + "/topics";
613     if (typeof paginationKey === "string" && paginationKey !== "") {
614       uri = uri + "?paginationKey=" + encodeURIComponent(paginationKey);
615     }
616     wrapper = KiiXHRWrapperFactory.createXHRWrapper('GET', uri);
617     wrapper.setKiiHeaders();
618     if (context != null) {
619       wrapper.setAuthToken(context._getToken());
620     } else {
621       wrapper.setCurrentUserToken();
622     }
623     listCallbacks = {
624       success: function() {
625         var json, topic, topics, _i, _len, _ref;
626         json = JSON.parse(wrapper.xhr.responseText);
627         topics = [];
628         _ref = json.topics;
629         for (_i = 0, _len = _ref.length; _i < _len; _i++) {
630           topic = _ref[_i];
631           topics.push(Kii.topicWithName(topic.topicID));
632         }
633         return callbacks != null ? callbacks.success(topics, (json.paginationKey === void 0 ? null : json.paginationKey)) : void 0;
634       },
635       failure: function() {
636         var errObj, errString;
637         errString = wrapper.getErrorString("list topics");
638         errObj = KiiUtilities._Error(errString, Kii);
639         return callbacks != null ? callbacks.failure(errObj) : void 0;
640       }
641     };
642     return wrapper.send(listCallbacks);
643   };
644 
645 
646   /** Authenticate as Thing.
647   <br><br>
648   <b>This api is intended to be used in a Thing device, where the user
649   credentials or app admin context is not configured. This Thing must be
650   already registered in Kii Cloud.
651   </b>
652   @param {String} vendorThingID vendorThingID of a registered Thing.
653   @param {String} password password for the registered Thing.
654   @param {Object} [callbacks] The callback methods called when authentication succeeded/failed.
655   @param {Method} callbacks.success The callback method called when authentication succeeded.
656   @param {Method} callbacks.failure The callback method called when authentication failed.
657   @return {Promise} return promise object.
658       <ul>
659         <li>fulfill callback function: function(thingAuthContext). thingAuthContext is a KiiThingContext instance.</li>
660         <li>reject callback function: function(error). error is an Error instance.
661           <ul>
662             <li>error.message</li>
663           </ul>
664         </li>
665       </ul>
666   @example
667   // example to use callbacks directly
668   Kii.authenticateAsThing("vendor thing id", "password of this thing", {
669       success: function(thingAuthContext) {
670           // thingAuthContext : KiiThingContext instance
671           // Operate entities with thingAuthContext.
672       },
673       failure: function(error) {
674           // Authentication failed.
675       }
676   );
677   
678   // example to use Promise
679   Kii.authenticateAsThing("vendor thing id", "password of this thing").then(
680       function(thingAuthContext) { // fulfill callback function
681           // thingAuthContext : KiiThingContext instance
682           // Operate entities with thingAuthContext.
683   
684       },
685       function(error) { // reject callback function
686           // Authentication failed.
687           var errorString = error.message;
688       }
689   );
690    */
691 
692   Kii.authenticateAsThing = function(vendorThingID, password, callbacks) {
693     return new Promise((function(_this) {
694       return function(resolve, reject) {
695         var errObj, sendCallbacks, wrapper;
696         if (!KiiUtilities._isNonEmptyString(vendorThingID) || !KiiUtilities._isNonEmptyString(password)) {
697           errObj = KiiUtilities._Error("vendorThingID or password is invalid");
698           if (callbacks != null) {
699             callbacks.failure(errObj);
700           }
701           reject(errObj);
702           return;
703         }
704         wrapper = KiiXHRWrapperFactory.createXHRWrapper('POST', "" + (root.Kii.getBaseURL()) + "/oauth2/token");
705         wrapper.setKiiHeaders();
706         wrapper.setContentType("application/vnd.kii.OauthTokenRequest+json");
707         sendCallbacks = {
708           success: function() {
709             var accessToken, errString, respJson, thingAuthContext, thingID;
710             respJson = JSON.parse(decodeURIComponent(wrapper.xhr.responseText));
711             thingID = respJson.id;
712             accessToken = respJson.access_token;
713             if ((thingID != null) && (accessToken != null)) {
714               thingAuthContext = new root.KiiThingContext({
715                 thingId: thingID,
716                 token: accessToken,
717                 vendorThingID: vendorThingID
718               });
719               if (callbacks != null) {
720                 callbacks.success(thingAuthContext);
721               }
722               return resolve(thingAuthContext);
723             } else {
724               errString = wrapper.getErrorString("invalid format response when authenticate thing ");
725               errObj = KiiUtilities._Error(errString);
726               if (callbacks != null) {
727                 callbacks.failure(errObj);
728               }
729               return reject(errObj);
730             }
731           },
732           failure: function() {
733             var errString;
734             errString = wrapper.getErrorString("authenticate as thing");
735             errObj = KiiUtilities._Error(errString);
736             if (callbacks != null) {
737               callbacks.failure(errObj);
738             }
739             return reject(errObj);
740           }
741         };
742         return wrapper.sendData(JSON.stringify({
743           username: "VENDOR_THING_ID:" + vendorThingID,
744           password: password
745         }), sendCallbacks);
746       };
747     })(this));
748   };
749 
750 
751   /** Create a KiiThingContext reference
752   <br><br>
753   <b>This api is intended to be used in a Thing device, where the user
754   credentials or app admin context is not configured. This Thing must be
755   already registered in Kii Cloud.
756   </b>
757   @param {String} thingID thingID of a registered Thing.
758   @param {String} token token for the registered Thing.
759   @param {Object} [callbacks] The callback methods called when creation succeeded/failed.
760   @param {Method} callbacks.success The callback method called when creation succeeded.
761   @param {Method} callbacks.failure The callback method called when creation failed.
762   @return {Promise} return promise object.
763       <ul>
764         <li>fulfill callback function: function(thingContext). thingContext is a KiiThingContext instance.</li>
765         <li>reject callback function: function(error). error is an Error instance.
766           <ul>
767             <li>error.message</li>
768           </ul>
769         </li>
770       </ul>
771   @example
772   // example to use callbacks directly
773   Kii.authenticateAsThingWithToken("thing_id", "thing_token", {
774       success: function(thingContext) {
775           // thingContext : KiiThingContext instance
776           // Operate entities with thingContext.
777       },
778       failure: function(error) {
779           // Creation failed.
780       }
781   );
782   
783   // example to use Promise
784   Kii.authenticateAsThingWithToken("thing_id", "thing_token").then(
785       function(thingContext) { // fulfill callback function
786           // thingContext : KiiThingContext instance
787           // Operate entities with thingContext.
788   
789       },
790       function(error) { // reject callback function
791           // Creation failed.
792           var errorString = error.message;
793       }
794   );
795    */
796 
797   Kii.authenticateAsThingWithToken = function(thingID, token, callbacks) {
798     return new Promise((function(_this) {
799       return function(resolve, reject) {
800         var errObj, thingAuthContext;
801         if (!KiiUtilities._isNonEmptyString(thingID) || !KiiUtilities._isNonEmptyString(token)) {
802           errObj = KiiUtilities._Error("thingID or token is invalid");
803           if (callbacks != null) {
804             callbacks.failure(errObj);
805           }
806           return reject(errObj);
807         } else {
808           thingAuthContext = new root.KiiThingContext({
809             thingId: thingID,
810             token: token
811           });
812           if (callbacks != null) {
813             callbacks.success(thingAuthContext);
814           }
815           return resolve(thingAuthContext);
816         }
817       };
818     })(this));
819   };
820 
821   return Kii;
822 
823 })();
824 
825 root._KiiHttpRequestType = {
826   jQuery: "jQuery",
827   XMLHttpRequest: "XMLHttpRequest",
828   Titanium: "Titanium"
829 };
830 
831 _Kii = (function() {
832   _Kii.prototype._logging = false;
833 
834   _Kii.prototype._baseURL = null;
835 
836   _Kii.prototype._currentUser = null;
837 
838   _Kii.prototype._httpRequestType = null;
839 
840   function _Kii(appID, appKey, site) {
841     this._appKey = appKey;
842     this._appID = appID;
843     this._baseURL = site;
844     this._expiresIn = 0;
845   }
846 
847   return _Kii;
848 
849 })();
850 
851 
852 /**
853     @class Represents a KiiACL object
854     @exports root.KiiACL as KiiACL
855  */
856 
857 root.KiiACL = (function() {
858   function KiiACL() {
859     this._thingWithID = __bind(this._thingWithID, this);
860     this._userWithID = __bind(this._userWithID, this);
861     this._groupWithID = __bind(this._groupWithID, this);
862     this._getRequest = __bind(this._getRequest, this);
863     this._saveItr = __bind(this._saveItr, this);
864     this._saveUsingCallbacks = __bind(this._saveUsingCallbacks, this);
865     this.save = __bind(this.save, this);
866     this._getKeyOfEntry = __bind(this._getKeyOfEntry, this);
867     this.removeACLEntry = __bind(this.removeACLEntry, this);
868     this.putACLEntry = __bind(this.putACLEntry, this);
869     this._listACLEntriesUsingCallbacks = __bind(this._listACLEntriesUsingCallbacks, this);
870     this.listACLEntries = __bind(this.listACLEntries, this);
871     this.aclPath = __bind(this.aclPath, this);
872     this._setParent = __bind(this._setParent, this);
873     this._entriesMap = {};
874   }
875 
876   KiiACL.prototype._setParent = function(_parent) {
877     this._parent = _parent;
878   };
879 
880   KiiACL.prototype.aclPath = function() {
881     var bucket, bucketName, group, object, objectId, path, stringToRemove, thing, topic, user;
882     if (this._parent instanceof root.KiiObject) {
883       object = this._parent;
884       if (object.getBucket().getUser() != null) {
885         user = object.getBucket().getUser();
886       } else if (object.getBucket().getGroup() != null) {
887         group = object.getBucket().getGroup();
888       } else if (object.getBucket().getThing() != null) {
889         thing = object.getBucket().getThing();
890       }
891       bucketName = object.getBucket()._getQualifiedBucketName();
892       objectId = object.getUUID();
893     } else if (this._parent instanceof root.KiiBucket) {
894       bucket = this._parent;
895       if (bucket.getUser() != null) {
896         user = bucket.getUser();
897       } else if (bucket.getGroup() != null) {
898         group = bucket.getGroup();
899       } else if (bucket.getThing() != null) {
900         thing = bucket.getThing();
901       }
902       bucketName = bucket._getQualifiedBucketName();
903     } else if (this._parent instanceof root.KiiTopic) {
904       topic = this._parent;
905     } else {
906       root.Kii.logger("Invalid ACL parent. Must belong to a KiiObject");
907     }
908     path = "/";
909     if (group != null) {
910       path += "groups/" + (group.getUUID()) + "/";
911     } else if (user != null) {
912       path += "users/" + (user.getUUID()) + "/";
913     } else if (thing != null) {
914       path += "things/" + (thing.getThingID()) + "/";
915     }
916     if (topic) {
917       stringToRemove = "" + (root.Kii.getBaseURL()) + "/apps/" + (root.Kii.getAppID()) + "/";
918       if (topic._uri.indexOf(stringToRemove) !== 0) {
919         path = null;
920       } else {
921         path += topic._uri.substr(stringToRemove.length) + "/acl";
922       }
923     } else {
924       if (objectId != null) {
925         path += "buckets/" + bucketName + "/objects/" + objectId + "/acl";
926       } else {
927         path += "buckets/" + bucketName + "/acl";
928       }
929     }
930     return path;
931   };
932 
933 
934   /** Get the list of active ACLs associated with this object from the server
935   @param {Object} [callbacks] An object with callback methods defined
936   @param {Method} callbacks.success The callback method to call on a successful list request
937   @param {Method} callbacks.failure The callback method to call on a failed list request
938   @return {Promise} return promise object.
939       <ul>
940         <li>fulfill callback function: function(params). params is Array instance.
941           <ul>
942             <li>params[0] is the KiiACL instance which this method was called on.</li>
943             <li>params[1] is array of KiiACLEntry instances.</li>
944           </ul>
945         </li>
946         <li>reject callback function: function(error). error is an Error instance.
947           <ul>
948             <li>error.target is the KiiACL instance which this method was called on.</li>
949             <li>error.message</li>
950           </ul>
951         </li>
952       </ul>
953   @example
954   // example to use callbacks directly
955   var acl = . . .; // a KiiACL object
956   acl.listACLEntries({
957   	success: function(theACL, theEntries) {
958   		// do something
959   	},
960   
961   	failure: function(theACL, anErrorString) {
962   		// do something with the error response
963   	}
964   });
965   
966   // example to use Promise
967   var acl = . . .; // a KiiACL object
968   acl.listACLEntries().then(
969       function(params) { // fulfill callback function
970           var theACL = params[0];
971           var theEntries = params[1];
972           // do something
973       },
974       function(error) { // reject callback function
975           var theACL = error.target;
976           var anErrorString = error.message;
977       		// do something with the error response
978   });
979    */
980 
981   KiiACL.prototype.listACLEntries = function(callbacks) {
982     return new Promise((function(_this) {
983       return function(resolve, reject) {
984         var listACLEntriesCallbacks;
985         listACLEntriesCallbacks = {
986           success: function() {
987             if (callbacks != null) {
988               callbacks.success.apply(callbacks, arguments);
989             }
990             return resolve(arguments);
991           },
992           failure: function() {
993             if (callbacks != null) {
994               callbacks.failure.apply(callbacks, arguments);
995             }
996             return reject(KiiUtilities._Error(arguments[1], _this));
997           }
998         };
999         return _this._listACLEntriesUsingCallbacks(listACLEntriesCallbacks);
1000       };
1001     })(this));
1002   };
1003 
1004   KiiACL.prototype._listACLEntriesUsingCallbacks = function(callbacks) {
1005     var listCallbacks, request;
1006     root.Kii.logger("Listing ACL entries");
1007     request = this._getRequest({
1008       path: this.aclPath(),
1009       withApp: true
1010     });
1011     listCallbacks = {
1012       success: (function(_this) {
1013         return function(data, statusCode) {
1014           var action, entity, key, results, subject, value, _i, _len;
1015           if (statusCode < 300 && statusCode >= 200) {
1016             results = [];
1017             for (key in data) {
1018               value = data[key];
1019               if (key === "WRITE_EXISTING_OBJECT") {
1020                 action = root.KiiACLAction.KiiACLObjectActionWrite;
1021               } else if (key === "READ_EXISTING_OBJECT") {
1022                 action = root.KiiACLAction.KiiACLObjectActionRead;
1023               } else if (key === "QUERY_OBJECTS_IN_BUCKET") {
1024                 action = root.KiiACLAction.KiiACLBucketActionQueryObjects;
1025               } else if (key === "CREATE_OBJECTS_IN_BUCKET") {
1026                 action = root.KiiACLAction.KiiACLBucketActionCreateObjects;
1027               } else if (key === "DROP_BUCKET_WITH_ALL_CONTENT") {
1028                 action = root.KiiACLAction.KiiACLBucketActionDropBucket;
1029               } else if (key === "READ_OBJECTS_IN_BUCKET") {
1030                 action = root.KiiACLAction.KiiACLBucketActionReadObjects;
1031               } else if (key === "SUBSCRIBE_TO_TOPIC") {
1032                 action = root.KiiACLAction.KiiACLSubscribeToTopic;
1033               } else if (key === "SEND_MESSAGE_TO_TOPIC") {
1034                 action = root.KiiACLAction.KiiACLSendMessageToTopic;
1035               } else {
1036                 continue;
1037               }
1038               for (_i = 0, _len = value.length; _i < _len; _i++) {
1039                 entity = value[_i];
1040                 if (entity.groupID != null) {
1041                   subject = _this._groupWithID(entity.groupID);
1042                 } else if (entity.userID != null) {
1043                   subject = _this._userWithID(entity.userID);
1044                 } else if (entity.thingID != null) {
1045                   subject = _this._thingWithID(entity.thingID);
1046                 } else {
1047                   continue;
1048                 }
1049                 results.push(root.KiiACLEntry.entryWithSubject(subject, action));
1050               }
1051             }
1052             return callbacks.success(_this, results);
1053           } else {
1054             return callbacks.failure(_this, "Unable to retrieve ACL list");
1055           }
1056         };
1057       })(this),
1058       failure: (function(_this) {
1059         return function(error, statusCode) {
1060           return callbacks.failure(_this, error);
1061         };
1062       })(this)
1063     };
1064     return request.execute(listCallbacks, false);
1065   };
1066 
1067 
1068   /** Add a KiiACLEntry to the local object, if not already present. This does not explicitly grant any permissions, which should be done through the KiiACLEntry itself. This method simply adds the entry to the local ACL object so it can be saved to the server.
1069   @param {KiiACLEntry} entry The KiiACLEntry to add
1070   @throws {InvalidArgumentException} If specified entry is not an instance of KiiACLEntry.
1071   @example
1072   var aclEntry = . . .; // a KiiACLEntry object
1073   var acl = . . .; // a KiiACL object
1074   acl.putACLEntry(aclEntry);
1075    */
1076 
1077   KiiACL.prototype.putACLEntry = function(entry) {
1078     var key;
1079     if (!(entry instanceof root.KiiACLEntry)) {
1080       throw new root.InvalidArgumentException('invalid entry');
1081     }
1082     key = this._getKeyOfEntry(entry);
1083     return this._entriesMap[key] = entry;
1084   };
1085 
1086 
1087   /** Remove a KiiACLEntry to the local object. This does not explicitly revoke any permissions, which should be done through the KiiACLEntry itself. This method simply removes the entry from the local ACL object and will not be saved to the server.
1088   @param {KiiACLEntry} entry The KiiACLEntry to remove
1089   @throws {InvalidArgumentException} If specified entry is not an instance of KiiACLEntry.
1090   @example
1091   var aclEntry = . . .; // a KiiACLEntry object
1092   var acl = . . .; // a KiiACL object
1093   acl.removeACLEntry(aclEntry);
1094    */
1095 
1096   KiiACL.prototype.removeACLEntry = function(entry) {
1097     var key;
1098     if (!(entry instanceof root.KiiACLEntry)) {
1099       throw new root.InvalidArgumentException('invalid entry');
1100     }
1101     key = this._getKeyOfEntry(entry);
1102     return delete this._entriesMap[key];
1103   };
1104 
1105   KiiACL.prototype._getKeyOfEntry = function(entry) {
1106     var key1, key2, key3;
1107     key1 = entry.getActionString();
1108     key2 = entry.getEntityString();
1109     key3 = entry.getGrant();
1110     return "" + key1 + "/" + key2 + ":" + key3;
1111   };
1112 
1113 
1114   /** Save the list of ACLEntry objects associated with this ACL object to the server
1115   @param {Object} [callbacks] An object with callback methods defined
1116   @param {Method} callbacks.success The callback method to call on a successful save request
1117   @param {Method} callbacks.failure The callback method to call on a failed save request
1118   @return {Promise} return promise object.
1119       <ul>
1120         <li>fulfill callback function: function(theSavedACL). theSavedACL is KiiACL instance.</li>
1121         <li>reject callback function: function(error). error is an Error instance.
1122           <ul>
1123             <li>error.target is the KiiACL instance which this method was called on.</li>
1124             <li>error.message</li>
1125           </ul>
1126         </li>
1127       </ul>
1128   @example
1129   // example to use callbacks directly
1130   var acl = . . .; // a KiiACL object
1131   acl.save({
1132       success: function(theSavedACL) {
1133           // do something with the saved acl
1134       },
1135   
1136       failure: function(theACL, anErrorString) {
1137           // do something with the error response
1138       }
1139   });
1140   
1141   // example to use Promise
1142   var acl = . . .; // a KiiACL object
1143   acl.save().then(
1144       function(theSavedACL) { // fulfill callback function
1145           // do something with the saved acl
1146       },
1147       function(error) { // reject callback function
1148           var theACL = error.target;
1149           var anErrorString = error.message;
1150           // do something with the error response
1151   });
1152    */
1153 
1154   KiiACL.prototype.save = function(callbacks) {
1155     return new Promise((function(_this) {
1156       return function(resolve, reject) {
1157         var saveCallbacks;
1158         saveCallbacks = {
1159           success: function() {
1160             if (callbacks != null) {
1161               callbacks.success.apply(callbacks, arguments);
1162             }
1163             return resolve(arguments[0]);
1164           },
1165           failure: function() {
1166             if (callbacks != null) {
1167               callbacks.failure.apply(callbacks, arguments);
1168             }
1169             return reject(KiiUtilities._Error(arguments[1], _this));
1170           }
1171         };
1172         return _this._saveUsingCallbacks(saveCallbacks);
1173       };
1174     })(this));
1175   };
1176 
1177   KiiACL.prototype._saveUsingCallbacks = function(callbacks) {
1178     var keys;
1179     root.Kii.logger("SAving acl");
1180     if (!this._entriesMap) {
1181       callbacks.failure(this, "There is no entry to save.");
1182       return;
1183     }
1184     keys = Object.keys(this._entriesMap);
1185     root.Kii.logger("Saving total entries : " + keys.length);
1186     if (keys.length < 1) {
1187       callbacks.failure(this, "There is no entry to save.");
1188       return;
1189     }
1190     return this._saveItr(keys, 0, callbacks);
1191   };
1192 
1193   KiiACL.prototype._saveItr = function(keys, idx, callbacks) {
1194     var aclEntry, path, request, _errorStr;
1195     aclEntry = this._entriesMap[keys[idx]];
1196     path = "" + (this.aclPath()) + "/" + (aclEntry.getActionString()) + "/" + (aclEntry.getEntityString());
1197     root.Kii.logger("Saving single @path: " + path);
1198     root.Kii.logger("Saving  entries index : " + idx);
1199     request = this._getRequest({
1200       path: path,
1201       withApp: true
1202     });
1203     request.setMethod(aclEntry.getGrant() === true ? "PUT" : "DELETE");
1204     _errorStr = null;
1205     return request.execute({
1206       success: (function(_this) {
1207         return function(data, status, xhr) {
1208           _this.removeACLEntry(aclEntry);
1209           if (idx < keys.length - 1) {
1210             return _this._saveItr(keys, idx + 1, callbacks);
1211           } else {
1212             return callbacks.success(_this);
1213           }
1214         };
1215       })(this),
1216       failure: (function(_this) {
1217         return function(errorStr, statusCode, errorCode) {
1218           return callbacks.failure(_this, errorStr);
1219         };
1220       })(this)
1221     }, false);
1222   };
1223 
1224   KiiACL.aclWithParent = function(parent) {
1225     var acl;
1226     acl = new root.KiiACL();
1227     acl._setParent(parent);
1228     return acl;
1229   };
1230 
1231   KiiACL.prototype._getRequest = function(spec) {
1232     var path, request, withApp;
1233     path = spec.path;
1234     withApp = spec.withApp;
1235     request = new KiiRequest(path, withApp);
1236     return request;
1237   };
1238 
1239   KiiACL.prototype._groupWithID = function(id) {
1240     var group;
1241     group = root.KiiGroup.groupWithID(id);
1242     return group;
1243   };
1244 
1245   KiiACL.prototype._userWithID = function(id) {
1246     if (id === 'ANONYMOUS_USER') {
1247       return new root.KiiAnonymousUser();
1248     } else if (id === 'ANY_AUTHENTICATED_USER') {
1249       return new root.KiiAnyAuthenticatedUser();
1250     } else {
1251       return root.KiiUser.userWithID(id);
1252     }
1253   };
1254 
1255   KiiACL.prototype._thingWithID = function(id) {
1256     return root.KiiThing.thingWithID(id);
1257   };
1258 
1259   return KiiACL;
1260 
1261 })();
1262 
1263 root.KiiACLAction = {
1264   KiiACLActionStart: -1,
1265   KiiACLBucketActionCreateObjects: 0,
1266   KiiACLBucketActionQueryObjects: 1,
1267   KiiACLBucketActionDropBucket: 2,
1268   KiiACLBucketActionReadObjects: 3,
1269   KiiACLObjectActionRead: 4,
1270   KiiACLObjectActionWrite: 5,
1271   KiiACLSubscribeToTopic: 6,
1272   KiiACLSendMessageToTopic: 7,
1273   KiiACLActionEnd: 8
1274 };
1275 
1276 
1277 /**
1278     @class Represents a KiiACLEntry object
1279     @exports root.KiiACLEntry as KiiACLEntry
1280  */
1281 
1282 root.KiiACLEntry = (function() {
1283   function KiiACLEntry() {
1284     this.getEntityString = __bind(this.getEntityString, this);
1285     this.getActionString = __bind(this.getActionString, this);
1286     this.getGrant = __bind(this.getGrant, this);
1287     this.setGrant = __bind(this.setGrant, this);
1288     this.getSubject = __bind(this.getSubject, this);
1289     this.setSubject = __bind(this.setSubject, this);
1290     this.getAction = __bind(this.getAction, this);
1291     this.setAction = __bind(this.setAction, this);
1292     this._action = -1;
1293     this._grant = true;
1294   }
1295 
1296 
1297   /** The action that is being permitted/restricted. Possible values:
1298   <br><br>
1299   KiiACLAction.KiiACLBucketActionCreateObjects,<br>
1300   KiiACLAction.KiiACLBucketActionQueryObjects,  <br>
1301   KiiACLAction.KiiACLBucketActionDropBucket,<br>
1302   KiiACLAction.KiiACLBucketActionReadObjects,<br>
1303   KiiACLAction.KiiACLObjectActionRead,<br>
1304   KiiACLAction.KiiACLObjectActionWrite,<br>
1305   KiiACLAction.KiiACLSubscribeToTopic,<br>
1306   KiiACLAction.KiiACLSendMessageToTopic
1307   
1308   @param {KiiACLAction} value The action being permitted/restricted
1309   @throws {InvalidACLAction} If the value is not one of the permitted values
1310    */
1311 
1312   KiiACLEntry.prototype.setAction = function(value) {
1313     if (value > root.KiiACLAction.KiiACLActionStart && value < root.KiiACLAction.KiiACLActionEnd) {
1314       return this._action = value;
1315     } else {
1316       throw new root.InvalidACLAction;
1317     }
1318   };
1319 
1320 
1321   /** Get the action that is being permitted/restricted in this entry
1322   @returns {KiiACLAction}
1323    */
1324 
1325   KiiACLEntry.prototype.getAction = function() {
1326     return this._action;
1327   };
1328 
1329 
1330   /** Set the subject to which the action/grant is being applied
1331   @param {KiiGroup|KiiUser|KiiAnyAuthenticatedUser|KiiAnonymousUser|KiiThing} subject instance.
1332   @throws {InvalidACLSubject} If the value is not one of the permitted values
1333    */
1334 
1335   KiiACLEntry.prototype.setSubject = function(value) {
1336     if ((value instanceof root.KiiGroup && (value.getID() != null)) || (value instanceof root.KiiUser && (value.getID() != null)) || value instanceof root.KiiAnyAuthenticatedUser || value instanceof root.KiiAnonymousUser || (value instanceof root.KiiThing && (value.getThingID() != null))) {
1337       return this._subject = value;
1338     } else {
1339       throw new root.InvalidACLSubject;
1340     }
1341   };
1342 
1343 
1344   /** Get the subject that is being permitted/restricted in this entry
1345   @returns {KiiUser|KiiGroup|KiiThing}
1346    */
1347 
1348   KiiACLEntry.prototype.getSubject = function() {
1349     return this._subject;
1350   };
1351 
1352 
1353   /** Set whether or not the action is being permitted to the subject
1354   @param {Boolean} value true if the action is permitted, false otherwise
1355   @throws {InvalidACLGrant} If the value is not a boolean type
1356    */
1357 
1358   KiiACLEntry.prototype.setGrant = function(value) {
1359     if (value === true || value === false) {
1360       return this._grant = value;
1361     } else {
1362       throw new root.InvalidACLGrant;
1363     }
1364   };
1365 
1366 
1367   /** Get whether or not the action is being permitted to the subject
1368   @returns {Boolean}
1369    */
1370 
1371   KiiACLEntry.prototype.getGrant = function() {
1372     return this._grant;
1373   };
1374 
1375 
1376   /** Create a KiiACLEntry object with a subject and action
1377   
1378   The entry will not be applied on the server until the KiiACL object is
1379   explicitly saved. This method simply returns a working KiiACLEntry with
1380   a specified subject and action.
1381   @param {KiiGroup|KiiUser|KiiAnyAuthenticatedUser|KiiAnonymousUser|KiiThing} Subject
1382   to which the action/grant is being applied
1383   @param {KiiACLAction} action One of the specified KiiACLAction values the
1384   permissions is being applied to
1385   @return A KiiACLEntry object with the specified attributes
1386   @throws {InvalidACLSubject} If specified subject is invalid.
1387   @throws {InvalidACLAction} If the specified action is invalid.
1388    */
1389 
1390   KiiACLEntry.entryWithSubject = function(subject, action) {
1391     var entry;
1392     root.Kii.logger("EWS: " + subject + ", " + action);
1393     entry = new root.KiiACLEntry();
1394     entry.setSubject(subject);
1395     entry.setAction(action);
1396     return entry;
1397   };
1398 
1399   KiiACLEntry.prototype.getActionString = function() {
1400     var retString;
1401     root.Kii.logger("Action: " + this.action);
1402     switch (this._action) {
1403       case root.KiiACLAction.KiiACLBucketActionCreateObjects:
1404         retString = "CREATE_OBJECTS_IN_BUCKET";
1405         break;
1406       case root.KiiACLAction.KiiACLBucketActionQueryObjects:
1407         retString = "QUERY_OBJECTS_IN_BUCKET";
1408         break;
1409       case root.KiiACLAction.KiiACLBucketActionDropBucket:
1410         retString = "DROP_BUCKET_WITH_ALL_CONTENT";
1411         break;
1412       case root.KiiACLAction.KiiACLBucketActionReadObjects:
1413         retString = "READ_OBJECTS_IN_BUCKET";
1414         break;
1415       case root.KiiACLAction.KiiACLObjectActionRead:
1416         retString = "READ_EXISTING_OBJECT";
1417         break;
1418       case root.KiiACLAction.KiiACLObjectActionWrite:
1419         retString = "WRITE_EXISTING_OBJECT";
1420         break;
1421       case root.KiiACLAction.KiiACLSubscribeToTopic:
1422         retString = "SUBSCRIBE_TO_TOPIC";
1423         break;
1424       case root.KiiACLAction.KiiACLSendMessageToTopic:
1425         retString = "SEND_MESSAGE_TO_TOPIC";
1426         break;
1427       default:
1428         return retString;
1429     }
1430     return retString;
1431   };
1432 
1433   KiiACLEntry.prototype.getEntityString = function() {
1434     var entityId, type;
1435     if (this._subject instanceof root.KiiGroup) {
1436       entityId = this._subject.getUUID();
1437       type = "GroupID";
1438     } else if (this._subject instanceof root.KiiUser) {
1439       entityId = this._subject.getUUID();
1440       type = "UserID";
1441     } else if (this._subject instanceof root.KiiAnyAuthenticatedUser) {
1442       type = "UserID";
1443       entityId = "ANY_AUTHENTICATED_USER";
1444     } else if (this._subject instanceof root.KiiAnonymousUser) {
1445       type = "UserID";
1446       entityId = "ANONYMOUS_USER";
1447     } else if (this._subject instanceof root.KiiThing) {
1448       type = "ThingID";
1449       entityId = this._subject.getThingID();
1450     }
1451     return "" + type + ":" + entityId;
1452   };
1453 
1454   return KiiACLEntry;
1455 
1456 })();
1457 
1458 
1459 /**
1460     @class Represents a KiiBucket object
1461     @exports root.KiiBucket as KiiBucket
1462  */
1463 
1464 root.KiiBucket = (function() {
1465   KiiBucket.prototype._className = "KiiBucket";
1466 
1467   KiiBucket.prototype.getUser = function() {
1468     return this._user;
1469   };
1470 
1471   KiiBucket.prototype.getGroup = function() {
1472     return this._group;
1473   };
1474 
1475   KiiBucket.prototype.getThing = function() {
1476     return this._thing;
1477   };
1478 
1479 
1480   /** The name of this bucket
1481   @returns {String}
1482    */
1483 
1484   KiiBucket.prototype.getBucketName = function() {
1485     return this._bucketName;
1486   };
1487 
1488   KiiBucket.prototype._setBucketName = function(_bucketName) {
1489     this._bucketName = _bucketName;
1490   };
1491 
1492   KiiBucket.prototype._getQualifiedBucketName = function() {
1493     return this._bucketName;
1494   };
1495 
1496 
1497   /** Create a KiiObject within the current bucket
1498   
1499   <br><br>The object will not be created on the server until the KiiObject is explicitly saved. This method simply returns an empty working KiiObject.
1500   @returns {KiiObject} An empty KiiObject with no specific type
1501   @example
1502   var bucket = . . .; // a KiiBucket
1503   var object = bucket.createObject();
1504    */
1505 
1506   KiiBucket.prototype.createObject = function() {
1507     return root.KiiObject.objectWithBucket(this, null);
1508   };
1509 
1510 
1511   /** Create a KiiObject within the current bucket, with type
1512   
1513   <br><br>The object will not be created on the server until the KiiObject is explicitly saved. This method simply returns an empty working KiiObject with a specified type. The type allows for better indexing and improved query results. It is recommended to use this method - but for lazy creation, the createObject method is also available.
1514   @param String type A string representing the desired object type
1515   @returns An empty KiiObject with specified type
1516   @example
1517   var bucket = . . .; // a KiiBucket
1518   var object = bucket.createObjectWithType("scores");
1519    */
1520 
1521   KiiBucket.prototype.createObjectWithType = function(type) {
1522     return root.KiiObject.objectWithBucket(this, type);
1523   };
1524 
1525 
1526   /** Create a KiiObject within the current bucket, specifying its ID.
1527   
1528   <br><br> If the object has not exist on KiiCloud, {@link KiiObject#saveAllFields(callback)}
1529     will create new Object which has ID specified in the argument.
1530     If the object exist in KiiCloud, references the existing object which has
1531     specified ID. use {@link KiiObject#refresh(callback)} to retrieve the contents of
1532     KiiObject.
1533    @param String objectID ID of the obeject you want to instantiate.
1534    @returns {KiiObject} KiiObject instance.
1535    @throws {InvalidArgumentException} objectID is not acceptable.
1536    Refer to {@link KiiObject.isValidObjectID(string)} for details of acceptable string.
1537    @example
1538    var bucket = . . .; // KiiBucket
1539    var object = bucket.createObjectWithID('__OBJECT_ID_');
1540    */
1541 
1542   KiiBucket.prototype.createObjectWithID = function(objectID) {
1543     if (!root.KiiObject.isValidObjectID(objectID)) {
1544       throw root.InvalidArgumentException('Specified obejctID is invalid.');
1545     }
1546     return root.KiiObject.objectWithID(this, objectID);
1547   };
1548 
1549 
1550   /** Get the ACL handle for this bucket
1551   
1552   <br><br>Any KiiACLEntry objects added or revoked from this ACL object will be appended to/removed from the server on ACL save.
1553   	@returns {KiiACL} A KiiACL object associated with this KiiObject
1554   	@example
1555   	var bucket = . . .; // a KiiBucket
1556   	var acl = bucket.acl();
1557    */
1558 
1559   KiiBucket.prototype.acl = function() {
1560     return root.KiiACL.aclWithParent(this);
1561   };
1562 
1563 
1564   /** Perform a query on the given bucket
1565   
1566   <br><br>The query will be executed against the server, returning a result set.
1567   @param KiiQuery query An object with callback methods defined
1568   @param Object callbacks An object with callback methods defined
1569   @param {Method} callbacks.success The callback method to call on a successful query request
1570   @param {Method} callbacks.failure The callback method to call on a failed query request
1571   @return {Promise} return promise object.
1572     <ul>
1573       <li>fulfill callback function: function(params). params is Array instance.
1574         <ul>
1575           <li>params[0] is a performed KiiQuery instance.</li>
1576           <li>params[1] is resultSet Array instance. Could be KiiObject, KiiGroup, KiiUser, etc.</li>
1577           <li>params[2] is a KiiQuery instance for next query. If there are no more results to be retrieved, it will be null.</li>
1578         </ul>
1579       </li>
1580       <li>reject callback function: function(error). error is an Error instance.
1581         <ul>
1582           <li>error.target is the KiiBucket instance which this method was called on.</li>
1583           <li>error.message</li>
1584         </ul>
1585       </li>
1586     </ul>
1587   @example
1588   // example to use callbacks directly
1589   var bucket = . . .; // a KiiBucket
1590   var queryObject = . . .; // a KiiQuery
1591   
1592   // define the callbacks (stored in a variable for reusability)
1593   var queryCallbacks = {
1594       success: function(queryPerformed, resultSet, nextQuery) {
1595           // do something with the results
1596           for(var i=0; i<resultSet.length; i++) {
1597               // do something with the object
1598               // resultSet[i]; // could be KiiObject, KiiGroup, KiiUser, etc
1599           }
1600   
1601           // if there are more results to be retrieved
1602           if(nextQuery != null) {
1603   
1604               // get them and repeat recursively until no results remain
1605               bucket.executeQuery(nextQuery, queryCallbacks);
1606           }
1607       },
1608   
1609       failure: function(bucket, anErrorString) {
1610           // do something with the error response
1611       }
1612   };
1613   bucket.executeQuery(queryObject, queryCallbacks);
1614   
1615   // example to use Promise
1616   var bucket = . . .; // a KiiBucket
1617   var queryObject = . . .; // a KiiQuery
1618   bucket.executeQuery(queryObject).then(
1619       function(params) {
1620           var queryPerformed = params[0];
1621           var resultSet = params[1];
1622           var nextQuery = params[2];
1623           // do something with the results
1624           for(var i=0; i<resultSet.length; i++) {
1625               // do something with the object
1626               // resultSet[i]; // could be KiiObject, KiiGroup, KiiUser, etc
1627           }
1628   
1629           // if there are more results to be retrieved
1630           if(nextQuery != null) {
1631   
1632               // get them and repeat recursively until no results remain
1633               bucket.executeQuery(nextQuery).then(
1634                   function(params) {
1635                       // next query success
1636                   },
1637                   function(error) {
1638                       // next query failed, please handle the error
1639                   }
1640               );
1641           }
1642   
1643       },
1644       function(error) {
1645           // do something with the error response
1646       }
1647   );
1648    */
1649 
1650   KiiBucket.prototype.executeQuery = function(query, callbacks) {
1651     return new Promise((function(_this) {
1652       return function(resolve, reject) {
1653         var executeQueryCallbacks;
1654         executeQueryCallbacks = {
1655           success: function() {
1656             if (callbacks != null) {
1657               callbacks.success.apply(callbacks, arguments);
1658             }
1659             return resolve(arguments);
1660           },
1661           failure: function() {
1662             if (callbacks != null) {
1663               callbacks.failure.apply(callbacks, arguments);
1664             }
1665             return reject(KiiUtilities._Error(arguments[1], _this));
1666           }
1667         };
1668         return _this._executeQueryUsingCallbacks(query, executeQueryCallbacks);
1669       };
1670     })(this));
1671   };
1672 
1673   KiiBucket.prototype._executeQueryUsingCallbacks = function(query, callbacks) {
1674     var data, error, executeCallbacks, path, request;
1675     try {
1676       path = this._generatePath() + "/query";
1677       data = {};
1678       if (query != null) {
1679         data = query._dictValue();
1680       } else {
1681         data.bucketQuery = {
1682           "clause": root.KiiQuery._emptyDictValue()
1683         };
1684       }
1685       request = this._getRequest({
1686         path: path,
1687         withApp: true
1688       });
1689       request.setMethod("POST");
1690       request.setContentType("application/vnd.kii.QueryRequest+json");
1691       request.setData(data);
1692       executeCallbacks = {
1693         success: (function(_this) {
1694           return function(data, statusCode) {
1695             var nextQuery, result, resultSet, _i, _len, _ref;
1696             if (statusCode < 300 && statusCode >= 200) {
1697               resultSet = [];
1698               _ref = data.results;
1699               for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1700                 result = _ref[_i];
1701                 resultSet.push(_this.objectWithJSON(result));
1702               }
1703               if (data.nextPaginationKey != null) {
1704                 nextQuery = new root.KiiQuery(query);
1705                 nextQuery.setPaginationKey(data.nextPaginationKey);
1706               } else {
1707                 nextQuery = null;
1708               }
1709               if (callbacks != null) {
1710                 return callbacks.success(query, resultSet, nextQuery);
1711               }
1712             } else if (callbacks != null) {
1713               return callbacks.failure(_this, "Unable to parse response");
1714             }
1715           };
1716         })(this),
1717         failure: (function(_this) {
1718           return function(error, statusCode) {
1719             if (callbacks != null) {
1720               return callbacks.failure(_this, error);
1721             }
1722           };
1723         })(this)
1724       };
1725       return request.execute(executeCallbacks, false);
1726     } catch (_error) {
1727       error = _error;
1728       return callbacks.failure(this, error);
1729     }
1730   };
1731 
1732 
1733   /** Execute count aggregation of specified query on current bucket.
1734   Query that passed as nextQuery in success callback of {@link #executeQuery}, is not
1735   supported, callbacks.failure will be fired in this case.
1736   
1737   @param {KiiQuery} query to be executed. If null, the operation will be same as {@link #count}.
1738   @param {Object} [callbacks] An object with callback methods defined.
1739   @param {Method} callbacks.success The callback method to call on a successful query request.
1740   @param {Method} callbacks.failure The callback method to call on a failed query request.
1741   @return {Promise} return promise object.
1742     <ul>
1743       <li>fulfill callback function: function(params). params is Array instance.
1744         <ul>
1745           <li>params[0] is a KiiBucket instance which this method was called on.</li>
1746           <li>params[1] is a KiiQuery instance.</li>
1747           <li>params[2] is an integer count result. </li>
1748         </ul>
1749       </li>
1750       <li>reject callback function: function(error). error is an Error instance.
1751         <ul>
1752           <li>error.target is the KiiBucket instance which this method was called on.</li>
1753           <li>error.message</li>
1754         </ul>
1755       </li>
1756     </ul>
1757   @example
1758   // example to use callbacks directly
1759   var bucket = . . .; // a KiiBucket
1760   var queryObject = . . .; // a KiiQuery
1761   
1762   // define the callbacks
1763   var callbacks = {
1764       success: function(bucket, query, count) {
1765           // do something with the results
1766       },
1767   
1768       failure: function(bucket, errorString) {
1769           // error happened.
1770       }
1771   };
1772   
1773   bucket.countWithQuery(queryObject, callbacks);
1774   
1775   // example to use Promise
1776   var bucket = . . .; // a KiiBucket
1777   var queryObject = . . .; // a KiiQuery
1778   
1779   bucket.countWithQuery(queryObject, callbacks).then(
1780       function(params) {
1781           var bucket = params[0];
1782           var query = params[1];
1783           var count = params[2];
1784           // do something with the results
1785       },
1786       function(error) {
1787           var bucket = error.target;
1788           var errorString = error.message;
1789           // error happened.
1790       }
1791   );
1792    */
1793 
1794   KiiBucket.prototype.countWithQuery = function(query, callbacks) {
1795     return new Promise((function(_this) {
1796       return function(resolve, reject) {
1797         var countWithQueryCallbacks;
1798         countWithQueryCallbacks = {
1799           success: function() {
1800             if (callbacks != null) {
1801               callbacks.success.apply(callbacks, arguments);
1802             }
1803             return resolve(arguments);
1804           },
1805           failure: function() {
1806             if (callbacks != null) {
1807               callbacks.failure.apply(callbacks, arguments);
1808             }
1809             return reject(KiiUtilities._Error(arguments[1], _this));
1810           }
1811         };
1812         return _this._countWithQueryUsingCallbacks(query, countWithQueryCallbacks);
1813       };
1814     })(this));
1815   };
1816 
1817   KiiBucket.prototype._countWithQueryUsingCallbacks = function(query, callbacks) {
1818     var data, executeCallbacks, path, request;
1819     path = this._generatePath() + "/query";
1820     data = {};
1821     if (query != null) {
1822       data = query._dictValue();
1823     } else {
1824       data.bucketQuery = {
1825         "clause": root.KiiQuery._emptyDictValue()
1826       };
1827       query = root.KiiQuery.queryWithClause();
1828     }
1829     data.bucketQuery.aggregations = [
1830       {
1831         "type": "COUNT",
1832         "putAggregationInto": "count_field"
1833       }
1834     ];
1835     request = this._getRequest({
1836       path: path,
1837       withApp: true
1838     });
1839     request.setMethod("POST");
1840     request.setContentType("application/vnd.kii.QueryRequest+json");
1841     request.setData(data);
1842     executeCallbacks = {
1843       success: (function(_this) {
1844         return function(data, statusCode) {
1845           var count;
1846           if (statusCode < 300 && statusCode >= 200) {
1847             count = data.aggregations.count_field;
1848             if (callbacks != null) {
1849               return callbacks.success(_this, query, count);
1850             }
1851           } else if (callbacks != null) {
1852             return callbacks.failure(_this, "Unable to parse response");
1853           }
1854         };
1855       })(this),
1856       failure: (function(_this) {
1857         return function(error, statusCode) {
1858           if (callbacks != null) {
1859             return callbacks.failure(_this, error);
1860           }
1861         };
1862       })(this)
1863     };
1864     return request.execute(executeCallbacks, false);
1865   };
1866 
1867 
1868   /** Execute count aggregation of all clause query on current bucket.
1869   @param {Object} [callbacks] An object with callback methods defined.
1870   @param {Method} callbacks.success The callback method to call on a successful query request.
1871   @param {Method} callbacks.failure The callback method to call on a failed query request.
1872   @return {Promise} return promise object.
1873     <ul>
1874       <li>fulfill callback function: function(params). params is Array instance.
1875         <ul>
1876           <li>params[0] is a KiiBucket instance which this method was called on.</li>
1877           <li>params[1] is a KiiQuery instance.</li>
1878           <li>params[2] is an integer count result. </li>
1879         </ul>
1880       </li>
1881       <li>reject callback function: function(error). error is an Error instance.
1882         <ul>
1883           <li>error.target is the KiiBucket instance which this method was called on.</li>
1884           <li>error.message</li>
1885         </ul>
1886       </li>
1887     </ul>
1888   @example
1889   // example to use callbacks directly
1890   var bucket = . . .; // a KiiBucket
1891   // define the callbacks
1892   var callbacks = {
1893       success: function(bucket, query, count) {
1894           // do something with the results
1895       },
1896   
1897       failure: function(bucket, errorString) {
1898           // error happened.
1899       }
1900   };
1901   
1902   bucket.count(callbacks);
1903   
1904   // example to use Promise
1905   var bucket = . . .; // a KiiBucket
1906   var queryObject = . . .; // a KiiQuery
1907   
1908   bucket.count().then(
1909       function(params) {
1910           var bucket = params[0];
1911           var count = params[2];
1912           // do something with the results
1913       },
1914       function(error) {
1915           var bucket = error.target;
1916           var errorString = error.message;
1917           // error happened.
1918       }
1919   );
1920    */
1921 
1922   KiiBucket.prototype.count = function(callbacks) {
1923     var all_query;
1924     all_query = root.KiiQuery.queryWithClause();
1925     return this.countWithQuery(all_query, callbacks);
1926   };
1927 
1928 
1929   /** Delete the given bucket from the server
1930   @name delete
1931   @memberOf root.KiiBucket#
1932   @function
1933   @param Object callbacks An object with callback methods defined
1934   @param {Method} callbacks.success The callback method to call on a successful query request
1935   @param {Method} callbacks.failure The callback method to call on a failed query request
1936   @return {Promise} return promise object.
1937     <ul>
1938       <li>fulfill callback function: function(deletedBucket). deletedBucket is KiiBucket instance.</li>
1939       <li>reject callback function: function(error). error is an Error instance.
1940         <ul>
1941           <li>error.target is the KiiBucket instance which this method was called on.</li>
1942           <li>error.message</li>
1943         </ul>
1944       </li>
1945     </ul>
1946   @example
1947   // example to use callbacks directly
1948   var bucket = . . .; // a KiiBucket
1949   bucket.delete({
1950       success: function(deletedBucket) {
1951           // do something with the result
1952       },
1953   
1954       failure: function(bucketToDelete, anErrorString) {
1955           // do something with the error response
1956       }
1957   });
1958   
1959   // example to use Promise
1960   var bucket = . . .; // a KiiBucket
1961   bucket.delete({
1962       success: function(deletedBucket) {
1963           // do something with the result
1964       },
1965   
1966       failure: function(bucketToDelete, anErrorString) {
1967           // do something with the error response
1968       }
1969   }).then(
1970       function(deletedBucket) {
1971         // do something with the result
1972       },
1973       function(error) {
1974         // do something with the error response
1975       }
1976   );
1977    */
1978 
1979   KiiBucket.prototype["delete"] = function(callbacks) {
1980     return new Promise((function(_this) {
1981       return function(resolve, reject) {
1982         var deleteCallbacks;
1983         deleteCallbacks = {
1984           success: function() {
1985             if (callbacks != null) {
1986               callbacks.success.apply(callbacks, arguments);
1987             }
1988             return resolve(arguments[0]);
1989           },
1990           failure: function() {
1991             if (callbacks != null) {
1992               callbacks.failure.apply(callbacks, arguments);
1993             }
1994             return reject(KiiUtilities._Error(arguments[1], _this));
1995           }
1996         };
1997         return _this._deleteUsingCallbacks(deleteCallbacks);
1998       };
1999     })(this));
2000   };
2001 
2002   KiiBucket.prototype._deleteUsingCallbacks = function(callbacks) {
2003     var executeCallbacks, request;
2004     request = this._getRequest({
2005       path: this._generatePath(),
2006       withApp: true
2007     });
2008     request.setMethod("DELETE");
2009     executeCallbacks = {
2010       success: (function(_this) {
2011         return function(data, statusCode) {
2012           if (callbacks != null) {
2013             return callbacks.success(_this);
2014           }
2015         };
2016       })(this),
2017       failure: (function(_this) {
2018         return function(error, statusCode) {
2019           if (callbacks != null) {
2020             return callbacks.failure(_this, error);
2021           }
2022         };
2023       })(this)
2024     };
2025     return request.execute(executeCallbacks, true);
2026   };
2027 
2028   function KiiBucket(bucketName, parent) {
2029     this.objectWithJSON = __bind(this.objectWithJSON, this);
2030     this._getHttpUri = __bind(this._getHttpUri, this);
2031     this._generatePath = __bind(this._generatePath, this);
2032     this._getRequest = __bind(this._getRequest, this);
2033     this._deleteUsingCallbacks = __bind(this._deleteUsingCallbacks, this);
2034     this["delete"] = __bind(this["delete"], this);
2035     this.count = __bind(this.count, this);
2036     this._countWithQueryUsingCallbacks = __bind(this._countWithQueryUsingCallbacks, this);
2037     this.countWithQuery = __bind(this.countWithQuery, this);
2038     this._executeQueryUsingCallbacks = __bind(this._executeQueryUsingCallbacks, this);
2039     this.executeQuery = __bind(this.executeQuery, this);
2040     this.acl = __bind(this.acl, this);
2041     this.createObjectWithID = __bind(this.createObjectWithID, this);
2042     this.createObjectWithType = __bind(this.createObjectWithType, this);
2043     this.createObject = __bind(this.createObject, this);
2044     this._getQualifiedBucketName = __bind(this._getQualifiedBucketName, this);
2045     this._setBucketName = __bind(this._setBucketName, this);
2046     this.getBucketName = __bind(this.getBucketName, this);
2047     this.getThing = __bind(this.getThing, this);
2048     this.getGroup = __bind(this.getGroup, this);
2049     this.getUser = __bind(this.getUser, this);
2050     if (!KiiUtilities._isNonEmptyString(bucketName)) {
2051       throw root.InvalidArgumentException('Specified bucket name is null or empty.');
2052     }
2053     this._bucketName = bucketName;
2054     if (parent != null) {
2055       if (parent instanceof root.KiiGroup) {
2056         this._group = parent;
2057       } else if (parent instanceof root.KiiUser) {
2058         this._user = parent;
2059       } else if (parent instanceof root.KiiThing) {
2060         this._thing = parent;
2061       }
2062     }
2063   }
2064 
2065   KiiBucket._bucketWithName = function(bucketName, parent) {
2066     var bucket;
2067     bucket = new root.KiiBucket(bucketName, parent);
2068     return bucket;
2069   };
2070 
2071   KiiBucket.prototype._getRequest = function(spec) {
2072     var path, request, withApp;
2073     path = spec.path;
2074     withApp = spec.withApp;
2075     request = new KiiRequest(path, withApp);
2076     return request;
2077   };
2078 
2079   KiiBucket.prototype._generatePath = function() {
2080     var path;
2081     if (this._user != null) {
2082       path = "/users/" + (this._user.getUUID()) + "/buckets/" + (this._getQualifiedBucketName());
2083     } else if (this._group != null) {
2084       path = "/groups/" + (this._group.getUUID()) + "/buckets/" + (this._getQualifiedBucketName());
2085     } else if (this._thing != null) {
2086       path = "/things/" + (this._thing.getThingID()) + "/buckets/" + (this._getQualifiedBucketName());
2087     } else {
2088       path = "/buckets/" + (this._getQualifiedBucketName());
2089     }
2090     return path;
2091   };
2092 
2093   KiiBucket.prototype._getHttpUri = function() {
2094     return "" + (root.Kii.getBaseURL()) + "/apps/" + (root.Kii.getAppID()) + "/" + (this._generatePath());
2095   };
2096 
2097   KiiBucket.prototype.objectWithJSON = function(json) {
2098     var newobject;
2099     newobject = this.createObject();
2100     newobject._updateWithJSON(json);
2101     return newobject;
2102   };
2103 
2104   return KiiBucket;
2105 
2106 })();
2107 
2108 root.KiiEncryptedBucket = (function(_super) {
2109   __extends(KiiEncryptedBucket, _super);
2110 
2111   function KiiEncryptedBucket(bucketName, parent) {
2112     this._getQualifiedBucketName = __bind(this._getQualifiedBucketName, this);
2113     if (!KiiUtilities._isNonEmptyString(bucketName)) {
2114       throw root.InvalidArgumentException('Specified bucket name is null or empty.');
2115     }
2116     if (root.KiiEncryptedBucket._isEncrypted(bucketName)) {
2117       KiiEncryptedBucket.__super__.constructor.call(this, bucketName.replace("CRYPTO:", ""), parent);
2118     } else {
2119       KiiEncryptedBucket.__super__.constructor.call(this, bucketName, parent);
2120     }
2121   }
2122 
2123   KiiEncryptedBucket.prototype._getQualifiedBucketName = function() {
2124     return "CRYPTO:" + this._bucketName;
2125   };
2126 
2127   KiiEncryptedBucket._bucketWithName = function(bucketName, parent) {
2128     var bucket;
2129     bucket = new root.KiiEncryptedBucket(bucketName, parent);
2130     return bucket;
2131   };
2132 
2133   KiiEncryptedBucket._isEncrypted = function(bucketName) {
2134     var isEncrypted;
2135     isEncrypted = bucketName.indexOf("CRYPTO:") === 0;
2136     return isEncrypted;
2137   };
2138 
2139   return KiiEncryptedBucket;
2140 
2141 })(root.KiiBucket);
2142 
2143 root.KiiEncryptedBucketWithToken = (function(_super) {
2144   __extends(KiiEncryptedBucketWithToken, _super);
2145 
2146   function KiiEncryptedBucketWithToken(bucketName, parent, token) {
2147     this.acl = __bind(this.acl, this);
2148     this.createObjectWithID = __bind(this.createObjectWithID, this);
2149     this.createObjectWithType = __bind(this.createObjectWithType, this);
2150     this.createObject = __bind(this.createObject, this);
2151     this._getRequest = __bind(this._getRequest, this);
2152     KiiEncryptedBucketWithToken.__super__.constructor.call(this, bucketName, parent);
2153     this._authToken = token;
2154   }
2155 
2156   KiiEncryptedBucketWithToken.prototype._getRequest = function(spec) {
2157     var request;
2158     request = KiiEncryptedBucketWithToken.__super__._getRequest.call(this, spec);
2159     request.setAdminToken(this._authToken);
2160     return request;
2161   };
2162 
2163   KiiEncryptedBucketWithToken.prototype.createObject = function() {
2164     return root.KiiObjectWithToken.objectWithBucket(this, null, this._authToken);
2165   };
2166 
2167   KiiEncryptedBucketWithToken.prototype.createObjectWithType = function(type) {
2168     return root.KiiObjectWithToken.objectWithBucket(this, type, this._authToken);
2169   };
2170 
2171   KiiEncryptedBucketWithToken.prototype.createObjectWithID = function(id) {
2172     return root.KiiObjectWithToken.objectWithID(this, id, this._authToken);
2173   };
2174 
2175   KiiEncryptedBucketWithToken.prototype.acl = function() {
2176     var acl;
2177     acl = new root.KiiACLWithToken(this, this._authToken);
2178     return acl;
2179   };
2180 
2181   return KiiEncryptedBucketWithToken;
2182 
2183 })(root.KiiEncryptedBucket);
2184 
2185 root.KiiBucketWithToken = (function(_super) {
2186   __extends(KiiBucketWithToken, _super);
2187 
2188   function KiiBucketWithToken(bucketName, parent, token) {
2189     this.acl = __bind(this.acl, this);
2190     this.createObjectWithID = __bind(this.createObjectWithID, this);
2191     this.createObjectWithType = __bind(this.createObjectWithType, this);
2192     this.createObject = __bind(this.createObject, this);
2193     this._getRequest = __bind(this._getRequest, this);
2194     KiiBucketWithToken.__super__.constructor.call(this, bucketName, parent);
2195     this._authToken = token;
2196   }
2197 
2198   KiiBucketWithToken.prototype._getRequest = function(spec) {
2199     var request;
2200     request = KiiBucketWithToken.__super__._getRequest.call(this, spec);
2201     request.setAdminToken(this._authToken);
2202     return request;
2203   };
2204 
2205   KiiBucketWithToken.prototype.createObject = function() {
2206     return root.KiiObjectWithToken.objectWithBucket(this, null, this._authToken);
2207   };
2208 
2209   KiiBucketWithToken.prototype.createObjectWithType = function(type) {
2210     return root.KiiObjectWithToken.objectWithBucket(this, type, this._authToken);
2211   };
2212 
2213   KiiBucketWithToken.prototype.createObjectWithID = function(id) {
2214     return root.KiiObjectWithToken.objectWithID(this, id, this._authToken);
2215   };
2216 
2217   KiiBucketWithToken.prototype.acl = function() {
2218     var acl;
2219     acl = new root.KiiACLWithToken(this, this._authToken);
2220     return acl;
2221   };
2222 
2223   return KiiBucketWithToken;
2224 
2225 })(root.KiiBucket);
2226 
2227 
2228 /**
2229     @class Represents a KiiGroup object
2230     @exports root.KiiGroup as KiiGroup
2231  */
2232 
2233 root.KiiGroup = (function() {
2234   KiiGroup.prototype._getAddMembers = function() {
2235     return this._addMembers;
2236   };
2237 
2238   KiiGroup.prototype._getRemoveMembers = function() {
2239     return this._removeMembers;
2240   };
2241 
2242   function KiiGroup() {
2243     this._setAuthToken = __bind(this._setAuthToken, this);
2244     this._getHttpURI = __bind(this._getHttpURI, this);
2245     this._listTopicsUsingCallbacks = __bind(this._listTopicsUsingCallbacks, this);
2246     this.listTopics = __bind(this.listTopics, this);
2247     this.topicWithName = __bind(this.topicWithName, this);
2248     this._setOwnerFromContext = __bind(this._setOwnerFromContext, this);
2249     this._userWithID = __bind(this._userWithID, this);
2250     this._getRequest = __bind(this._getRequest, this);
2251     this._updateWithJSON = __bind(this._updateWithJSON, this);
2252     this._getOwnerUsingCallbacks = __bind(this._getOwnerUsingCallbacks, this);
2253     this.getOwner = __bind(this.getOwner, this);
2254     this._deleteUsingCallbacks = __bind(this._deleteUsingCallbacks, this);
2255     this["delete"] = __bind(this["delete"], this);
2256     this._refreshUsingCallbacks = __bind(this._refreshUsingCallbacks, this);
2257     this.refresh = __bind(this.refresh, this);
2258     this._saveWithOwnerUsingCallbacks = __bind(this._saveWithOwnerUsingCallbacks, this);
2259     this.saveWithOwner = __bind(this.saveWithOwner, this);
2260     this._saveUsingCallbacks = __bind(this._saveUsingCallbacks, this);
2261     this.save = __bind(this.save, this);
2262     this._changeGroupNameUsingCallbacks = __bind(this._changeGroupNameUsingCallbacks, this);
2263     this.changeGroupName = __bind(this.changeGroupName, this);
2264     this._changeOwner = __bind(this._changeOwner, this);
2265     this._saveMembers = __bind(this._saveMembers, this);
2266     this._getMemberListUsingCallbacks = __bind(this._getMemberListUsingCallbacks, this);
2267     this.getMemberList = __bind(this.getMemberList, this);
2268     this._removeMember = __bind(this._removeMember, this);
2269     this._addMember = __bind(this._addMember, this);
2270     this.removeUser = __bind(this.removeUser, this);
2271     this.addUser = __bind(this.addUser, this);
2272     this.encryptedBucketWithName = __bind(this.encryptedBucketWithName, this);
2273     this.bucketWithName = __bind(this.bucketWithName, this);
2274     this.objectURI = __bind(this.objectURI, this);
2275     this._setOwner = __bind(this._setOwner, this);
2276     this.getCachedOwner = __bind(this.getCachedOwner, this);
2277     this._setName = __bind(this._setName, this);
2278     this.getName = __bind(this.getName, this);
2279     this.getID = __bind(this.getID, this);
2280     this._setUUID = __bind(this._setUUID, this);
2281     this.getUUID = __bind(this.getUUID, this);
2282     this._setAddMembers = __bind(this._setAddMembers, this);
2283     this._getRemoveMembers = __bind(this._getRemoveMembers, this);
2284     this._getAddMembers = __bind(this._getAddMembers, this);
2285     this._addMembers = {};
2286     this._removeMembers = {};
2287   }
2288 
2289   KiiGroup.prototype._setAddMembers = function(members) {
2290     var member, _i, _len, _results;
2291     if (members != null) {
2292       _results = [];
2293       for (_i = 0, _len = members.length; _i < _len; _i++) {
2294         member = members[_i];
2295         _results.push(this.addUser(member));
2296       }
2297       return _results;
2298     }
2299   };
2300 
2301 
2302   /** @deprecated Use {@link KiiGroup.getId} instead.
2303   Get the UUID of the given group, assigned by the server
2304   @returns {String}
2305    */
2306 
2307   KiiGroup.prototype.getUUID = function() {
2308     return this._uuid;
2309   };
2310 
2311   KiiGroup.prototype._setUUID = function(_uuid) {
2312     this._uuid = _uuid;
2313   };
2314 
2315 
2316   /** Get the ID of the current KiiGroup instance.
2317   @returns {String} Id of the group or null if the group has not saved to cloud.
2318    */
2319 
2320   KiiGroup.prototype.getID = function() {
2321     return this._uuid;
2322   };
2323 
2324 
2325   /** The name of this group
2326   @returns {String}
2327    */
2328 
2329   KiiGroup.prototype.getName = function() {
2330     return this._groupName;
2331   };
2332 
2333   KiiGroup.prototype._setName = function(_groupName) {
2334     this._groupName = _groupName;
2335   };
2336 
2337 
2338   /** Returns the owner of this group if this group holds the information of owner.
2339   
2340   Group will holds the information of owner when "saving group on cloud" or "retrieving group info/owner from cloud".
2341   The cache will not be shared among the different instances of KiiGroup.
2342   <UL>
2343   <LI>This API will not access to server.
2344   To update the group owner information on cloud, please call {@link KiiGroup#refresh} or {@link KiiGroup#getOwner}.
2345   </LI>
2346   <LI>This API does not return all the properties of the owner.
2347   To get all owner properties, {@link KiiUser#refresh} is necessary.</LI>
2348   </UL>
2349   @returns {KiiUser} KiiUser who owns this group, undefined if this group doesn't hold the information of owner yet.
2350   @link KiiGroup#getOwner
2351    */
2352 
2353   KiiGroup.prototype.getCachedOwner = function() {
2354     return this._owner;
2355   };
2356 
2357   KiiGroup.prototype._setOwner = function(_owner) {
2358     this._owner = _owner;
2359   };
2360 
2361 
2362   /** Get a specifically formatted string referencing the group
2363   
2364   <br><br>The group must exist in the cloud (have a valid UUID).
2365   @returns {String} A URI string based on the current group. null if a URI couldn't be generated.
2366   @example
2367   var group = . . .; // a KiiGroup
2368   var uri = group.objectURI();
2369    */
2370 
2371   KiiGroup.prototype.objectURI = function() {
2372     if (this._uuid != null) {
2373       return "kiicloud://groups/" + this._uuid;
2374     } else {
2375       return null;
2376     }
2377   };
2378 
2379 
2380   /** Register new group own by current user on Kii Cloud with specified ID.
2381   
2382   <br><br>If the group that has specified id already exists, registration will be failed.
2383   
2384   @param {String} groupID ID of the KiiGroup
2385   @param {String} groupName Name of the KiiGroup
2386   @param {Array} members An array of KiiUser objects to add to the group
2387   @param {Object} [callbacks] An object with callback methods defined
2388   @param {Method} callbacks.success The callback method to call on a successful register request
2389   @param {Method} callbacks.failure The callback method to call on a failed register request
2390   @return {Promise} return promise object.
2391         <ul>
2392           <li>fulfill callback function: function(theSavedGroup). theSavedGroup is KiiGroup instance.</li>
2393           <li>reject callback function: function(error). error is an Error instance.
2394             <ul>
2395               <li>error.target is the KiiGroup instance which this method was called on.</li>
2396               <li>error.message</li>
2397               <li>error.addMembersArray is array of KiiUser to be added as memebers of this group.</li>
2398               <li>error.removeMembersArray is array of KiiUser to be removed from the memebers list of this group.</li>
2399             </ul>
2400           </li>
2401         </ul>
2402   @example
2403   // example to use callbacks directly
2404   var members = [];
2405   members.push(KiiUser.userWithID("Member User Id"));
2406   KiiGroup.registerGroupWithID("Group ID", "Group Name", members, {
2407       success: function(theSavedGroup) {
2408           // do something with the saved group
2409       },
2410       failure: function(theGroup, anErrorString, addMembersArray, removeMembersArray) {
2411           // do something with the error response
2412       }
2413   });
2414   
2415   // example to use Promise
2416   var members = [];
2417   members.push(KiiUser.userWithID("Member User Id"));
2418   KiiGroup.registerGroupWithID("Group ID", "Group Name", members).then(
2419       function(theSavedGroup) {
2420           // do something with the saved group
2421       },
2422       function(error) {
2423           var theGroup = error.target;
2424           var anErrorString = error.message;
2425           var addMembersArray = error.addMembersArray;
2426           // do something with the error response
2427   });
2428    */
2429 
2430   KiiGroup.registerGroupWithID = function(groupID, groupName, members, callbacks) {
2431     return new Promise(function(resolve, reject) {
2432       var registerGroupWithIDCallbacks, _ref, _ref1;
2433       registerGroupWithIDCallbacks = {
2434         success: function() {
2435           if (callbacks != null) {
2436             callbacks.success.apply(callbacks, arguments);
2437           }
2438           return resolve(arguments[0]);
2439         },
2440         failure: function() {
2441           var error;
2442           if (callbacks != null) {
2443             callbacks.failure.apply(callbacks, arguments);
2444           }
2445           error = KiiUtilities._Error(arguments[1], arguments[0]);
2446           error.addMembersArray = arguments[2];
2447           error.removeMembersArray = arguments[3];
2448           return reject(error);
2449         }
2450       };
2451       return KiiGroup._registerGroupWithIDUsingCallbacks((_ref = root.KiiUser.getCurrentUser()) != null ? _ref.getAccessToken() : void 0, groupID, groupName, (_ref1 = root.Kii.getCurrentUser()) != null ? _ref1.getID() : void 0, members, registerGroupWithIDCallbacks);
2452     });
2453   };
2454 
2455   KiiGroup._registerGroupWithIDUsingCallbacks = function(token, groupID, groupName, owner, members, callbacks) {
2456     var data, i, member, memberIDs, requestCallbacks, url, wrapper, xhr, _i, _len;
2457     if (!KiiUtilities._isNonEmptyString(groupID)) {
2458       callbacks.failure(null, "groupID is null or empty", members, null);
2459       return;
2460     }
2461     if (!KiiUtilities._validateGroupID(groupID)) {
2462       callbacks.failure(null, "invalid groupID : " + groupID, members, null);
2463       return;
2464     }
2465     if (!KiiUtilities._isNonEmptyString(groupName)) {
2466       callbacks.failure(null, "groupName is null or empty", members, null);
2467       return;
2468     }
2469     if (owner == null) {
2470       callbacks.failure(null, "owner is null", members, null);
2471       return;
2472     }
2473     url = root.Kii.getBaseURL() + "/apps/" + root.Kii.getAppID() + "/groups/" + groupID;
2474     wrapper = KiiXHRWrapperFactory.createXHRWrapper("PUT", url);
2475     xhr = wrapper.xhr;
2476     wrapper.setKiiHeaders();
2477     wrapper.setAuthToken(token);
2478     wrapper.setContentType("application/vnd.kii.GroupCreationRequest+json");
2479     data = {};
2480     data.name = groupName;
2481     data.owner = owner;
2482     if ((members != null) && members.length > 0) {
2483       memberIDs = [];
2484       for (i = _i = 0, _len = members.length; _i < _len; i = ++_i) {
2485         member = members[i];
2486         memberIDs.push(member.getID());
2487       }
2488       data.members = memberIDs;
2489     }
2490     requestCallbacks = {
2491       success: function() {
2492         var group;
2493         try {
2494           group = KiiGroup.groupWithNameAndMembers(groupName, members);
2495           group._setUUID(groupID);
2496           return callbacks.success(group);
2497         } catch (_error) {
2498           return callbacks.failure(null, wrapper.getErrorString("failed to register group."));
2499         }
2500       },
2501       failure: function() {
2502         var errString;
2503         errString = wrapper.getErrorString("failed to register group.");
2504         return callbacks.failure(null, errString, members, null);
2505       }
2506     };
2507     return wrapper.sendData(JSON.stringify(data), requestCallbacks);
2508   };
2509 
2510 
2511   /** Creates a reference to a bucket for this group
2512   
2513   <br><br>The bucket will be created/accessed within this group's scope
2514   @param {String} bucketName The name of the bucket the user should create/access
2515   @returns {KiiBucket} A working KiiBucket object
2516   @example
2517   var group = . . .; // a KiiGroup
2518   var bucket = group.bucketWithName("myBucket");
2519    */
2520 
2521   KiiGroup.prototype.bucketWithName = function(bucketName) {
2522     var bucket;
2523     bucket = new root.KiiBucket(bucketName, this);
2524     return bucket;
2525   };
2526 
2527 
2528   /** Creates a reference to a encrypted bucket for this group
2529   
2530   <br><br>The bucket will be created/accessed within this group's scope
2531   @param {String} bucketName The name of the bucket the user should create/access
2532   @returns {KiiEncryptedBucket} A working KiiEncryptedBucket object
2533   @example
2534   var group = . . .; // a KiiGroup
2535   var bucket = group.encryptedBucketWithName("myBucket");
2536    */
2537 
2538   KiiGroup.prototype.encryptedBucketWithName = function(bucketName) {
2539     var bucket;
2540     bucket = new root.KiiEncryptedBucket(bucketName, this);
2541     return bucket;
2542   };
2543 
2544 
2545   /** Adds a user to the given group
2546   
2547   <br><br>This method will NOT access the server immediately. You must call save to add the user on the server. This allows multiple users to be added/removed before calling save.
2548   @param {KiiUser} member The user to be added to the group
2549   @example
2550   var user = . . .; // a KiiUser
2551   var group = . . .; // a KiiGroup
2552   group.addUser(user);
2553   group.save(callbacks);
2554    */
2555 
2556   KiiGroup.prototype.addUser = function(member) {
2557     var userID;
2558     if (member == null) {
2559       root.Kii.logger("Passed member is null");
2560       return;
2561     }
2562     if (member.getUUID() == null) {
2563       root.Kii.logger("Passed member ID is null");
2564       return;
2565     }
2566     userID = member.getUUID();
2567     if (!(userID in this._addMembers)) {
2568       this._addMembers[userID] = member;
2569     }
2570     if (userID in this._removeMembers) {
2571       return delete this._removeMembers[userID];
2572     }
2573   };
2574 
2575 
2576   /** Removes a user from the given group
2577   
2578   <br><br>This method will NOT access the server immediately. You must call save to remove the user on the server. This allows multiple users to be added/removed before calling save.
2579   @param {KiiUser} member The user to be added to the group
2580   @example
2581   var user = . . .; // a KiiUser
2582   var group = . . .; // a KiiGroup
2583   group.removeUser(user);
2584   group.save(callbacks);
2585    */
2586 
2587   KiiGroup.prototype.removeUser = function(member) {
2588     var userID;
2589     if (member == null) {
2590       root.Kii.logger("Passed member is null");
2591       return;
2592     }
2593     if (member.getUUID() == null) {
2594       root.Kii.logger("Passed member uuid is null");
2595       return;
2596     }
2597     userID = member.getUUID();
2598     if (!(userID in this._removeMembers)) {
2599       this._removeMembers[userID] = member;
2600     }
2601     if (userID in this._addMembers) {
2602       return delete this._addMembers[userID];
2603     }
2604   };
2605 
2606   KiiGroup.prototype._addMember = function(member, callback) {
2607     var memberCallbacks, request;
2608     root.Kii.logger("Adding member " + (member.getUUID()) + " to group " + this._groupName);
2609     request = this._getRequest({
2610       path: "/groups/" + this._uuid + "/members/" + (member.getUUID()),
2611       withApp: true
2612     });
2613     request.setMethod("PUT");
2614     memberCallbacks = {
2615       success: (function(_this) {
2616         return function(data, statusCode) {
2617           delete _this._addMembers[member.getUUID()];
2618           return _this._saveMembers(callback);
2619         };
2620       })(this),
2621       failure: (function(_this) {
2622         return function(error, statusCode) {
2623           var addMembersArray, removeMembersArray, userID;
2624           addMembersArray = (function() {
2625             var _ref, _results;
2626             _ref = this._addMembers;
2627             _results = [];
2628             for (userID in _ref) {
2629               member = _ref[userID];
2630               _results.push(member);
2631             }
2632             return _results;
2633           }).call(_this);
2634           removeMembersArray = (function() {
2635             var _ref, _results;
2636             _ref = this._removeMembers;
2637             _results = [];
2638             for (userID in _ref) {
2639               member = _ref[userID];
2640               _results.push(member);
2641             }
2642             return _results;
2643           }).call(_this);
2644           return callback.failure(_this, error, addMembersArray, removeMembersArray);
2645         };
2646       })(this)
2647     };
2648     return request.execute(memberCallbacks, false);
2649   };
2650 
2651   KiiGroup.prototype._removeMember = function(member, callback) {
2652     var removeCallbacks, request;
2653     root.Kii.logger("Removing member " + (member.getUUID()) + " to group " + this._groupName);
2654     request = this._getRequest({
2655       path: "/groups/" + this._uuid + "/members/" + (member.getUUID()),
2656       withApp: true
2657     });
2658     request.setMethod("DELETE");
2659     removeCallbacks = {
2660       success: (function(_this) {
2661         return function(data, statusCode) {
2662           delete _this._getRemoveMembers()[member.getUUID()];
2663           return _this._saveMembers(callback);
2664         };
2665       })(this),
2666       failure: (function(_this) {
2667         return function(error, statusCode) {
2668           var addMembersArray, removeMembersArray, userID;
2669           addMembersArray = (function() {
2670             var _ref, _results;
2671             _ref = this._addMembers;
2672             _results = [];
2673             for (userID in _ref) {
2674               member = _ref[userID];
2675               _results.push(member);
2676             }
2677             return _results;
2678           }).call(_this);
2679           removeMembersArray = (function() {
2680             var _ref, _results;
2681             _ref = this._removeMembers;
2682             _results = [];
2683             for (userID in _ref) {
2684               member = _ref[userID];
2685               _results.push(member);
2686             }
2687             return _results;
2688           }).call(_this);
2689           return callback.failure(_this, error, addMembersArray, removeMembersArray);
2690         };
2691       })(this)
2692     };
2693     return request.execute(removeCallbacks, false);
2694   };
2695 
2696 
2697   /** Gets a list of all current members of a group
2698   @param {Object} [callbacks] An object with callback methods defined
2699   @param {Method} callbacks.success The callback method to call on a successful list request
2700   @param {Method} callbacks.failure The callback method to call on a failed list request
2701   @return {Promise} return promise object.
2702     <ul>
2703       <li>fulfill callback function: function(params). params is Array instance.
2704         <ul>
2705           <li>params[0] is a KiiGroup instance which this method was called on.</li>
2706           <li>params[1] is array of memeber KiiUser instances.</li>
2707         </ul>
2708       </li>
2709       <li>reject callback function: function(error). error is an Error instance.
2710         <ul>
2711           <li>error.target is the KiiGroup instance which this method was called on.</li>
2712           <li>error.message</li>
2713         </ul>
2714       </li>
2715     </ul>
2716   @example
2717   // example to use callbacks directly
2718   var group = . . .; // a KiiGroup
2719   group.getMemberList({
2720       success: function(theGroup, memberList) {
2721           // do something with the result
2722           for(var i=0; i<memberList.length; i++){
2723               var u = memberList[i]; // a KiiUser within the group
2724           }
2725       },
2726   
2727       failure: function(theGroup, anErrorString) {
2728           // do something with the error response
2729       }
2730   });
2731   
2732   // example to use Promise
2733   var group = . . .; // a KiiGroup
2734   group.getMemberList().then(
2735       function(params) {
2736           var theGroup = params[0];
2737           var memberlist = params[1];
2738           // do something with the result
2739           for(var i=0; i<memberList.length; i++){
2740               var u = memberList[i]; // a KiiUser within the group
2741           }
2742       },
2743       function(error) {
2744           // do something with the error response
2745       }
2746   );
2747    */
2748 
2749   KiiGroup.prototype.getMemberList = function(callbacks) {
2750     return new Promise((function(_this) {
2751       return function(resolve, reject) {
2752         var getMemberListCallbacks;
2753         getMemberListCallbacks = {
2754           success: function() {
2755             if (callbacks != null) {
2756               callbacks.success.apply(callbacks, arguments);
2757             }
2758             return resolve(arguments);
2759           },
2760           failure: function() {
2761             if (callbacks != null) {
2762               callbacks.failure.apply(callbacks, arguments);
2763             }
2764             return reject(KiiUtilities._Error(arguments[1], _this));
2765           }
2766         };
2767         return _this._getMemberListUsingCallbacks(getMemberListCallbacks);
2768       };
2769     })(this));
2770   };
2771 
2772   KiiGroup.prototype._getMemberListUsingCallbacks = function(callbacks) {
2773     var listCallbacks, request;
2774     root.Kii.logger("Getting member list for group " + this._groupName);
2775     request = this._getRequest({
2776       path: "/groups/" + this._uuid + "/members",
2777       withApp: true
2778     });
2779     request.setAccept("application/vnd.kii.MembersRetrievalResponse+json");
2780     listCallbacks = {
2781       success: (function(_this) {
2782         return function(data, statusCode) {
2783           var member, memberList, members, _i, _len;
2784           if (statusCode < 300 && statusCode >= 200) {
2785             memberList = [];
2786             members = data['members'];
2787             for (_i = 0, _len = members.length; _i < _len; _i++) {
2788               member = members[_i];
2789               memberList.push(_this._userWithID(member.userID));
2790             }
2791             if (callbacks != null) {
2792               return callbacks.success(_this, memberList);
2793             }
2794           } else if (callbacks != null) {
2795             return callbacks.failure(_this, "Unable to get member list of group");
2796           }
2797         };
2798       })(this),
2799       failure: (function(_this) {
2800         return function(error, statusCode) {
2801           if (callbacks != null) {
2802             return callbacks.failure(_this, error);
2803           }
2804         };
2805       })(this)
2806     };
2807     return request.execute(listCallbacks, false);
2808   };
2809 
2810   KiiGroup.prototype._saveMembers = function(callbacks) {
2811     var addMemberKeys, removeMemberKeys;
2812     addMemberKeys = Object.keys(this._addMembers);
2813     removeMemberKeys = Object.keys(this._removeMembers);
2814     if (addMemberKeys.length === 0 && removeMemberKeys.length === 0) {
2815       callbacks.success(this);
2816     }
2817     if (addMemberKeys.length > 0) {
2818       this._addMember(this._addMembers[addMemberKeys[0]], callbacks);
2819       return;
2820     }
2821     if (removeMemberKeys.length > 0) {
2822       this._removeMember(this._removeMembers[removeMemberKeys[0]], callbacks);
2823     }
2824   };
2825 
2826   KiiGroup.prototype._changeOwner = function(owner, callbacks) {
2827     var data, request, saveCallbacks;
2828     request = this._getRequest({
2829       path: "/groups/" + this._uuid + "/owner",
2830       withApp: true
2831     });
2832     request.setContentType("application/vnd.kii.GroupOwnerChangeRequest+json");
2833     request.setMethod("PUT");
2834     data = {};
2835     data.owner = owner;
2836     request.setData(data);
2837     saveCallbacks = {
2838       success: (function(_this) {
2839         return function(data, statusCode) {
2840           if (statusCode < 300 && statusCode >= 200) {
2841             return callbacks.success(_this);
2842           }
2843         };
2844       })(this),
2845       failure: (function(_this) {
2846         return function(error, statusCode) {
2847           if (callbacks != null) {
2848             return callbacks.failure(_this, error);
2849           }
2850         };
2851       })(this)
2852     };
2853     return request.execute(saveCallbacks, false);
2854   };
2855 
2856 
2857   /** Updates the group name on the server
2858   
2859   @param {String} newName A String of the desired group name
2860   @param {Object} [callbacks] An object with callback methods defined
2861   @param {Method} callbacks.success The callback method to call on a successful save request
2862   @param {Method} callbacks.failure The callback method to call on a failed save request
2863   @return {Promise} return promise object.
2864     <ul>
2865       <li>fulfill callback function: function(theRenamedGroup). theRenamedGroup is KiiGroup instance.</li>
2866       <li>reject callback function: function(error). error is an Error instance.
2867         <ul>
2868           <li>error.target is the KiiGroup instance which this method was called on.</li>
2869           <li>error.message</li>
2870         </ul>
2871       </li>
2872     </ul>
2873   @example
2874   // example to use callbacks directly
2875   var group = . . .; // a KiiGroup
2876   group.changeGroupName("myNewName", {
2877       success: function(theRenamedGroup) {
2878           // do something with the group
2879       },
2880   
2881       failure: function(theGroup, anErrorString) {
2882           // do something with the error response
2883       }
2884   });
2885   
2886   // example to use Promise
2887   var group = . . .; // a KiiGroup
2888   group.changeGroupName("myNewName").then(
2889       function(theRenamedGroup) {
2890           // do something with the group
2891       },
2892       function(error) {
2893           // do something with the error response
2894       }
2895   );
2896    */
2897 
2898   KiiGroup.prototype.changeGroupName = function(newName, callbacks) {
2899     return new Promise((function(_this) {
2900       return function(resolve, reject) {
2901         var changeGroupNameCallbacks;
2902         changeGroupNameCallbacks = {
2903           success: function() {
2904             if (callbacks != null) {
2905               callbacks.success.apply(callbacks, arguments);
2906             }
2907             return resolve(arguments[0]);
2908           },
2909           failure: function() {
2910             if (callbacks != null) {
2911               callbacks.failure.apply(callbacks, arguments);
2912             }
2913             return reject(KiiUtilities._Error(arguments[1], _this));
2914           }
2915         };
2916         return _this._changeGroupNameUsingCallbacks(newName, changeGroupNameCallbacks);
2917       };
2918     })(this));
2919   };
2920 
2921   KiiGroup.prototype._changeGroupNameUsingCallbacks = function(newName, callbacks) {
2922     var request, saveCallbacks;
2923     root.Kii.logger("Saving group: " + this.name);
2924     if (this._uuid != null) {
2925       request = this._getRequest({
2926         path: "/groups/" + this._uuid + "/name",
2927         withApp: true
2928       });
2929       request.setContentType("text/plain");
2930       request.setMethod("PUT");
2931       request.setData(newName);
2932       saveCallbacks = {
2933         success: (function(_this) {
2934           return function(data, statusCode) {
2935             if (statusCode < 300 && statusCode >= 200) {
2936               _this._setName(newName);
2937               if (callbacks != null) {
2938                 return callbacks.success(_this);
2939               }
2940             } else if (callbacks != null) {
2941               return callbacks.failure(_this, "Unable to change group name - invalid response");
2942             }
2943           };
2944         })(this),
2945         failure: (function(_this) {
2946           return function(error, statusCode) {
2947             if (callbacks != null) {
2948               return callbacks.failure(_this, error);
2949             }
2950           };
2951         })(this)
2952       };
2953       return request.execute(saveCallbacks, true);
2954     } else {
2955       return callbacks.failure(this, "Invalid group. Save the group on the server before updating the name.");
2956     }
2957   };
2958 
2959 
2960   /** Saves the latest group values to the server
2961   
2962   <br><br>If the group does not yet exist, it will be created. If the group already exists, the members that have changed will be updated accordingly. If the group already exists and there is no updates of members, it will allways succeed but does not execute update. To change the name of group, use {@link #changeGroupName}.
2963   @param {Object} [callbacks] An object with callback methods defined
2964   @param {Method} callbacks.success The callback method to call on a successful save request
2965   @param {Method} callbacks.failure The callback method to call on a failed save request
2966   @return {Promise} return promise object.
2967         <ul>
2968           <li>fulfill callback function: function(theSavedGroup). theSavedGroup is KiiGroup instance.</li>
2969           <li>reject callback function: function(error). error is an Error instance.
2970             <ul>
2971               <li>error.target is the KiiGroup instance which this method was called on.</li>
2972               <li>error.message</li>
2973               <li>error.addMembersArray is array of KiiUser to be added as memebers of this group.</li>
2974               <li>error.removeMembersArray is array of KiiUser to be removed from the memebers list of this group.</li>
2975             </ul>
2976           </li>
2977         </ul>
2978   @example
2979   // example to use callbacks directly
2980   var group = . . .; // a KiiGroup
2981   group.save({
2982       success: function(theSavedGroup) {
2983           // do something with the saved group
2984       },
2985   
2986       failure: function(theGroup, anErrorString, addMembersArray, removeMembersArray) {
2987           // do something with the error response
2988       }
2989   });
2990   
2991   // example to use Promise
2992   var group = . . .; // a KiiGroup
2993   group.save().then(
2994       function(theSavedGroup) {
2995           // do something with the saved group
2996       },
2997       function(error) {
2998           var theGroup = error.target;
2999           var anErrorString = error.message;
3000           var addMembersArray = error.addMembersArray;
3001           var removeMembersArray = error.removeMembersArray;
3002           // do something with the error response
3003   });
3004    */
3005 
3006   KiiGroup.prototype.save = function(callbacks) {
3007     return new Promise((function(_this) {
3008       return function(resolve, reject) {
3009         var saveCallbacks;
3010         saveCallbacks = {
3011           success: function() {
3012             if (callbacks != null) {
3013               callbacks.success.apply(callbacks, arguments);
3014             }
3015             return resolve(arguments[0]);
3016           },
3017           failure: function() {
3018             var error;
3019             if (callbacks != null) {
3020               callbacks.failure.apply(callbacks, arguments);
3021             }
3022             error = KiiUtilities._Error(arguments[1], _this);
3023             error.addMembersArray = arguments[2];
3024             error.removeMembersArray = arguments[3];
3025             return reject(error);
3026           }
3027         };
3028         return _this._saveUsingCallbacks(saveCallbacks);
3029       };
3030     })(this));
3031   };
3032 
3033   KiiGroup.prototype._saveUsingCallbacks = function(callbacks) {
3034     var data, request, saveCallbacks;
3035     root.Kii.logger("Saving group: " + this.name);
3036     if (this._uuid == null) {
3037       request = this._getRequest({
3038         path: "/groups",
3039         withApp: true
3040       });
3041       request.setContentType("application/vnd.kii.GroupCreationRequest+json");
3042       request.setMethod("POST");
3043       data = {};
3044       if (this._groupName != null) {
3045         data.name = this._groupName;
3046       }
3047       this._setOwnerFromContext(data);
3048       request.setData(data);
3049       saveCallbacks = {
3050         success: (function(_this) {
3051           return function(data, statusCode) {
3052             if (statusCode < 300 && statusCode >= 200) {
3053               _this._setUUID(data.groupID);
3054               return _this._saveMembers(callbacks);
3055             }
3056           };
3057         })(this),
3058         failure: (function(_this) {
3059           return function(error, statusCode) {
3060             var addMembersArray, member, removeMembersArray, userID;
3061             if (callbacks != null) {
3062               addMembersArray = (function() {
3063                 var _ref, _results;
3064                 _ref = this._addMembers;
3065                 _results = [];
3066                 for (userID in _ref) {
3067                   member = _ref[userID];
3068                   _results.push(member);
3069                 }
3070                 return _results;
3071               }).call(_this);
3072               removeMembersArray = (function() {
3073                 var _ref, _results;
3074                 _ref = this._removeMembers;
3075                 _results = [];
3076                 for (userID in _ref) {
3077                   member = _ref[userID];
3078                   _results.push(member);
3079                 }
3080                 return _results;
3081               }).call(_this);
3082               return callbacks.failure(_this, error, addMembersArray, removeMembersArray);
3083             }
3084           };
3085         })(this)
3086       };
3087       return request.execute(saveCallbacks, false);
3088     } else {
3089       return this._saveMembers(callbacks);
3090     }
3091   };
3092 
3093 
3094   /** Saves the latest group values to the server with specified owner.
3095   This method can be used only by the group owner or app admin.
3096   
3097   <br><br>If the group does not yet exist, it will be created. If the group already exists, the members and owner that have changed will be updated accordingly. If the group already exists and there is no updates of members and owner, it will allways succeed but does not execute update. To change the name of group, use {@link #changeGroupName}.
3098   @param {String} user id of owner
3099   @param {Object} [callbacks] An object with callback methods defined
3100   @param {Method} callbacks.success The callback method to call on a successful save request
3101   @param {Method} callbacks.failure The callback method to call on a failed save request
3102   @return {Promise} return promise object.
3103         <ul>
3104           <li>fulfill callback function: function(theSavedGroup). theSavedGroup is KiiGroup instance.</li>
3105           <li>reject callback function: function(error). error is an Error instance.
3106             <ul>
3107               <li>error.target is the KiiGroup instance which this method was called on.</li>
3108               <li>error.message</li>
3109               <li>error.addMembersArray is array of KiiUser to be added as memebers of this group.</li>
3110               <li>error.removeMembersArray is array of KiiUser to be removed from the memebers list of this group.</li>
3111             </ul>
3112           </li>
3113         </ul>
3114   @example
3115   // example to use callbacks directly
3116   var group = . . .; // a KiiGroup
3117   group.saveWithOwner("UserID of owner", {
3118       success: function(theSavedGroup) {
3119           // do something with the saved group
3120       },
3121   
3122       failure: function(theGroup, anErrorString, addMembersArray, removeMembersArray) {
3123           // do something with the error response
3124       }
3125   });
3126   
3127   // example to use Promise
3128   var group = . . .; // a KiiGroup
3129   group.saveWithOwner("UserID of owner").then(
3130       function(theSavedGroup) {
3131           // do something with the saved group
3132       },
3133       function(error) {
3134           var theGroup = error.target;
3135           var anErrorString = error.message;
3136           var addMembersArray = error.addMembersArray;
3137           var removeMembersArray = error.removeMembersArray;
3138           // do something with the error response
3139   });
3140    */
3141 
3142   KiiGroup.prototype.saveWithOwner = function(owner, callbacks) {
3143     return new Promise((function(_this) {
3144       return function(resolve, reject) {
3145         var saveCallbacks;
3146         saveCallbacks = {
3147           success: function() {
3148             if (callbacks != null) {
3149               callbacks.success.apply(callbacks, arguments);
3150             }
3151             return resolve(arguments[0]);
3152           },
3153           failure: function() {
3154             var error;
3155             if (callbacks != null) {
3156               callbacks.failure.apply(callbacks, arguments);
3157             }
3158             error = KiiUtilities._Error(arguments[1], _this);
3159             error.addMembersArray = arguments[2];
3160             error.removeMembersArray = arguments[3];
3161             return reject(error);
3162           }
3163         };
3164         return _this._saveWithOwnerUsingCallbacks(owner, saveCallbacks);
3165       };
3166     })(this));
3167   };
3168 
3169   KiiGroup.prototype._saveWithOwnerUsingCallbacks = function(owner, callbacks) {
3170     var data, request, saveCallbacks, saveMemberCallbacks;
3171     if (this._uuid == null) {
3172       request = this._getRequest({
3173         path: "/groups",
3174         withApp: true
3175       });
3176       request.setContentType("application/vnd.kii.GroupCreationRequest+json");
3177       request.setMethod("POST");
3178       data = {};
3179       if (this._groupName != null) {
3180         data.name = this._groupName;
3181       }
3182       data.owner = owner;
3183       request.setData(data);
3184       saveCallbacks = {
3185         success: (function(_this) {
3186           return function(data, statusCode) {
3187             if (statusCode < 300 && statusCode >= 200) {
3188               _this._setUUID(data.groupID);
3189               return _this._saveMembers(callbacks);
3190             }
3191           };
3192         })(this),
3193         failure: (function(_this) {
3194           return function(error, statusCode) {
3195             var addMembersArray, member, removeMembersArray, userID;
3196             if (callbacks != null) {
3197               addMembersArray = (function() {
3198                 var _ref, _results;
3199                 _ref = this._addMembers;
3200                 _results = [];
3201                 for (userID in _ref) {
3202                   member = _ref[userID];
3203                   _results.push(member);
3204                 }
3205                 return _results;
3206               }).call(_this);
3207               removeMembersArray = (function() {
3208                 var _ref, _results;
3209                 _ref = this._removeMembers;
3210                 _results = [];
3211                 for (userID in _ref) {
3212                   member = _ref[userID];
3213                   _results.push(member);
3214                 }
3215                 return _results;
3216               }).call(_this);
3217               return callbacks.failure(_this, error, addMembersArray, removeMembersArray);
3218             }
3219           };
3220         })(this)
3221       };
3222       return request.execute(saveCallbacks, false);
3223     } else {
3224       saveMemberCallbacks = {
3225         success: (function(_this) {
3226           return function(group) {
3227             return _this._changeOwner(owner, callbacks);
3228           };
3229         })(this),
3230         failure: (function(_this) {
3231           return function(group, error) {
3232             var addMembersArray, member, removeMembersArray, userID;
3233             addMembersArray = (function() {
3234               var _ref, _results;
3235               _ref = this._addMembers;
3236               _results = [];
3237               for (userID in _ref) {
3238                 member = _ref[userID];
3239                 _results.push(member);
3240               }
3241               return _results;
3242             }).call(_this);
3243             removeMembersArray = (function() {
3244               var _ref, _results;
3245               _ref = this._removeMembers;
3246               _results = [];
3247               for (userID in _ref) {
3248                 member = _ref[userID];
3249                 _results.push(member);
3250               }
3251               return _results;
3252             }).call(_this);
3253             return callbacks.failure(_this, error, addMembersArray, removeMembersArray);
3254           };
3255         })(this)
3256       };
3257       return this._saveMembers(saveMemberCallbacks);
3258     }
3259   };
3260 
3261 
3262   /** Updates the local group's data with the group data on the server
3263   
3264   <br><br>The group must exist on the server. Local data will be overwritten.
3265   @param {Object} [callbacks] An object with callback methods defined
3266   @param {Method} callbacks.success The callback method to call on a successful refresh request
3267   @param {Method} callbacks.failure The callback method to call on a failed refresh request
3268   @return {Promise} return promise object.
3269     <ul>
3270       <li>fulfill callback function: function(theRefreshedGroup). theRefreshedGroup is KiiGroup instance.</li>
3271       <li>reject callback function: function(error). error is an Error instance.
3272         <ul>
3273           <li>error.target is the KiiGroup instance which this method was called on.</li>
3274           <li>error.message</li>
3275         </ul>
3276       </li>
3277     </ul>
3278   @example
3279   // example to use callbacks directly
3280   var group = . . .; // a KiiGroup
3281   group.refresh({
3282       success: function(theRefreshedGroup) {
3283           // do something with the refreshed group
3284       },
3285   
3286       failure: function(theGroup, anErrorString) {
3287           // do something with the error response
3288       }
3289   });
3290   
3291   // example to use Promise
3292   var group = . . .; // a KiiGroup
3293   group.refresh().then(
3294       function(theRefreshedGroup) {
3295           // do something with the refreshed group
3296       },
3297       function(error) {
3298           // do something with the error response
3299       }
3300   );
3301    */
3302 
3303   KiiGroup.prototype.refresh = function(callbacks) {
3304     return new Promise((function(_this) {
3305       return function(resolve, reject) {
3306         var refreshCallbacks;
3307         refreshCallbacks = {
3308           success: function() {
3309             if (callbacks != null) {
3310               callbacks.success.apply(callbacks, arguments);
3311             }
3312             return resolve(arguments[0]);
3313           },
3314           failure: function() {
3315             if (callbacks != null) {
3316               callbacks.failure.apply(callbacks, arguments);
3317             }
3318             return reject(KiiUtilities._Error(arguments[1], _this));
3319           }
3320         };
3321         return _this._refreshUsingCallbacks(refreshCallbacks);
3322       };
3323     })(this));
3324   };
3325 
3326   KiiGroup.prototype._refreshUsingCallbacks = function(callbacks) {
3327     var refreshCallbacks, request;
3328     root.Kii.logger("Refreshing group: " + this._groupName);
3329     request = new this._getRequest({
3330       path: "/groups/" + this._uuid,
3331       withApp: true
3332     });
3333     request.setAccept("application/vnd.kii.GroupRetrievalResponse+json");
3334     refreshCallbacks = {
3335       success: (function(_this) {
3336         return function(data, statusCode) {
3337           _this._updateWithJSON(data);
3338           if (callbacks != null) {
3339             return callbacks.success(_this);
3340           }
3341         };
3342       })(this),
3343       failure: (function(_this) {
3344         return function(error, statusCode) {
3345           if (callbacks != null) {
3346             return callbacks.failure(_this, error);
3347           }
3348         };
3349       })(this)
3350     };
3351     return request.execute(refreshCallbacks, false);
3352   };
3353 
3354 
3355   /** Delete the group from the server
3356   @name delete
3357   @memberOf root.KiiGroup#
3358   @function
3359   @param {Object} [callbacks] An object with callback methods defined
3360   @param {Method} callbacks.success The callback method to call on a successful delete request
3361   @param {Method} callbacks.failure The callback method to call on a failed delete request
3362   @return {Promise} return promise object.
3363     <ul>
3364       <li>fulfill callback function: function(theDeletedGroup). theDeletedGroup is KiiGroup instance.</li>
3365       <li>reject callback function: function(error). error is an Error instance.
3366         <ul>
3367           <li>error.target is the KiiGroup instance which this method was called on.</li>
3368           <li>error.message</li>
3369         </ul>
3370       </li>
3371     </ul>
3372   @example
3373   // example to use callbacks directly
3374   var group = . . .; // a KiiGroup
3375   group.delete({
3376       success: function(theDeletedGroup) {
3377           // do something
3378       },
3379   
3380       failure: function(theGroup, anErrorString) {
3381           // do something with the error response
3382       }
3383   });
3384   
3385   // example to use Promise
3386   var group = . . .; // a KiiGroup
3387   group.delete({
3388       success: function(theDeletedGroup) {
3389       },
3390   
3391       failure: function(theGroup, anErrorString) {
3392       }
3393   }).then(
3394       function(theDeletedGroup) {
3395           // do something
3396       },
3397       function(error) {
3398           // do something with the error response
3399       }
3400   );
3401    */
3402 
3403   KiiGroup.prototype["delete"] = function(callbacks) {
3404     return new Promise((function(_this) {
3405       return function(resolve, reject) {
3406         var deleteCallbacks;
3407         deleteCallbacks = {
3408           success: function() {
3409             if (callbacks != null) {
3410               callbacks.success.apply(callbacks, arguments);
3411             }
3412             return resolve(arguments[0]);
3413           },
3414           failure: function() {
3415             if (callbacks != null) {
3416               callbacks.failure.apply(callbacks, arguments);
3417             }
3418             return reject(KiiUtilities._Error(arguments[1], _this));
3419           }
3420         };
3421         return _this._deleteUsingCallbacks(deleteCallbacks);
3422       };
3423     })(this));
3424   };
3425 
3426   KiiGroup.prototype._deleteUsingCallbacks = function(callbacks) {
3427     var deleteCallbacks, request;
3428     root.Kii.logger("Deleting group: " + this._groupName);
3429     request = this._getRequest({
3430       path: "/groups/" + this._uuid,
3431       withApp: true
3432     });
3433     request.setMethod("DELETE");
3434     deleteCallbacks = {
3435       success: (function(_this) {
3436         return function(data, statusCode) {
3437           if (statusCode < 300 && statusCode >= 200 && (callbacks != null)) {
3438             return callbacks.success(_this);
3439           } else if (callbacks != null) {
3440             return callbacks.failure(_this, "Unable to parse response");
3441           }
3442         };
3443       })(this),
3444       failure: (function(_this) {
3445         return function(error, statusCode) {
3446           if (callbacks != null) {
3447             return callbacks.failure(_this, error);
3448           }
3449         };
3450       })(this)
3451     };
3452     return request.execute(deleteCallbacks, true);
3453   };
3454 
3455 
3456   /** Gets the owner of the associated group
3457   
3458   This API does not return all the properties of the owner.
3459   To get all owner properties, {@link KiiUser#refresh} is necessary.
3460   
3461   @param {Object} [callbacks] An object with callback methods defined
3462   @param {Method} callbacks.success The callback method to call on a successful add request
3463   @param {Method} callbacks.failure The callback method to call on a failed add request
3464   @return {Promise} return promise object.
3465     <ul>
3466       <li>fulfill callback function: function(params). params is Array instance.
3467         <ul>
3468           <li>params[0] is the KiiGroup instance which this method was called on.</li>
3469           <li>params[1] is an group owner KiiUser instances.</li>
3470         </ul>
3471       </li>
3472       <li>reject callback function: function(error). error is an Error instance.
3473         <ul>
3474           <li>error.target is the KiiGroup instance which this method was called on.</li>
3475           <li>error.message</li>
3476         </ul>
3477       </li>
3478     </ul>
3479   @example
3480   // example to use callbacks directly
3481   var group = . . .; // a KiiGroup
3482   group.getOwner({
3483       success: function(theGroup, theOwner) {
3484           // do something
3485       },
3486       failure: function(theGroup, anErrorString) {
3487           // do something with the error response
3488       }
3489   });
3490   
3491   // example to use Promise
3492   var group = . . .; // a KiiGroup
3493   group.getOwner().then(
3494       function(params) {
3495           // do something
3496       },
3497       function(error) {
3498           // do something with the error response
3499       }
3500   );
3501    */
3502 
3503   KiiGroup.prototype.getOwner = function(callbacks) {
3504     return new Promise((function(_this) {
3505       return function(resolve, reject) {
3506         var getOwnerCallbacks;
3507         getOwnerCallbacks = {
3508           success: function() {
3509             if (callbacks != null) {
3510               callbacks.success.apply(callbacks, arguments);
3511             }
3512             return resolve(arguments);
3513           },
3514           failure: function() {
3515             if (callbacks != null) {
3516               callbacks.failure.apply(callbacks, arguments);
3517             }
3518             return reject(KiiUtilities._Error(arguments[1], _this));
3519           }
3520         };
3521         return _this._getOwnerUsingCallbacks(getOwnerCallbacks);
3522       };
3523     })(this));
3524   };
3525 
3526   KiiGroup.prototype._getOwnerUsingCallbacks = function(callbacks) {
3527     root.Kii.logger("Getting owner of group " + this._groupName);
3528     return this.refresh({
3529       success: (function(_this) {
3530         return function(group) {
3531           if (callbacks != null) {
3532             return callbacks.success(group, group.getCachedOwner());
3533           }
3534         };
3535       })(this),
3536       failure: (function(_this) {
3537         return function(group, error) {
3538           if (callbacks != null) {
3539             return callbacks.failure(group, error);
3540           }
3541         };
3542       })(this)
3543     });
3544   };
3545 
3546 
3547   /** Creates a reference to a group with the given name
3548   <br><br>
3549   <b>Note:</b>
3550   Returned instance from this API can not operate existing KiiGroup.<br>
3551   If you want to operate existing KiiGroup, please use {@link KiiGroup.groupWithURI}.
3552   
3553   @param {String} groupName An application-specific group name
3554   @returns {KiiGroup} A new KiiGroup reference
3555   @example
3556   var group = new KiiGroup.groupWithName("myGroup");
3557    */
3558 
3559   KiiGroup.groupWithName = function(groupName) {
3560     return root.KiiGroup.groupWithNameAndMembers(groupName, null);
3561   };
3562 
3563 
3564   /** Creates a reference to a group with the given name and a list of default members
3565   <br><br>
3566   <b>Note:</b>
3567   Returned instance from this API can not operate existing KiiGroup.<br>
3568   If you want to operate existing KiiGroup, please use {@link KiiGroup.groupWithURI}.
3569   
3570   @param {String} groupName An application-specific group name
3571   @param {Array} members An array of KiiUser objects to add to the group
3572   @returns {KiiGroup} A new KiiGroup reference
3573   @example
3574   var group = new KiiGroup.groupWithName("myGroup", members);
3575    */
3576 
3577   KiiGroup.groupWithNameAndMembers = function(groupName, members) {
3578     var group;
3579     group = new root.KiiGroup();
3580     group._setName(groupName);
3581     group._setAddMembers(members);
3582     return group;
3583   };
3584 
3585 
3586   /** Instantiate KiiGroup that refers to existing group which has specified ID.
3587   You have to specify the ID of existing KiiGroup. Unlike KiiObject,
3588   you can not assign ID in the client side.<br>
3589   <b>NOTE</b>: This API does not access to the server.
3590   After instantiation, call {@link KiiGroup#refresh} to fetch the properties.
3591   @param groupId ID of the KiiGroup to instantiate.
3592   @return instance of KiiGroup.
3593   @throws {InvalidArgumentException} when passed groupID is empty or null.
3594   @example
3595   var group = new KiiUser.groupWithID("__GROUP_ID__");
3596    */
3597 
3598   KiiGroup.groupWithID = function(groupID) {
3599     var group;
3600     if ((groupID == null) || groupID === "") {
3601       throw new root.InvalidArgumentException('groupID should not null or empty');
3602     }
3603     group = new root.KiiGroup();
3604     group._setUUID(groupID);
3605     return group;
3606   };
3607 
3608 
3609   /** Generate a new KiiGroup based on a given URI
3610   <br><br>
3611   <b>Note:</b>
3612   Returned instance from this API can operate existing KiiGroup.<br>
3613   If you want to create a new KiiGroup, please use {@link KiiGroup.groupWithName}.
3614   
3615   @param {String} uri The URI of the group to be represented
3616   @returns {KiiGroup} A new KiiGroup with its parameters filled in from the URI
3617   @throws {InvalidURIException} If the URI given is invalid
3618   @example
3619   var group = new KiiGroup.groupWithURI("kiicloud://myuri");
3620    */
3621 
3622   KiiGroup.groupWithURI = function(uri) {
3623     var compLength, components, group, newURI;
3624     group = null;
3625     newURI = uri.substr("kiicloud://".length);
3626     components = newURI.split("/");
3627     compLength = components.length;
3628     if (compLength > 0) {
3629       group = new root.KiiGroup();
3630       group._setUUID(components[compLength - 1]);
3631     } else {
3632       throw new root.InvalidURIException;
3633     }
3634     return group;
3635   };
3636 
3637   KiiGroup._groupWithJSON = function(json) {
3638     var group;
3639     group = new root.KiiGroup();
3640     if (json.groupID != null) {
3641       group._setUUID(json.groupID);
3642     }
3643     if (json.name != null) {
3644       group._setName(json.name);
3645     }
3646     if (json.owner != null) {
3647       group._setOwner(root.KiiUser.userWithID(json.owner));
3648     }
3649     return group;
3650   };
3651 
3652   KiiGroup.prototype._updateWithJSON = function(json) {
3653     if (json.groupID != null) {
3654       this._setUUID(json.groupID);
3655     }
3656     if (json.name != null) {
3657       this._setName(json.name);
3658     } else {
3659       this._setName(null);
3660     }
3661     if (json.owner != null) {
3662       return this._setOwner(this._userWithID(json.owner));
3663     } else {
3664       return this._setOwner(null);
3665     }
3666   };
3667 
3668   KiiGroup.prototype._getRequest = function(spec) {
3669     var path, request, withApp;
3670     path = spec.path;
3671     withApp = spec.withApp;
3672     request = new KiiRequest(path, withApp);
3673     return request;
3674   };
3675 
3676   KiiGroup.prototype._userWithID = function(id) {
3677     var user;
3678     user = root.KiiUser.userWithID(id);
3679     return user;
3680   };
3681 
3682   KiiGroup.prototype._setOwnerFromContext = function(data) {
3683     if (root.Kii.getCurrentUser() != null) {
3684       this._owner = root.Kii.getCurrentUser();
3685       return data.owner = this._owner.getUUID();
3686     }
3687   };
3688 
3689 
3690   /**
3691   Instantiate topic belongs to this group.
3692   @param {String} topicName name of the topic. Must be a not empty string.
3693   @return {KiiTopic} topic instance.
3694    */
3695 
3696   KiiGroup.prototype.topicWithName = function(topicName) {
3697     var id, puri;
3698     if (typeof topicName !== "string" || topicName === "") {
3699       throw new root.InvalidArgumentException('topicName should not null or empty');
3700     }
3701     id = this.getID();
3702     if (!id) {
3703       throw 'can not instantiate topic from instance which doesn\'t have ID';
3704     }
3705     puri = this._getHttpURI();
3706     return new root.KiiTopic(puri, topicName);
3707   };
3708 
3709 
3710   /** Gets a list of topics in this group scope
3711   @param {Object} [callbacks] An object with callback methods defined
3712   @param {Method} callbacks.success The callback method to call on a successful list request
3713   @param {Method} callbacks.failure The callback method to call on a failed list request
3714   @param {String} [paginationKey] You can specify the pagination key with the nextPaginationKey passed by callbacks.success. If empty string or no string object is provided, this API regards no paginationKey specified.
3715   @return {Promise} return promise object.
3716       <ul>
3717         <li>fulfill callback function: function(params). params is Array instance.
3718           <ul>
3719             <li>params[0] is array of KiiTopic instances.</li>
3720             <li>params[1] is string of nextPaginationKey.</li>
3721           </ul>
3722         </li>
3723         <li>reject callback function: function(error). error is an Error instance.
3724           <ul>
3725             <li>error.target is the KiiGroup instance which this method was called on. </li>
3726             <li>error.message</li>
3727           </ul>
3728         </li>
3729       </ul>
3730   @example
3731   // example to use callbacks directly
3732   var group = . . .; // a KiiGroup
3733   group.listTopics({
3734       success: function(topicList, nextPaginationKey) {
3735           // do something with the result
3736           for(var i=0; i<topicList.length; i++){
3737               var topic = topicList[i];
3738           }
3739           if (nextPaginationKey != null) {
3740               group.listTopics({
3741                   success: function(topicList, nextPaginationKey) {...},
3742                   failure: function(anErrorString) {...}
3743               }, nextPaginationKey);
3744           }
3745       },
3746       failure: function(anErrorString) {
3747           // do something with the error response
3748       }
3749   });
3750   
3751   // example to use promise
3752   var group = . . .; // a KiiGroup
3753   group.listTopics().then(
3754       function(params) {
3755           var topicList = params[0];
3756           var nextPaginationKey = params[1];
3757           // do something with the result
3758           for(var i=0; i<topicList.length; i++){
3759               var topic = topicList[i];
3760           }
3761           if (nextPaginationKey != null) {
3762               group.listTopics(null, nextPaginationKey).then(
3763                   function(params) {...},
3764                   function(error) {...}
3765               );
3766           }
3767       },
3768       function(error) {
3769           // do something with the error response
3770       }
3771   );
3772    */
3773 
3774   KiiGroup.prototype.listTopics = function(callbacks, paginationKey) {
3775     return new Promise((function(_this) {
3776       return function(resolve, reject) {
3777         var listTopicsCallbacks;
3778         listTopicsCallbacks = {
3779           success: function() {
3780             if (callbacks != null) {
3781               callbacks.success.apply(callbacks, arguments);
3782             }
3783             return resolve(arguments);
3784           },
3785           failure: function() {
3786             if (callbacks != null) {
3787               callbacks.failure.apply(callbacks, arguments);
3788             }
3789             return reject(arguments[0]);
3790           }
3791         };
3792         return _this._listTopicsUsingCallbacks(listTopicsCallbacks, paginationKey);
3793       };
3794     })(this));
3795   };
3796 
3797   KiiGroup.prototype._listTopicsUsingCallbacks = function(callbacks, paginationKey) {
3798     var listCallbacks, uri, wrapper;
3799     uri = "" + (this._getHttpURI()) + "/topics";
3800     if (typeof paginationKey === "string" && paginationKey !== "") {
3801       uri = uri + "?paginationKey=" + encodeURIComponent(paginationKey);
3802     }
3803     wrapper = KiiXHRWrapperFactory.createXHRWrapper('GET', uri);
3804     wrapper.setKiiHeaders();
3805     this._setAuthToken(wrapper);
3806     listCallbacks = {
3807       success: (function(_this) {
3808         return function() {
3809           var json, topic, topics, _i, _len, _ref;
3810           json = JSON.parse(wrapper.xhr.responseText);
3811           topics = [];
3812           _ref = json.topics;
3813           for (_i = 0, _len = _ref.length; _i < _len; _i++) {
3814             topic = _ref[_i];
3815             topics.push(_this.topicWithName(topic.topicID));
3816           }
3817           return callbacks != null ? callbacks.success(topics, (json.paginationKey === void 0 ? null : json.paginationKey)) : void 0;
3818         };
3819       })(this),
3820       failure: (function(_this) {
3821         return function() {
3822           var errObj, errString;
3823           errString = wrapper.getErrorString("list topics");
3824           errObj = KiiUtilities._Error(errString, _this);
3825           return callbacks != null ? callbacks.failure(errObj) : void 0;
3826         };
3827       })(this)
3828     };
3829     return wrapper.send(listCallbacks);
3830   };
3831 
3832   KiiGroup.prototype._getHttpURI = function() {
3833     return "" + (root.Kii.getBaseURL()) + "/apps/" + (root.Kii.getAppID()) + "/groups/" + (this.getID());
3834   };
3835 
3836   KiiGroup.prototype._setAuthToken = function(wrapper) {
3837     return wrapper.setCurrentUserToken();
3838   };
3839 
3840   return KiiGroup;
3841 
3842 })();
3843 
3844 
3845 /**
3846     @class Represents a KiiObject object
3847     @exports root.KiiObject as KiiObject
3848  */
3849 
3850 root.KiiObject = (function() {
3851 
3852   /** Get the UUID of the given object, assigned by the server
3853   @returns {String}
3854    */
3855   KiiObject.prototype.getUUID = function() {
3856     return this._uuid;
3857   };
3858 
3859   KiiObject.prototype._setUUID = function(_uuid) {
3860     this._uuid = _uuid;
3861   };
3862 
3863 
3864   /** Get Id of the object or null if the object ID hasn't been assigned.
3865   @returns {String}
3866    */
3867 
3868   KiiObject.prototype.getID = function() {
3869     return this._uuid;
3870   };
3871 
3872 
3873   /** Get the server's creation date of this object
3874   @returns {String}
3875    */
3876 
3877   KiiObject.prototype.getCreated = function() {
3878     return this._created;
3879   };
3880 
3881   KiiObject.prototype._setCreated = function(_created) {
3882     this._created = _created;
3883   };
3884 
3885 
3886   /** Get the modified date of the given object, assigned by the server
3887   @returns {String}
3888    */
3889 
3890   KiiObject.prototype.getModified = function() {
3891     return this._modified;
3892   };
3893 
3894   KiiObject.prototype._setModified = function(_modified) {
3895     this._modified = _modified;
3896   };
3897 
3898 
3899   /** Get the application-defined type name of the object
3900   @returns {String} type of this object. null or undefined if none exists
3901    */
3902 
3903   KiiObject.prototype.getObjectType = function() {
3904     return this._objectType;
3905   };
3906 
3907   KiiObject.prototype._setObjectType = function(_objectType) {
3908     this._objectType = _objectType;
3909   };
3910 
3911   KiiObject.prototype.getBucket = function() {
3912     root.Kii.logger("GEtting bucket " + this._bucket);
3913     return this._bucket;
3914   };
3915 
3916   KiiObject.prototype._setBucket = function(_bucket) {
3917     this._bucket = _bucket;
3918   };
3919 
3920 
3921   /** Get the body content-type.
3922   It will be updated after the success of {@link KiiObject#uploadBody} and {@link KiiObject#downloadBody}
3923   returns null or undefined when this object doesn't have body content-type information.
3924   @returns {String} content-type of object body
3925    */
3926 
3927   KiiObject.prototype.getBodyContentType = function() {
3928     return this._bodyContentType;
3929   };
3930 
3931   KiiObject.prototype._setBodyContentType = function(_bodyContentType) {
3932     this._bodyContentType = _bodyContentType;
3933   };
3934 
3935   function KiiObject() {
3936     this._deleteBodyUsingCallbacks = __bind(this._deleteBodyUsingCallbacks, this);
3937     this.deleteBody = __bind(this.deleteBody, this);
3938     this._publishBodyExpiresInUsingCallbacks = __bind(this._publishBodyExpiresInUsingCallbacks, this);
3939     this.publishBodyExpiresIn = __bind(this.publishBodyExpiresIn, this);
3940     this._publishBodyExpiresAtUsingCallbacks = __bind(this._publishBodyExpiresAtUsingCallbacks, this);
3941     this.publishBodyExpiresAt = __bind(this.publishBodyExpiresAt, this);
3942     this._publishBodyUsingCallbacks = __bind(this._publishBodyUsingCallbacks, this);
3943     this.publishBody = __bind(this.publishBody, this);
3944     this._downloadBodyUsingCallbacks = __bind(this._downloadBodyUsingCallbacks, this);
3945     this.downloadBody = __bind(this.downloadBody, this);
3946     this._uploadBodyUsingCallbacks = __bind(this._uploadBodyUsingCallbacks, this);
3947     this.uploadBody = __bind(this.uploadBody, this);
3948     this._moveBodyUsingCallbacks = __bind(this._moveBodyUsingCallbacks, this);
3949     this.moveBody = __bind(this.moveBody, this);
3950     this._parseObjectUri = __bind(this._parseObjectUri, this);
3951     this._userWithID = __bind(this._userWithID, this);
3952     this._setAuthorizationHeader = __bind(this._setAuthorizationHeader, this);
3953     this._getToken = __bind(this._getToken, this);
3954     this._getRequest = __bind(this._getRequest, this);
3955     this._setETag = __bind(this._setETag, this);
3956     this._deleteUsingCallbacks = __bind(this._deleteUsingCallbacks, this);
3957     this["delete"] = __bind(this["delete"], this);
3958     this._refreshUsingCallbacks = __bind(this._refreshUsingCallbacks, this);
3959     this.refresh = __bind(this.refresh, this);
3960     this._saveUsingCallbacks = __bind(this._saveUsingCallbacks, this);
3961     this.save = __bind(this.save, this);
3962     this._saveAllFieldsUsingCallbacks = __bind(this._saveAllFieldsUsingCallbacks, this);
3963     this.saveAllFields = __bind(this.saveAllFields, this);
3964     this._performUpdate = __bind(this._performUpdate, this);
3965     this._performSave = __bind(this._performSave, this);
3966     this._updateWithJSON = __bind(this._updateWithJSON, this);
3967     this._convertToObjectType = __bind(this._convertToObjectType, this);
3968     this.objectURI = __bind(this.objectURI, this);
3969     this.objectACL = __bind(this.objectACL, this);
3970     this.getGeoPoint = __bind(this.getGeoPoint, this);
3971     this.setGeoPoint = __bind(this.setGeoPoint, this);
3972     this.remove = __bind(this.remove, this);
3973     this.getKeys = __bind(this.getKeys, this);
3974     this.get = __bind(this.get, this);
3975     this.set = __bind(this.set, this);
3976     this._getPath = __bind(this._getPath, this);
3977     this._setBodyContentType = __bind(this._setBodyContentType, this);
3978     this.getBodyContentType = __bind(this.getBodyContentType, this);
3979     this._setBucket = __bind(this._setBucket, this);
3980     this.getBucket = __bind(this.getBucket, this);
3981     this._setObjectType = __bind(this._setObjectType, this);
3982     this.getObjectType = __bind(this.getObjectType, this);
3983     this._setModified = __bind(this._setModified, this);
3984     this.getModified = __bind(this.getModified, this);
3985     this._setCreated = __bind(this._setCreated, this);
3986     this.getCreated = __bind(this.getCreated, this);
3987     this.getID = __bind(this.getID, this);
3988     this._setUUID = __bind(this._setUUID, this);
3989     this.getUUID = __bind(this.getUUID, this);
3990     this._customInfo = {};
3991     this._alteredFields = [];
3992   }
3993 
3994   KiiObject.prototype._getPath = function() {
3995     var path;
3996     if (this._bucket.getUser() != null) {
3997       path = "/users/" + (this._bucket.getUser().getUUID()) + "/buckets/" + (this._bucket._getQualifiedBucketName()) + "/objects/";
3998     } else if (this._bucket.getGroup() != null) {
3999       path = "/groups/" + (this._bucket.getGroup().getUUID()) + "/buckets/" + (this._bucket._getQualifiedBucketName()) + "/objects/";
4000     } else if (this._bucket.getThing() != null) {
4001       path = "/things/" + (this._bucket.getThing().getThingID()) + "/buckets/" + (this._bucket._getQualifiedBucketName()) + "/objects/";
4002     } else {
4003       path = "/buckets/" + (this._bucket._getQualifiedBucketName()) + "/objects/";
4004     }
4005     if (this._uuid != null) {
4006       path += this._uuid;
4007     }
4008     return path;
4009   };
4010 
4011 
4012   /** Sets a key/value pair to a KiiObject
4013   
4014   <br><br>If the key already exists, its value will be written over.
4015   <br><b>NOTE: Before involving floating point value, please consider using integer instead. For example, use percentage, permil, ppm, etc.</br></b>
4016   The reason is:
4017    <li>Will dramatically improve the performance of bucket query.</li>
4018    <li>Bucket query does not support the mixed result of integer and floating point.
4019    ex.) If you use same key for integer and floating point and inquire object with the integer value, objects which has floating point value with the key would not be evaluated in the query. (and vice versa)</li>
4020   @param {String} key The key to set.
4021   if null, empty string or string prefixed with '_' is specified, silently ignored and have no effect.
4022   We don't check if actual type is String or not. If non-string type is specified, it will be encoded as key by JSON.stringify()
4023   @param {Object} value The value to be set. Object must be JSON-encodable type (dictionary, array, string, number, boolean)
4024   We don't check actual type of the value. It will be encoded as value by JSON.stringify()
4025   @example
4026   var obj = . . .; // a KiiObject
4027   obj.set("score", 4298);
4028    */
4029 
4030   KiiObject.prototype.set = function(key, value) {
4031     if (!KiiUtilities._isNonEmptyString(key) || key.indexOf("_") === 0) {
4032       root.Kii.logger("[WARN] Reserved key is used for custom field. key=" + key);
4033       return;
4034     }
4035     this._customInfo[key] = value;
4036     return this._alteredFields.push(key);
4037   };
4038 
4039 
4040   /** Gets the value associated with the given key
4041   @param {String} key The key to retrieve
4042   @returns {Object} The object associated with the key. null or undefined if none exists
4043   @example
4044   var obj = . . .; // a KiiObject
4045   var score = obj.get("score");
4046    */
4047 
4048   KiiObject.prototype.get = function(key) {
4049     return this._customInfo[key];
4050   };
4051 
4052 
4053   /** Gets the array object that contains all keys of custom field.
4054   The array of keys from local cache will be returned.
4055   To get the latest array of keys from cloud, calling refresh() is necessary prior calling this method.
4056   The returned array object does not include reserved keys such as _created, _modified, etc.
4057   @returns {Array} keys An array of all keys of custom field.
4058   @example
4059   var obj = . . .; // a KiiObject
4060   for(var key of obj.keys()) {
4061   }
4062    */
4063 
4064   KiiObject.prototype.getKeys = function() {
4065     var key, keys;
4066     keys = [];
4067     for (key in this._customInfo) {
4068       keys.push(key);
4069     }
4070     return keys;
4071   };
4072 
4073 
4074   /** Removes a pair of key/value from this object.
4075   This pair is also removed from server when saveAllFields() is succeeded. 
4076   @param {String} key The key to be removed
4077   @example
4078   var obj = . . .; // a KiiObject
4079   obj.remove("score");
4080    */
4081 
4082   KiiObject.prototype.remove = function(key) {
4083     var index;
4084     delete this._customInfo[key];
4085     index = this._alteredFields.indexOf(key);
4086     if (index >= 0) {
4087       return this._alteredFields.splice(index, 1);
4088     }
4089   };
4090 
4091 
4092   /**
4093       Set Geo point to this object with the specified key.
4094       @param {String} key The key to set.
4095       @param {KiiGeoPoint} KiiGeoPoint to be tied to the specified key.
4096       @throws {String}  Specified kiiGeoPint is not an instance of KiiGeoPoint.
4097    */
4098 
4099   KiiObject.prototype.setGeoPoint = function(key, kiiGeoPoint) {
4100     if (!(kiiGeoPoint instanceof root.KiiGeoPoint)) {
4101       throw root.InvalidArgumentException("Specified kiiGeoPoint is not an instance of KiiGeoPoint");
4102     }
4103     this._customInfo[key] = kiiGeoPoint._toDict();
4104     return this._alteredFields.push(key);
4105   };
4106 
4107 
4108   /**
4109       Gets the geo point associated with the given key.
4110       @param {String} key The key of the geo point to retrieve.
4111       @returns {KiiGeoPoint} KiiGeoPoint tied to the key. null if null exists.
4112    */
4113 
4114   KiiObject.prototype.getGeoPoint = function(key) {
4115     var lat, lon, point;
4116     point = this._customInfo[key];
4117     lat = point.lat;
4118     lon = point.lon;
4119     return root.KiiGeoPoint.geoPoint(lat, lon);
4120   };
4121 
4122 
4123   /** Get the ACL handle for this file
4124   
4125   <br><br>Any KiiACLEntry objects added or revoked from this ACL object will be appended to/removed from the server on ACL save.
4126   	@returns {KiiACL} A KiiACL object associated with this KiiObject
4127   	@example
4128   	var obj = . . .; // a KiiObject
4129   	var acl = obj.objectACL();
4130    */
4131 
4132   KiiObject.prototype.objectACL = function() {
4133     return root.KiiACL.aclWithParent(this);
4134   };
4135 
4136 
4137   /** Get a specifically formatted string referencing the object
4138   
4139   <br><br>The object must exist in the cloud (have a valid UUID).
4140   @returns {String} A URI string based on the current object. null if a URI couldn't be generated.
4141   @example
4142   var obj = . . .; // a KiiObject
4143   var uri = obj.objectURI();
4144    */
4145 
4146   KiiObject.prototype.objectURI = function() {
4147     var base, uri;
4148     base = "kiicloud://";
4149     if ((this._bucket != null) && (this._uuid != null)) {
4150       uri = base;
4151       if (this._bucket.getGroup() != null) {
4152         uri += "groups/" + (this._bucket.getGroup().getUUID()) + "/";
4153       } else if (this._bucket.getUser() != null) {
4154         uri += "users/" + (this._bucket.getUser().getUUID()) + "/";
4155       } else if (this._bucket.getThing() != null) {
4156         uri += "things/" + (this._bucket.getThing().getThingID()) + "/";
4157       }
4158       uri += "buckets/" + (this._bucket._getQualifiedBucketName()) + "/objects/" + this._uuid;
4159     }
4160     return uri;
4161   };
4162 
4163   KiiObject.prototype._convertToObjectType = function(contentType) {
4164     var result;
4165     if ('application/json' === contentType) {
4166       return {
4167         'success': true,
4168         'type': null
4169       };
4170     }
4171     result = contentType.match(RegExp("$application/vnd\\." + (root.Kii.getAppID()) + "\\.([^\\.])+\\+json"));
4172     if (result != null) {
4173       return {
4174         'success': true,
4175         'type': result
4176       };
4177     }
4178     return {
4179       'success': false,
4180       'type': null
4181     };
4182   };
4183 
4184   KiiObject.prototype._updateWithJSON = function(json, patch) {
4185     var key, val, _results;
4186     if (!patch) {
4187       this._customInfo = {};
4188     }
4189     _results = [];
4190     for (key in json) {
4191       val = json[key];
4192       if (key === "_id") {
4193         if (this._uuid == null) {
4194           root.Kii.logger("Setting uuid: " + val);
4195           _results.push(this._uuid = val);
4196         } else {
4197           _results.push(void 0);
4198         }
4199       } else if (key === "_created") {
4200         _results.push(this._created = val);
4201       } else if (key === "_modified") {
4202         _results.push(this._modified = val);
4203       } else if (key === "_owner") {
4204         _results.push(this._owner = this._userWithID(val));
4205       } else if (key === "_dataType") {
4206         _results.push(this._objectType = val);
4207       } else if (key === "_calculated") {
4208         _results.push(this._customInfo[key] = val);
4209       } else if (key[0] !== "_") {
4210         _results.push(this._customInfo[key] = val);
4211       } else if (key === "_version") {
4212         _results.push(this._etag = val);
4213       } else {
4214         _results.push(void 0);
4215       }
4216     }
4217     return _results;
4218   };
4219 
4220   KiiObject.prototype._performSave = function(callbacks) {
4221     var data, path, request, saveCallbacks;
4222     path = this._getPath();
4223     path = path.slice(0, +(path.length - 2) + 1 || 9e9);
4224     request = new this._getRequest({
4225       path: path,
4226       withApp: true
4227     });
4228     request.setMethod("POST");
4229     data = this._customInfo;
4230     request.setData(data);
4231     if (this._objectType != null) {
4232       request.setContentType("application/vnd." + (root.Kii.getAppID()) + "." + this._objectType + "+json");
4233     }
4234     saveCallbacks = {
4235       success: (function(_this) {
4236         return function(data, statusCode, headers) {
4237           var result;
4238           if (statusCode < 300 && statusCode >= 200) {
4239             _this._etag = headers['etag'];
4240             if (data['objectID'] != null) {
4241               _this._uuid = data['objectID'];
4242               if (data['createdAt'] != null) {
4243                 _this._created = data['createdAt'];
4244               }
4245               if (data['dataType'] != null) {
4246                 result = _this._convertToObjectType(data['dataType']);
4247                 if (result['success']) {
4248                   _this._objectType = result['type'];
4249                 }
4250               }
4251               _this._modified = _this._created;
4252               _this._alteredFields = [];
4253               if (callbacks != null) {
4254                 return callbacks.success(_this);
4255               }
4256             } else {
4257               return callbacks.failure(_this, "No objectID response");
4258             }
4259           } else if (callbacks != null) {
4260             return callbacks.failure(_this, "Unable to parse response");
4261           }
4262         };
4263       })(this),
4264       failure: (function(_this) {
4265         return function(error, statusCode) {
4266           if (callbacks != null) {
4267             return callbacks.failure(_this, error);
4268           }
4269         };
4270       })(this)
4271     };
4272     return request.execute(saveCallbacks, false);
4273   };
4274 
4275   KiiObject.prototype._performUpdate = function(patch, callbacks, overwrite) {
4276     var data, isSaved, key, path, request, updateCallbacks, _i, _len, _ref;
4277     path = this._getPath();
4278     request = new this._getRequest({
4279       path: path,
4280       withApp: true
4281     });
4282     data = {};
4283     if (patch) {
4284       request.addHeader("X-HTTP-Method-Override", "PATCH");
4285       request.setMethod("POST");
4286       _ref = this._alteredFields;
4287       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
4288         key = _ref[_i];
4289         data[key] = this._customInfo[key];
4290       }
4291     } else {
4292       request.setMethod("PUT");
4293       data = this._customInfo;
4294     }
4295     request.setData(data);
4296     isSaved = this._created > 0;
4297     if (!overwrite) {
4298       if (isSaved) {
4299         if (this._etag == null) {
4300           callbacks.failure(this, "IllegalState! Call KiiObject#refresh() prior call this method.");
4301           return;
4302         }
4303         request.addHeader("If-Match", this._etag);
4304       } else {
4305         if (patch && (this._etag == null)) {
4306           callbacks.failure(this, "IllegalState! Call KiiObject#refresh() prior call this method.");
4307           return;
4308         }
4309         request.addHeader("If-None-Match", "*");
4310       }
4311     }
4312     if (this._objectType != null) {
4313       request.setContentType("application/vnd." + (root.Kii.getAppID()) + "." + this._objectType + "+json");
4314     }
4315     updateCallbacks = {
4316       success: (function(_this) {
4317         return function(data, statusCode, headers) {
4318           if (statusCode < 300 && statusCode >= 200) {
4319             _this._etag = headers['etag'];
4320             if (patch) {
4321               _this._updateWithJSON(data, true);
4322             } else {
4323               if (data['createdAt'] != null) {
4324                 _this._created = data['createdAt'];
4325               }
4326               if (data['modifiedAt'] != null) {
4327                 _this._modified = data['modifiedAt'];
4328               }
4329             }
4330             _this._alteredFields = [];
4331             if (callbacks != null) {
4332               return callbacks.success(_this);
4333             }
4334           } else if (callbacks != null) {
4335             return callbacks.failure(_this, "Unable to parse response");
4336           }
4337         };
4338       })(this),
4339       failure: (function(_this) {
4340         return function(error, statusCode) {
4341           if (callbacks != null) {
4342             return callbacks.failure(_this, error);
4343           }
4344         };
4345       })(this)
4346     };
4347     return request.execute(updateCallbacks, false);
4348   };
4349 
4350 
4351   /** Create or update the KiiObject on KiiCloud.
4352   <br><br>When call this method for the object that has not saved on cloud, will send all fields.
4353   Call this method for the object that has saved on cloud, Update all field of this object.
4354   @param {Object} [callbacks] An object with callback methods defined
4355       sucess: function called when save succeeded.<br>
4356       failure: function called when save failed.
4357   @param overwrite optional, true by default.
4358           <ul>
4359             <li><b>If overwrite is true:</b>
4360             <ul>
4361               <li>If a KiiObject with the same ID exists in cloud, the local copy will overwrite the remote copy, even if the remote copy is newer. </li>
4362             </ul>
4363               <li><b>Otherwise:</b>
4364             <ul>
4365               <li>If a KiiObject with the same ID exists in cloud and the remote copy is newer, save will fail.</li>
4366             </ul>
4367           </ul>
4368   @return {Promise} return promise object.
4369     <ul>
4370       <li>fulfill callback function: function(theSavedObject). theSavedObject is KiiObject instance.</li>
4371       <li>reject callback function: function(error). error is an Error instance.
4372         <ul>
4373           <li>error.target is the KiiObject instance which this method was called on.</li>
4374           <li>error.message</li>
4375         </ul>
4376       </li>
4377     </ul>
4378   @example
4379   // example to use callbacks directly
4380   var obj = . . .; // a KiiObject
4381   obj.saveAllFields({
4382       success: function(theSavedObject) {
4383           // do something with the saved object
4384       },
4385   
4386       failure: function(theObject, anErrorString) {
4387           // do something with the error response
4388       }
4389   });
4390   
4391   // example to use Promise
4392   var obj = . . .; // a KiiObject
4393   obj.saveAllFields().then(
4394       function(theSavedObject) {
4395           // do something with the saved object
4396       },
4397       function(error) {
4398           // do something with the error response
4399       }
4400   );
4401    */
4402 
4403   KiiObject.prototype.saveAllFields = function(callbacks, overwrite) {
4404     if (overwrite == null) {
4405       overwrite = true;
4406     }
4407     return new Promise((function(_this) {
4408       return function(resolve, reject) {
4409         var saveCallbacks;
4410         saveCallbacks = {
4411           success: function() {
4412             if (callbacks != null) {
4413               callbacks.success.apply(callbacks, arguments);
4414             }
4415             return resolve(arguments[0]);
4416           },
4417           failure: function() {
4418             if (callbacks != null) {
4419               callbacks.failure.apply(callbacks, arguments);
4420             }
4421             return reject(KiiUtilities._Error(arguments[1], _this));
4422           }
4423         };
4424         return _this._saveAllFieldsUsingCallbacks(saveCallbacks, overwrite);
4425       };
4426     })(this));
4427   };
4428 
4429   KiiObject.prototype._saveAllFieldsUsingCallbacks = function(callbacks, overwrite) {
4430     if (overwrite == null) {
4431       overwrite = true;
4432     }
4433     if (this._uuid != null) {
4434       return this._performUpdate(false, callbacks, overwrite);
4435     } else {
4436       return this._performSave(callbacks);
4437     }
4438   };
4439 
4440 
4441   /** Create or update the KiiObject on KiiCloud.
4442   <br><br>When call this method for the object that has not saved on cloud, will send all fields.
4443   Call this method for the object that has saved on cloud, Update only updated fields.
4444   Do not send fields that has not updated locally. To send all fields regardless of updates, call {@link KiiObject#saveAllFields}.
4445   @param {Object} [callbacks] An object with callback methods defined
4446       sucess: function called when save succeeded.<br>
4447       failure: function called when save failed.
4448   @param overwrite optional, true by default.
4449           <ul>
4450             <li><b>If overwrite is true:</b>
4451             <ul>
4452               <li>If a KiiObject with the same ID exists in cloud, the local copy will overwrite the remote copy, even if the remote copy is newer. </li>
4453             </ul>
4454               <li><b>Otherwise:</b>
4455             <ul>
4456               <li>If a KiiObject with the same ID exists in cloud and the remote copy is newer, save will fail.</li>
4457             </ul>
4458           </ul>
4459   @return {Promise} return promise object.
4460     <ul>
4461       <li>fulfill callback function: function(theSavedObject). theSavedObject is KiiObject instance.</li>
4462       <li>reject callback function: function(error). error is an Error instance.
4463         <ul>
4464           <li>error.target is the KiiObject instance which this method was called on.</li>
4465           <li>error.message</li>
4466         </ul>
4467       </li>
4468     </ul>
4469   @example
4470   // example to use callbacks directly
4471   var obj = . . .; // a KiiObject
4472   obj.save({
4473       success: function(theSavedObject) {
4474           // do something with the saved object
4475       },
4476   
4477       failure: function(theObject, anErrorString) {
4478           // do something with the error response
4479       }
4480   });
4481   
4482   // example to use Promise
4483   var obj = . . .; // a KiiObject
4484   obj.save().then(
4485       function(theSavedObject) {
4486           // do something with the saved object
4487       },
4488       function(error) {
4489           // do something with the error response
4490       }
4491   );
4492    */
4493 
4494   KiiObject.prototype.save = function(callbacks, overwrite) {
4495     if (overwrite == null) {
4496       overwrite = true;
4497     }
4498     return new Promise((function(_this) {
4499       return function(resolve, reject) {
4500         var saveCallbacks;
4501         saveCallbacks = {
4502           success: function() {
4503             if (callbacks != null) {
4504               callbacks.success.apply(callbacks, arguments);
4505             }
4506             return resolve(arguments[0]);
4507           },
4508           failure: function() {
4509             if (callbacks != null) {
4510               callbacks.failure.apply(callbacks, arguments);
4511             }
4512             return reject(KiiUtilities._Error(arguments[1], _this));
4513           }
4514         };
4515         return _this._saveUsingCallbacks(saveCallbacks, overwrite);
4516       };
4517     })(this));
4518   };
4519 
4520   KiiObject.prototype._saveUsingCallbacks = function(callbacks, overwrite) {
4521     if (overwrite == null) {
4522       overwrite = true;
4523     }
4524     if (this._uuid != null) {
4525       return this._performUpdate(true, callbacks, overwrite);
4526     } else {
4527       return this._performSave(callbacks);
4528     }
4529   };
4530 
4531 
4532   /** Updates the local object's data with the user data on the server
4533   
4534   <br><br>The object must exist on the server. Local data will be overwritten.
4535   @param {Object} [callbacks] An object with callback methods defined
4536   @param {Method} callbacks.success The callback method to call on a successful refresh request
4537   @param {Method} callbacks.failure The callback method to call on a failed refresh request
4538   @return {Promise} return promise object.
4539     <ul>
4540       <li>fulfill callback function: function(theRefreshedObject). theRefreshedObject is KiiObject instance.</li>
4541       <li>reject callback function: function(error). error is an Error instance.
4542         <ul>
4543           <li>error.target is the KiiObject instance which this method was called on.</li>
4544           <li>error.message</li>
4545         </ul>
4546       </li>
4547     </ul>
4548   @example
4549   // example to use callbacks directly
4550   var obj = . . .; // a KiiObject
4551   obj.refresh({
4552       success: function(theRefreshedObject) {
4553           // do something with the refreshed object
4554       },
4555   
4556       failure: function(theObject, anErrorString) {
4557           // do something with the error response
4558       }
4559   });
4560   
4561   // example to use Promise
4562   var obj = . . .; // a KiiObject
4563   obj.refresh().then(
4564       function(theRefreshedObject) {
4565           // do something with the refreshed object
4566       },
4567       function(error) {
4568           // do something with the error response
4569       }
4570   );
4571    */
4572 
4573   KiiObject.prototype.refresh = function(callbacks) {
4574     return new Promise((function(_this) {
4575       return function(resolve, reject) {
4576         var refreshCallbacks;
4577         refreshCallbacks = {
4578           success: function() {
4579             if (callbacks != null) {
4580               callbacks.success.apply(callbacks, arguments);
4581             }
4582             return resolve(arguments[0]);
4583           },
4584           failure: function() {
4585             if (callbacks != null) {
4586               callbacks.failure.apply(callbacks, arguments);
4587             }
4588             return reject(KiiUtilities._Error(arguments[1], _this));
4589           }
4590         };
4591         return _this._refreshUsingCallbacks(refreshCallbacks);
4592       };
4593     })(this));
4594   };
4595 
4596   KiiObject.prototype._refreshUsingCallbacks = function(callbacks) {
4597     var path, refreshCallbacks, request;
4598     path = this._getPath();
4599     request = new this._getRequest({
4600       path: path,
4601       withApp: true
4602     });
4603     refreshCallbacks = {
4604       success: (function(_this) {
4605         return function(data, statusCode, headers) {
4606           if (statusCode < 300 && statusCode >= 200) {
4607             _this._etag = headers['etag'];
4608             _this._updateWithJSON(data, false);
4609             if (callbacks != null) {
4610               return callbacks.success(_this);
4611             }
4612           } else if (callbacks != null) {
4613             return callbacks.failure(_this, "Unable to parse response");
4614           }
4615         };
4616       })(this),
4617       failure: (function(_this) {
4618         return function(error, statusCode) {
4619           if (callbacks != null) {
4620             return callbacks.failure(_this, error);
4621           }
4622         };
4623       })(this)
4624     };
4625     return request.execute(refreshCallbacks, false);
4626   };
4627 
4628 
4629   /** Delete the object from the server
4630   @name delete
4631   @memberOf root.KiiObject#
4632   @function
4633   @param {Object} [callbacks] An object with callback methods defined
4634   @param {Method} callbacks.success The callback method to call on a successful delete request
4635   @param {Method} callbacks.failure The callback method to call on a failed delete request
4636   @return {Promise} return promise object.
4637     <ul>
4638       <li>fulfill callback function: function(theDeletedObject). theDeletedObject is KiiObject instance.</li>
4639       <li>reject callback function: function(error). error is an Error instance.
4640         <ul>
4641           <li>error.target is the KiiObject instance which this method was called on.</li>
4642           <li>error.message</li>
4643         </ul>
4644       </li>
4645     </ul>
4646   @example
4647   // example to use callbacks directly
4648   var obj = . . .; // a KiiObject
4649   obj.delete({
4650       success: function(theDeletedObject) {
4651           // do something
4652       },
4653   
4654       failure: function(theObject, anErrorString) {
4655           // do something with the error response
4656       }
4657   });
4658   
4659   // example to use Promise
4660   var obj = . . .; // a KiiObject
4661   obj.delete().then(
4662       function(theDeletedObject) {
4663           // do something
4664       },
4665       function(error) {
4666           // do something with the error response
4667       }
4668   );
4669    */
4670 
4671   KiiObject.prototype["delete"] = function(callbacks) {
4672     return new Promise((function(_this) {
4673       return function(resolve, reject) {
4674         var deleteCallbacks;
4675         deleteCallbacks = {
4676           success: function() {
4677             if (callbacks != null) {
4678               callbacks.success.apply(callbacks, arguments);
4679             }
4680             return resolve(arguments[0]);
4681           },
4682           failure: function() {
4683             if (callbacks != null) {
4684               callbacks.failure.apply(callbacks, arguments);
4685             }
4686             return reject(KiiUtilities._Error(arguments[1], _this));
4687           }
4688         };
4689         return _this._deleteUsingCallbacks(deleteCallbacks);
4690       };
4691     })(this));
4692   };
4693 
4694   KiiObject.prototype._deleteUsingCallbacks = function(callbacks) {
4695     var path, refreshCallbacks, request;
4696     path = this._getPath();
4697     request = new this._getRequest({
4698       path: path,
4699       withApp: true
4700     });
4701     request.setMethod("DELETE");
4702     refreshCallbacks = {
4703       success: (function(_this) {
4704         return function(data, statusCode) {
4705           if (statusCode < 300 && statusCode >= 200 && (callbacks != null)) {
4706             return callbacks.success(_this);
4707           } else if (callbacks != null) {
4708             return callbacks.failure(_this, "Unable to parse response");
4709           }
4710         };
4711       })(this),
4712       failure: (function(_this) {
4713         return function(error, statusCode) {
4714           if (callbacks != null) {
4715             return callbacks.failure(_this, error);
4716           }
4717         };
4718       })(this)
4719     };
4720     return request.execute(refreshCallbacks, true);
4721   };
4722 
4723   KiiObject.objectWithBucket = function(bucket, type) {
4724     var obj;
4725     root.Kii.logger("Creating object w type: " + type);
4726     obj = new root.KiiObject;
4727     obj._setBucket(bucket);
4728     obj._setObjectType(type);
4729     root.Kii.logger(obj);
4730     return obj;
4731   };
4732 
4733   KiiObject.objectWithID = function(bucket, objectID) {
4734     var obj;
4735     root.Kii.logger("Creating object with id: " + objectID);
4736     obj = new root.KiiObject;
4737     obj._setBucket(bucket);
4738     obj._setUUID(objectID);
4739     root.Kii.logger(obj);
4740     return obj;
4741   };
4742 
4743   KiiObject.prototype._setETag = function(_etag) {
4744     this._etag = _etag;
4745   };
4746 
4747 
4748   /** Generate a new KiiObject based on a given URI
4749   @param {String} uri The URI of the object to be represented
4750   @returns {KiiObject} A new KiiObject with its parameters filled in from the URI
4751   @throws {InvalidURIException} If the URI is not in the proper format
4752   @example
4753   var group = new KiiObject.objectWithURI("kiicloud://myuri");
4754    */
4755 
4756   KiiObject.objectWithURI = function(uri) {
4757     var bucket, bucketIndex, bucketName, compLength, components, newURI, obj, subject;
4758     newURI = uri.substr("kiicloud://".length);
4759     components = newURI.split("/");
4760     compLength = components.length;
4761     root.Kii.logger(components);
4762     if (compLength >= 4) {
4763       bucketIndex = compLength === 4 ? 1 : 3;
4764       bucketName = components[bucketIndex];
4765       subject = null;
4766       if (components[0] === "groups") {
4767         subject = new root.KiiGroup.groupWithID(components[1]);
4768       } else if (components[0] === "users") {
4769         subject = root.KiiUser.userWithID(components[1]);
4770       } else if (components[0] === "things") {
4771         subject = root.KiiThing.thingWithID(components[1]);
4772       }
4773       bucket = null;
4774       if (root.KiiEncryptedBucket._isEncrypted(bucketName)) {
4775         bucket = new root.KiiEncryptedBucket._bucketWithName(bucketName, subject);
4776       } else {
4777         bucket = new root.KiiBucket._bucketWithName(bucketName, subject);
4778       }
4779       root.Kii.logger(bucket);
4780       obj = bucket.createObject();
4781       obj._setUUID(components[compLength - 1]);
4782       root.Kii.logger(obj);
4783     } else {
4784       throw new root.InvalidURIException;
4785     }
4786     return obj;
4787   };
4788 
4789   KiiObject.prototype._getRequest = function(spec) {
4790     var path, request, withApp;
4791     path = spec.path;
4792     withApp = spec.withApp;
4793     request = new KiiRequest(path, withApp);
4794     return request;
4795   };
4796 
4797   KiiObject.prototype._getToken = function() {
4798     var currUser, token;
4799     currUser = root.KiiUser.getCurrentUser();
4800     token = currUser ? currUser.getAccessToken() : null;
4801     if (token) {
4802       return token;
4803     } else {
4804       return null;
4805     }
4806   };
4807 
4808   KiiObject.prototype._setAuthorizationHeader = function(xhr) {
4809     var token;
4810     token = this._getToken();
4811     if (token) {
4812       return xhr.setRequestHeader("Authorization", "Bearer " + token);
4813     }
4814   };
4815 
4816   KiiObject.prototype._userWithID = function(id) {
4817     var user;
4818     user = root.KiiUser.userWithID(id);
4819     return user;
4820   };
4821 
4822   KiiObject.prototype._parseObjectUri = function(uri) {
4823     var data, targetData, uriElement, uriPrefix;
4824     uriElement = uri.replace(/^kiicloud:\/\//g, "").split("/");
4825     uriPrefix = uriElement[0];
4826     if (uriPrefix === "users") {
4827       targetData = {
4828         'appID': root.Kii.getAppID(),
4829         'userID': uriElement[1],
4830         'type': "APP_AND_USER"
4831       };
4832       if (root.KiiEncryptedBucket._isEncrypted(uriElement[3])) {
4833         data = {
4834           'targetObjectScope': targetData,
4835           'targetBucketType': "crypto",
4836