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