1/* 2 * Copyright (c) 2021-2023 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 16/** 17 * 18 * AppStorage 19 * 20 * Class implements a Map of ObservableObjectBase UI state variables. 21 * AppStorage singleton is sub-class of @see LocalStorage for 22 * UI state of app-wide access and same life cycle as the app. 23 * 24 * @since 7 25 */ 26 27class AppStorage extends LocalStorage { 28 /** 29 * create and initialize singleton 30 * initialzie with all properties and their values that Object.keys(params) returns 31 * Property values must not be undefined. 32 * 33 * not a public / sdk function 34 */ 35 public static createSingleton(initializingPropersties?: Object): void { 36 if (!AppStorage.instance_) { 37 stateMgmtConsole.debug("Creating AppStorage instance."); 38 AppStorage.instance_ = new AppStorage(initializingPropersties); 39 } else { 40 stateMgmtConsole.error("AppStorage.createNewInstance(..): instance exists already, internal error!") 41 } 42 } 43 44 45 /** 46 * create and return a two-way sync "(link") to named property 47 * 48 * Same as @see LocalStorage.link() 49 * 50 * @param propName name of source property in AppStorage 51 * @param linkUser IPropertySubscriber to be notified when source changes, 52 * @param subscribersName the linkUser (subscriber) uses this name for the property 53 * this name will be used in propertyChange(propName) callback of IMultiPropertiesChangeSubscriber 54 * @returns SynchedPropertyTwoWay{Simple|Object| object with given LocalStoage prop as its source. 55 * Apps can use SDK functions of base class SubscribedAbstractProperty<S> 56 * return undefiend if named property does not already exist in AppStorage 57 * 58 * @since 10 59 */ 60 public static link<T>(key: string, linkUser?: IPropertySubscriber, subscribersName?: string): SubscribedAbstractProperty<T> { 61 return AppStorage.getOrCreate().link(key, linkUser, subscribersName); 62 } 63 64 /** 65 * @see link 66 * @since 7 67 * @deprecated 68 */ 69 public static Link<T>(key: string, linkUser?: IPropertySubscriber, subscribersName?: string): SubscribedAbstractProperty<T> { 70 return AppStorage.getOrCreate().link(key, linkUser, subscribersName); 71 } 72 73 /** 74 * Like @see link(), but will create and initialize a new source property in LocalStorage if missing 75 * 76 * Same as @see LocalStorage.setAndLink() 77 * 78 * @param propName name of source property in AppStorage 79 * @param defaultValue value to be used for initializing if new creating new property in AppStorage 80 * default value must be of type S, must not be undefined or null. 81 * @param linkUser IPropertySubscriber to be notified when return 'link' changes, 82 * @param subscribersName the linkUser (subscriber) uses this name for the property 83 * this name will be used in propertyChange(propName) callback of IMultiPropertiesChangeSubscriber 84 * @returns SynchedPropertyTwoWay{Simple|Object| object with given LocalStoage prop as its source. 85 * Apps can use SDK functions of base class SubscribedAbstractProperty<S> 86 * 87 * @since 10 88 */ 89 public static setAndLink<T>(key: string, defaultValue: T, linkUser?: IPropertySubscriber, subscribersName?: string): SubscribedAbstractProperty<T> { 90 return AppStorage.getOrCreate().setAndLink(key, defaultValue, linkUser, subscribersName); 91 } 92 93 /** 94 * @see setAndLink 95 * @since 7 96 * @deprecated 97 */ 98 public static SetAndLink<T>(key: string, defaultValue: T, linkUser?: IPropertySubscriber, subscribersName?: string): SubscribedAbstractProperty<T> { 99 return AppStorage.getOrCreate().setAndLink(key, defaultValue, linkUser, subscribersName); 100 } 101 102 /** 103 * create and return a one-way sync ('prop') to named property 104 * 105 * Same as @see LocalStorage.prop() 106 * 107 * @param propName name of source property in AppStorage 108 * @param propUser IPropertySubscriber to be notified when source changes, 109 * @param subscribersName the linkUser (subscriber) uses this name for the property 110 * this name will be used in propertyChange(propName) callback of IMultiPropertiesChangeSubscriber 111 * @returns SynchedPropertyOneWay{Simple|Object| object with given LocalStoage prop as its source. 112 * Apps can use SDK functions of base class SubscribedAbstractProperty<S> 113 * return undefiend if named property does not already exist in AppStorage. 114 * @since 10 115 */ 116 public static prop<T>(propName: string, propUser?: IPropertySubscriber, subscribersName?: string): SubscribedAbstractProperty<T> { 117 return AppStorage.getOrCreate().prop(propName, propUser, subscribersName); 118 } 119 120 /** 121 * @see prop 122 * @since 7 123 * @deprecated 124 */ 125 public static Prop<T>(propName: string, propUser?: IPropertySubscriber, subscribersName?: string): SubscribedAbstractProperty<T> { 126 return AppStorage.getOrCreate().prop(propName, propUser, subscribersName); 127 } 128 129 /** 130 * Like @see prop(), will create and initialize a new source property in AppStorage if missing 131 * 132 * Same as @see LocalStorage.setAndProp() 133 * 134 * @param propName name of source property in AppStorage 135 * @param defaultValue value to be used for initializing if new creating new property in AppStorage. 136 * default value must be of type S, must not be undefined or null. 137 * @param propUser IPropertySubscriber to be notified when returned 'prop' changes, 138 * @param subscribersName the propUser (subscriber) uses this name for the property 139 * this name will be used in propertyChange(propName) callback of IMultiPropertiesChangeSubscriber 140 * @returns SynchedPropertyOneWay{Simple|Object| object with given LocalStoage prop as its source. 141 * Apps can use SDK functions of base class SubscribedAbstractProperty<S> 142 * 143 * @since 10 144 */ 145 public static setAndProp<S>(key: string, defaultValue: S, propUser?: IPropertySubscriber, subscribersName?: string): SubscribedAbstractProperty<S> { 146 return AppStorage.getOrCreate().setAndProp(key, defaultValue, propUser, subscribersName); 147 } 148 149 /** 150 * @see setAndProp 151 * @since 7 152 * @deprecated 153 */ 154 public static SetAndProp<S>(key: string, defaultValue: S, propUser?: IPropertySubscriber, subscribersName?: string): SubscribedAbstractProperty<S> { 155 return AppStorage.getOrCreate().setAndProp(key, defaultValue, propUser, subscribersName); 156 } 157 158 159 /** 160 * Check if AppStorage has a property with given name 161 * return true if property with given name exists 162 * same as ES6 Map.prototype.has() 163 * 164 * Same as @see LocalStorage.has() 165 * 166 * @param propName searched property 167 * @returns true if property with such name exists in AppStorage 168 * 169 * @since 10 170 */ 171 public static has(key: string): boolean { 172 return AppStorage.getOrCreate().has(key); 173 } 174 175 /** 176 * @see has() 177 * @since 7 178 * @deprecated 179 */ 180 public static Has(key: string): boolean { 181 return AppStorage.getOrCreate().has(key); 182 } 183 184 /** 185 * Returns value of given property 186 * return undefined if no property with this name 187 * 188 * @Same as see LocalStorage.get() 189 * 190 * @param propName 191 * @returns property value if found or undefined 192 * 193 * @since 10 194 * 195 */ 196 public static get<T>(key: string): T | undefined { 197 return AppStorage.getOrCreate().get(key); 198 } 199 200 /** 201 * @see get 202 * @since 7 203 * @deprecated 204 * 205 */ 206 public static Get<T>(key: string): T | undefined { 207 return AppStorage.getOrCreate().get(key); 208 } 209 210 /** 211 * Set value of given property in AppStorage 212 * Method sets nothing and returns false if property with this name does not exist 213 * or if newValue is `undefined` or `null` (`undefined`, `null` value are not allowed for state variables). 214 * 215 * Same as @see LocalStorage.set 216 * 217 * @param propName 218 * @param newValue must be of type T and must not be undefined or null 219 * @returns true on success, i.e. when above conditions are satisfied, otherwise false 220 * 221 * @since 10 222 */ 223 public static set<T>(key: string, newValue: T): boolean { 224 return AppStorage.getOrCreate().set(key, newValue); 225 } 226 227 /** 228 * @see set 229 * @since 7 230 * @deprecated 231 */ 232 public static Set<T>(key: string, newValue: T): boolean { 233 return AppStorage.getOrCreate().set(key, newValue); 234 } 235 236 /** 237 * Set value of given property, if it exists, @see set() . 238 * Add property if no property with given name and initialize with given value. 239 * Do nothing and return false if newValuue is undefined or null 240 * (undefined, null value is not allowed for state variables) 241 * 242 * @see LocalStorage.setOrCreate() 243 * 244 * @param propName 245 * @param newValue must be of type T and must not be undefined or null 246 * @returns true on success, i.e. when above conditions are satisfied, otherwise false 247 * 248 * @since 10 249 */ 250 public static setOrCreate<T>(key: string, newValue: T): void { 251 AppStorage.getOrCreate().setOrCreate(key, newValue); 252 } 253 254 /** 255 * @see setOrCreate 256 * @since 7 257 * @deprecated 258 */ 259 public static SetOrCreate<T>(key: string, newValue: T): void { 260 AppStorage.getOrCreate().setOrCreate(key, newValue); 261 } 262 263 264 /** 265 * Delete property from StorageBase 266 * Use with caution: 267 * Before deleting a prop from AppStorage all its subscribers need to 268 * unsubscribe from the property. 269 * This method fails and returns false if given property still has subscribers 270 * Another reason for failing is unkmown property. 271 * 272 * Developer advise: 273 * Subscribers are created with @see link(), @see prop() 274 * and also via @LocalStorageLink and @LocalStorageProp state variable decorators. 275 * That means as long as their is a @Component instance that uses such decorated variable 276 * or a sync relationship with a SubscribedAbstractProperty variable the property can nit 277 * (and also should not!) be deleted from AppStorage. 278 * 279 * Same as @see LocalStorage.delete() 280 * 281 * @param propName 282 * @returns false if method failed 283 * 284 * @since 10 285 */ 286 public static delete(key: string): boolean { 287 return AppStorage.getOrCreate().delete(key); 288 } 289 290 /** 291 * @see delete 292 * @since 7 293 * @deprecated 294 */ 295 public static Delete(key: string): boolean { 296 return AppStorage.getOrCreate().delete(key); 297 } 298 299 /** 300 * Provide names of all properties in AppStorage 301 * same as ES6 Map.prototype.keys() 302 * 303 * Same as @see LocalStorage.keys() 304 * 305 * @returns return a Map Iterator 306 * 307 * @since 10 308 */ 309 public static keys(): IterableIterator<string> { 310 return AppStorage.getOrCreate().keys(); 311 } 312 313 /** 314 * @see keys 315 * @since 7 316 * @deprecated 317 */ 318 public static Keys(): IterableIterator<string> { 319 return AppStorage.getOrCreate().keys(); 320 } 321 322 /** 323 * Returns number of properties in AppStorage 324 * same as Map.prototype.size() 325 * 326 * Same as @see LocalStorage.size() 327 * 328 * @param propName 329 * @returns return number of properties 330 * 331 * @since 10 332 */ 333 public static size(): number { 334 return AppStorage.getOrCreate().size(); 335 } 336 337 /** 338 * @see size 339 * @since 7 340 * @deprecated 341 */ 342 public static Size(): number { 343 return AppStorage.getOrCreate().size(); 344 } 345 346 /** 347 * delete all properties from the AppStorage 348 * 349 * @see delete(), same as @see LocalStorage.clear() 350 * 351 * precondition is that there are no subscribers. 352 * method returns false and deletes no poperties if there is any property 353 * that still has subscribers 354 * 355 * @since 10 356 */ 357 public static clear(): boolean { 358 return AppStorage.getOrCreate().clear(); 359 } 360 361 /** 362 * @see clear 363 * @since 7 364 * @deprecated 365 */ 366 public static Clear(): boolean { 367 return AppStorage.getOrCreate().clear(); 368 } 369 370 /** 371 * Same as @see clear(). 372 * 373 * @since 7, deprecated, used clear() instead! 374 * 375 */ 376 public static StaticClear(): boolean { 377 return AppStorage.clear(); 378 } 379 380 /** 381 * not a public / sdk function 382 */ 383 public static aboutToBeDeleted(): void { 384 AppStorage.getOrCreate().aboutToBeDeleted(); 385 } 386 387 388 /** 389 * return number of subscribers to named property 390 * useful for debug purposes 391 * 392 * not a public / sdk function 393 */ 394 public static numberOfSubscribersTo(propName: string): number | undefined { 395 return AppStorage.getOrCreate().numberOfSubscrbersTo(propName); 396 } 397 398 399 /** 400 * Subscribe to value change notifications of named property 401 * Any object implementing ISinglePropertyChangeSubscriber interface 402 * and registerign itself to SubscriberManager can register 403 * Caution: do remember to unregister, otherwise the property will block 404 * cleanup, @see delete() and @see clear() 405 * 406 * Same as @see LocalStorage.subscribeToChangesOf() 407 * 408 * @param propName property in AppStorage to subscribe to 409 * @param subscriber object that implements ISinglePropertyChangeSubscriber interface 410 * @returns false if named property does not exist 411 * 412 * @since 10 413 */ 414 public static subscribeToChangesOf<T>(propName: string, subscriber: ISinglePropertyChangeSubscriber<T>): boolean { 415 return AppStorage.getOrCreate().subscribeToChangesOf(propName, subscriber); 416 } 417 418 419 /** 420 * @see subscribeToChangesOf 421 * @since 7 422 * @deprecated 423 */ 424 public static SubscribeToChangesOf<T>(propName: string, subscriber: ISinglePropertyChangeSubscriber<T>): boolean { 425 return AppStorage.getOrCreate().subscribeToChangesOf(propName, subscriber); 426 } 427 428 /** 429 * inverse of @see SubscribeToChangesOf, 430 * same as @see LocalStorage.subscribeToChangesOf() 431 * 432 * @param propName property in AppStorage to subscribe to 433 * @param subscriberId id of the subscrber passed to @see subscribeToChangesOf 434 * @returns false if named property does not exist 435 * 436 * @since 10 437 */ 438 public static unsubscribeFromChangesOf(propName: string, subscriberId: number): boolean { 439 return AppStorage.getOrCreate().unsubscribeFromChangesOf(propName, subscriberId); 440 } 441 442 /** 443 * @see unsubscribeFromChangesOf 444 * @since 7 445 * @deprecated 446 */ 447 public static UnsubscribeFromChangesOf(propName: string, subscriberId: number): boolean { 448 return AppStorage.getOrCreate().unsubscribeFromChangesOf(propName, subscriberId); 449 } 450 451 /** 452 * Unimplemented, currently all properties of AppStorage are mutable. 453 * 454 * @since 7, deprecated 455 */ 456 public static IsMutable(key: string): boolean { 457 return true; 458 } 459 460 /** 461 * not a public / sdk function 462 */ 463 464 public static __createSync<T>(storagePropName: string, defaultValue: T, 465 factoryFunc: SynchedPropertyFactoryFunc): ObservedPropertyAbstract<T> { 466 return AppStorage.getOrCreate().__createSync(storagePropName, defaultValue, factoryFunc); 467 } 468 469 // instance functions below: 470 // Should all be protected, but TS lang does not allow access from static member to protected member 471 472 private static instance_: AppStorage = undefined; 473 474 /** 475 * not a public / sdk function 476 */ 477 private static getOrCreate(): AppStorage { 478 if (!AppStorage.instance_) { 479 stateMgmtConsole.warn("AppStorage instance missing. Use AppStorage.createInstance(initObj). Creating instance without any initialization."); 480 AppStorage.instance_ = new AppStorage({}); 481 } 482 return AppStorage.instance_; 483 } 484 485 /** singleton class, app can not create instances 486 * 487 * not a public / sdk function 488 */ 489 protected constructor(initializingProperties: Object) { 490 super(initializingProperties); 491 } 492} 493 494 495