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