1/* 2 * Copyright (c) 2021-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 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 7 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 /** 66 * Like @see link(), but will create and initialize a new source property in LocalStorge if missing 67 * 68 * Same as @see LocalStorage.setAndLink() 69 * 70 * @param propName name of source property in AppStorage 71 * @param defaultValue value to be used for initializing if new creating new property in AppStorage 72 * default value must be of type S, must not be undefined or null. 73 * @param linkUser IPropertySubscriber to be notified when return 'link' changes, 74 * @param subscribersName the linkUser (subscriber) uses this name for the property 75 * this name will be used in propertyChange(propName) callback of IMultiPropertiesChangeSubscriber 76 * @returns SynchedPropertyTwoWay{Simple|Object| object with given LocalStoage prop as its source. 77 * Apps can use SDK functions of base class SubscribedAbstractProperty<S> 78 * 79 * @since 7 80 */ 81 public static SetAndLink<T>(key: string, defaultValue: T, linkUser?: IPropertySubscriber, subscribersName?: string): SubscribedAbstractProperty<T> { 82 return AppStorage.GetOrCreate().setAndLink(key, defaultValue, linkUser, subscribersName); 83 } 84 85 /** 86 * create and return a one-way sync ('prop') to named property 87 * 88 * Same as @see LocalStorage.prop() 89 * 90 * @param propName name of source property in AppStorage 91 * @param propUser IPropertySubscriber to be notified when source changes, 92 * @param subscribersName the linkUser (subscriber) uses this name for the property 93 * this name will be used in propertyChange(propName) callback of IMultiPropertiesChangeSubscriber 94 * @returns SynchedPropertyOneWay{Simple|Object| object with given LocalStoage prop as its source. 95 * Apps can use SDK functions of base class SubscribedAbstractProperty<S> 96 * return undefiend if named property does not already exist in AppStorage. 97 * @since 7 98 */ 99 public static Prop<T>(propName: string, propUser?: IPropertySubscriber, subscribersName?: string): SubscribedAbstractProperty<T> { 100 return AppStorage.GetOrCreate().prop(propName, propUser, subscribersName); 101 } 102 103 /** 104 * Like @see prop(), will create and initialize a new source property in AppStorage if missing 105 * 106 * Same as @see LocalStorage.setAndProp() 107 * 108 * @param propName name of source property in AppStorage 109 * @param defaultValue value to be used for initializing if new creating new property in AppStorage. 110 * default value must be of type S, must not be undefined or null. 111 * @param propUser IPropertySubscriber to be notified when returned 'prop' changes, 112 * @param subscribersName the propUser (subscriber) uses this name for the property 113 * this name will be used in propertyChange(propName) callback of IMultiPropertiesChangeSubscriber 114 * @returns SynchedPropertyOneWay{Simple|Object| object with given LocalStoage prop as its source. 115 * Apps can use SDK functions of base class SubscribedAbstractProperty<S> 116 * 117 * @since 7 118 */ 119 public static SetAndProp<S>(key: string, defaultValue: S, propUser?: IPropertySubscriber, subscribersName?: string): SubscribedAbstractProperty<S> { 120 return AppStorage.GetOrCreate().setAndProp(key, defaultValue, propUser, subscribersName); 121 } 122 123 124 /** 125 * Check if AppStorge has a property with given name 126 * return true if prooperty with given name exists 127 * same as ES6 Map.prototype.has() 128 * 129 * Same as @see LocalStorage.has() 130 * 131 * @param propName searched property 132 * @returns true if property with such name exists in AppStorage 133 * 134 * @since 7 135 */ 136 public static Has(key: string): boolean { 137 return AppStorage.GetOrCreate().has(key); 138 } 139 140 141 /** 142 * Returns value of given property 143 * return undefined if no property with this name 144 * 145 * 146 * @Same as see LocalStorage.get() 147 * 148 * @param propName 149 * @returns property value if found or undefined 150 * 151 */ 152 public static Get<T>(key: string): T | undefined { 153 return AppStorage.GetOrCreate().get(key); 154 } 155 156 /** 157 * Set value of given property in AppStorage 158 * Methosd sets nothing and returns false if property with this name does not exist 159 * or if newValue is `undefined` or `null` (`undefined`, `null` value are not allowed for state variables). 160 * 161 * Same as @see LocalStorage.set 162 * 163 * @param propName 164 * @param newValue must be of type T and must not be undefined or null 165 * @returns true on success, i.e. when above conditions are satisfied, otherwise false 166 * 167 * @since 7 168 */ 169 public static Set<T>(key: string, newValue: T): boolean { 170 return AppStorage.GetOrCreate().set(key, newValue); 171 } 172 173 /** 174 * Set value of given property, if it exists, @see set() . 175 * Add property if no property with given name and initialize with given value. 176 * Do nothing and return false if newValuue is undefined or null 177 * (undefined, null value is not allowed for state variables) 178 * 179 * @see LocalStorage.setOrCreate() 180 * 181 * @param propName 182 * @param newValue must be of type T and must not be undefined or null 183 * @returns true on success, i.e. when above conditions are satisfied, otherwise false 184 * 185 * @since 7 186 */ 187 public static SetOrCreate<T>(key: string, newValue: T): void { 188 AppStorage.GetOrCreate().setOrCreate(key, newValue); 189 } 190 191 192 /** 193 * Delete property from StorageBase 194 * Use with caution: 195 * Before deleting a prop from AppStorage all its subscribers need to 196 * unsubscribe from the property. 197 * This method fails and returns false if given property still has subscribers 198 * Another reason for failing is unkmown property. 199 * 200 * Developer advise: 201 * Subscribers are created with @see link(), @see prop() 202 * and also via @LocalStorageLink and @LocalStorageProp state variable decorators. 203 * That means as long as their is a @Component instance that uses such decorated variable 204 * or a sync relationship with a SubscribedAbstractProperty variable the property can nit 205 * (and also should not!) be deleted from AppStorage. 206 * 207 * Same as @see LocalStorage.delete() 208 * 209 * @param propName 210 * @returns false if method failed 211 * 212 * @since 7 213 */ 214 public static Delete(key: string): boolean { 215 return AppStorage.GetOrCreate().delete(key); 216 } 217 218 /** 219 * Provide names of all properties in AppStorage 220 * same as ES6 Map.prototype.keys() 221 * 222 * Same as @see LocalStorage.keys() 223 * 224 * @returns return a Map Iterator 225 * 226 * @since 7 227 */ 228 public static Keys(): IterableIterator<string> { 229 return AppStorage.GetOrCreate().keys(); 230 } 231 232 233 /** 234 * Returns number of properties in AppStorage 235 * same as Map.prototype.size() 236 * 237 * Same as @see LocalStorage.size() 238 * 239 * @param propName 240 * @returns return number of properties 241 * 242 * @since 7 243 */ 244 public static Size(): number { 245 return AppStorage.GetOrCreate().size(); 246 } 247 248 /** 249 * delete all properties from the AppStorage 250 * 251 * @see delete(), same as @see LocalStorage.clear() 252 * 253 * precondition is that there are no subscribers. 254 * method returns false and deletes no poperties if there is any property 255 * that still has subscribers 256 * 257 * @since 7 258 */ 259 public static Clear(): boolean { 260 return AppStorage.GetOrCreate().clear(); 261 } 262 263 /** 264 * Same as @see Clear(). 265 * 266 * @since 7, depreciated, used Clear() instead! 267 * 268 */ 269 public static StaticClear(): boolean { 270 return AppStorage.Clear(); 271 } 272 273 /** 274 * not a public / sdk function 275 */ 276 public static AboutToBeDeleted(): void { 277 AppStorage.GetOrCreate().aboutToBeDeleted(); 278 } 279 280 281 /** 282 * return number of subscribers to named property 283 * useful for debug purposes 284 * 285 * not a public / sdk function 286 */ 287 public static NumberOfSubscribersTo(propName: string): number | undefined { 288 return AppStorage.GetOrCreate().numberOfSubscrbersTo(propName); 289 } 290 291 292 /** 293 * Subscribe to value change notifications of named property 294 * Any object implementing ISinglePropertyChangeSubscriber interface 295 * and registerign itself to SubscriberManager can register 296 * Caution: do remember to unregister, otherwise the property will block 297 * cleanup, @see delete() and @see clear() 298 * 299 * Same as @see LocalStorage.subscribeToChangesOf() 300 * 301 * @param propName property in AppStorage to subscribe to 302 * @param subscriber object that implements ISinglePropertyChangeSubscriber interface 303 * @returns false if named property does not exist 304 * 305 * @since 7 306 */ 307 public static SubscribeToChangesOf<T>(propName: string, subscriber: ISinglePropertyChangeSubscriber<T>): boolean { 308 return AppStorage.GetOrCreate().subscribeToChangesOf(propName, subscriber); 309 } 310 311 312 /** 313 * inverse of @see SubscribeToChangesOf, 314 * same as @see LocalStorage.subscribeToChangesOf() 315 * 316 * @param propName property in AppStorage to subscribe to 317 * @param subscriberId id of the subscrber passed to @see subscribeToChangesOf 318 * @returns false if named property does not exist 319 * 320 * @since 7 321 */ 322 public static UnsubscribeFromChangesOf(propName: string, subscriberId: number): boolean { 323 return AppStorage.GetOrCreate().unsubscribeFromChangesOf(propName, subscriberId); 324 } 325 326 /** 327 * Unimplemenrted, currently all properties of AppStorage are mutable. 328 * 329 * @since 7, depreciated 330 */ 331 public static IsMutable(key: string): boolean { 332 return true; 333 } 334 335 /** 336 * not a public / sdk function 337 */ 338 339 public static __CreateSync<T>(storagePropName: string, defaultValue: T, 340 factoryFunc: SynchedPropertyFactoryFunc): ObservedPropertyAbstract<T> { 341 return AppStorage.GetOrCreate().__createSync(storagePropName, defaultValue, factoryFunc); 342 } 343 344 // instance functions below: 345 // Should all be protected, but TS lang does not allow access from static member to protected member 346 347 private static Instance_: AppStorage = undefined; 348 349 /** 350 * not a public / sdk function 351 */ 352 private static GetOrCreate(): AppStorage { 353 if (!AppStorage.Instance_) { 354 stateMgmtConsole.warn("AppStorage instance missing. Use AppStorage.CreateInstance(initObj). Creating instance without any initialization."); 355 AppStorage.Instance_ = new AppStorage({}); 356 } 357 return AppStorage.Instance_; 358 } 359 360 /** singleton class, app can not create instances 361 * 362 * not a public / sdk function 363 */ 364 protected constructor(initializingProperties: Object) { 365 super(initializingProperties); 366 } 367} 368 369 370