1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16const distributedObject = requireInternal('data.distributedDataObject'); 17const SESSION_ID = '__sessionId'; 18const VERSION = '__version'; 19const COMPLEX_TYPE = '[COMPLEX]'; 20const STRING_TYPE = '[STRING]'; 21const NULL_TYPE = '[NULL]'; 22const JS_ERROR = 1; 23const SDK_VERSION_8 = 8; 24const SDK_VERSION_9 = 9; 25 26class Distributed { 27 constructor(obj) { 28 constructorMethod(this, obj); 29 } 30 31 setSessionId(sessionId) { 32 if (sessionId == null || sessionId === '') { 33 leaveSession(this.__sdkVersion, this.__proxy); 34 return false; 35 } 36 if (this.__proxy[SESSION_ID] === sessionId) { 37 console.info('same session has joined ' + sessionId); 38 return true; 39 } 40 leaveSession(this.__sdkVersion, this.__proxy); 41 let object = joinSession(this.__sdkVersion, this.__proxy, this.__objectId, sessionId); 42 if (object != null) { 43 this.__proxy = object; 44 return true; 45 } 46 return false; 47 } 48 49 on(type, callback) { 50 onWatch(this.__sdkVersion, type, this.__proxy, callback); 51 distributedObject.recordCallback(this.__sdkVersion, type, this.__objectId, callback); 52 } 53 54 off(type, callback) { 55 offWatch(this.__sdkVersion, type, this.__proxy, callback); 56 if (callback !== undefined || callback != null) { 57 distributedObject.deleteCallback(this.__sdkVersion, type, this.__objectId, callback); 58 } else { 59 distributedObject.deleteCallback(this.__sdkVersion, type, this.__objectId); 60 } 61 } 62 63 save(deviceId, callback) { 64 if (this.__proxy[SESSION_ID] == null || this.__proxy[SESSION_ID] === '') { 65 console.info('not join a session, can not do save'); 66 return JS_ERROR; 67 } 68 return this.__proxy.save(deviceId, this[VERSION], callback); 69 } 70 71 revokeSave(callback) { 72 if (this.__proxy[SESSION_ID] == null || this.__proxy[SESSION_ID] === '') { 73 console.info('not join a session, can not do revoke save'); 74 return JS_ERROR; 75 } 76 return this.__proxy.revokeSave(callback); 77 } 78 79 __proxy; 80 __objectId; 81 __version; 82 __sdkVersion = SDK_VERSION_8; 83} 84 85function constructorMethod(result, obj) { 86 result.__proxy = obj; 87 Object.keys(obj).forEach(key => { 88 Object.defineProperty(result, key, { 89 enumerable: true, 90 configurable: true, 91 get: function () { 92 return result.__proxy[key]; 93 }, 94 set: function (newValue) { 95 result[VERSION]++; 96 result.__proxy[key] = newValue; 97 } 98 }); 99 }); 100 Object.defineProperty(result, SESSION_ID, { 101 enumerable: true, 102 configurable: true, 103 get: function () { 104 return result.__proxy[SESSION_ID]; 105 }, 106 set: function (newValue) { 107 result.__proxy[SESSION_ID] = newValue; 108 } 109 }); 110 result.__objectId = randomNum(); 111 result[VERSION] = 0; 112 console.info('constructor success '); 113} 114 115function randomNum() { 116 return distributedObject.sequenceNum(); 117} 118 119function newDistributed(obj) { 120 console.info('start newDistributed'); 121 if (obj == null) { 122 console.error('object is null'); 123 return null; 124 } 125 return new Distributed(obj); 126} 127 128function joinSession(version, obj, objectId, sessionId, context) { 129 console.info('start joinSession ' + sessionId); 130 if (obj == null || sessionId == null || sessionId === '') { 131 console.error('object is null'); 132 return null; 133 } 134 135 let object = null; 136 if (context !== undefined || context != null) { 137 object = distributedObject.createObjectSync(version, sessionId, objectId, context); 138 } else { 139 object = distributedObject.createObjectSync(version, sessionId, objectId); 140 } 141 142 if (object == null) { 143 console.error('create fail'); 144 return null; 145 } 146 Object.keys(obj).forEach(key => { 147 console.info('start define ' + key); 148 Object.defineProperty(object, key, { 149 enumerable: true, 150 configurable: true, 151 get: function () { 152 console.info('start get ' + key); 153 let result = object.get(key); 154 console.info('get ' + result); 155 if (typeof result === 'string') { 156 if (result.startsWith(STRING_TYPE)) { 157 result = result.substr(STRING_TYPE.length); 158 } else if (result.startsWith(COMPLEX_TYPE)) { 159 result = JSON.parse(result.substr(COMPLEX_TYPE.length)); 160 } else if (result.startsWith(NULL_TYPE)) { 161 result = null; 162 } else { 163 console.error('error type ' + result); 164 } 165 } 166 console.info('get ' + result + ' success'); 167 return result; 168 }, 169 set: function (newValue) { 170 console.info('start set ' + key + ' ' + newValue); 171 if (typeof newValue === 'object') { 172 let value = COMPLEX_TYPE + JSON.stringify(newValue); 173 object.put(key, value); 174 console.info('set ' + key + ' ' + value); 175 } else if (typeof newValue === 'string') { 176 let value = STRING_TYPE + newValue; 177 object.put(key, value); 178 console.info('set ' + key + ' ' + value); 179 } else if (newValue == null) { 180 let value = NULL_TYPE; 181 object.put(key, value); 182 console.info('set ' + key + ' ' + value); 183 } else { 184 object.put(key, newValue); 185 console.info('set ' + key + ' ' + newValue); 186 } 187 } 188 }); 189 if (obj[key] !== undefined) { 190 object[key] = obj[key]; 191 } 192 }); 193 194 Object.defineProperty(object, SESSION_ID, { 195 value: sessionId, 196 configurable: true, 197 }); 198 return object; 199} 200 201function leaveSession(version, obj) { 202 console.info('start leaveSession'); 203 if (obj == null || obj[SESSION_ID] == null || obj[SESSION_ID] === '') { 204 console.warn('object is null'); 205 return; 206 } 207 Object.keys(obj).forEach(key => { 208 Object.defineProperty(obj, key, { 209 value: obj[key], 210 configurable: true, 211 writable: true, 212 enumerable: true, 213 }); 214 }); 215 // disconnect,delete object 216 distributedObject.destroyObjectSync(version, obj); 217 delete obj[SESSION_ID]; 218} 219 220function onWatch(version, type, obj, callback) { 221 console.info('start on ' + obj[SESSION_ID]); 222 if (obj[SESSION_ID] != null && obj[SESSION_ID] !== undefined && obj[SESSION_ID].length > 0) { 223 distributedObject.on(version, type, obj, callback); 224 } 225} 226 227function offWatch(version, type, obj, callback = undefined) { 228 console.info('start off ' + obj[SESSION_ID] + ' ' + callback); 229 if (obj[SESSION_ID] != null && obj[SESSION_ID] !== undefined && obj[SESSION_ID].length > 0) { 230 if (callback !== undefined || callback != null) { 231 distributedObject.off(version, type, obj, callback); 232 } else { 233 distributedObject.off(version, type, obj); 234 } 235 } 236} 237 238function newDistributedV9(context, obj) { 239 console.info('start newDistributed'); 240 let checkparameter = function(parameter, type) { 241 throw { 242 code: 401, 243 message :"Parameter error. The type of '" + parameter + "' must be '" + type + "'."}; 244 }; 245 if (typeof context !== 'object') { 246 checkparameter('context', 'Context'); 247 } 248 if (typeof obj !== 'object') { 249 checkparameter('source', 'object'); 250 } 251 if (obj == null) { 252 console.error('object is null'); 253 return null; 254 } 255 return new DistributedV9(obj, context); 256} 257 258class DistributedV9 { 259 260 constructor(obj, context) { 261 this.__context = context; 262 constructorMethod(this, obj); 263 } 264 265 setSessionId(sessionId, callback) { 266 if (typeof sessionId === 'function' || sessionId == null || sessionId === '') { 267 leaveSession(this.__sdkVersion, this.__proxy); 268 if (typeof sessionId === 'function') { 269 return sessionId(this.__proxy); 270 } else if (typeof callback === 'function') { 271 return callback(null, this.__proxy); 272 } else { 273 return Promise.resolve(null, this.__proxy); 274 } 275 } 276 if (this.__proxy[SESSION_ID] === sessionId) { 277 console.info('same session has joined ' + sessionId); 278 if (typeof callback === 'function') { 279 return callback(null, this.__proxy); 280 } else { 281 return Promise.resolve(null, this.__proxy); 282 } 283 } 284 leaveSession(this.__sdkVersion, this.__proxy); 285 let object = joinSession(this.__sdkVersion, this.__proxy, this.__objectId, sessionId, this.__context); 286 if (object != null) { 287 this.__proxy = object; 288 if (typeof callback === 'function') { 289 return callback(null, this.__proxy); 290 } else { 291 return Promise.resolve(null, object); 292 } 293 } else { 294 if (typeof callback === 'function') { 295 return callback(null, null); 296 } else { 297 return Promise.reject(null, null); 298 } 299 } 300 } 301 302 on(type, callback) { 303 onWatch(this.__sdkVersion, type, this.__proxy, callback); 304 distributedObject.recordCallback(this.__sdkVersion, type, this.__objectId, callback); 305 } 306 307 off(type, callback) { 308 offWatch(this.__sdkVersion, type, this.__proxy, callback); 309 if (callback !== undefined || callback != null) { 310 distributedObject.deleteCallback(this.__sdkVersion, type, this.__objectId, callback); 311 } else { 312 distributedObject.deleteCallback(this.__sdkVersion, type, this.__objectId); 313 } 314 } 315 316 save(deviceId, callback) { 317 if (this.__proxy[SESSION_ID] == null || this.__proxy[SESSION_ID] === '') { 318 console.info('not join a session, can not do save'); 319 return JS_ERROR; 320 } 321 return this.__proxy.save(deviceId, this[VERSION], callback); 322 } 323 324 revokeSave(callback) { 325 if (this.__proxy[SESSION_ID] == null || this.__proxy[SESSION_ID] === '') { 326 console.info('not join a session, can not do revoke save'); 327 return JS_ERROR; 328 } 329 return this.__proxy.revokeSave(callback); 330 } 331 332 __context; 333 __proxy; 334 __objectId; 335 __version; 336 __sdkVersion = SDK_VERSION_9; 337} 338 339export default { 340 createDistributedObject: newDistributed, 341 create: newDistributedV9, 342 genSessionId: randomNum 343}; 344