• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
16class DistributedStorage implements IMultiPropertiesChangeSubscriber {
17  private storage_: IStorage;
18
19  private id_: number;
20  private links_: Map<string, SubscribedAbstractProperty<any>>;
21  private aviliable_: boolean;
22  private notifier_: (status: string) => void;
23
24  public constructor(sessionId: string, notifier: (status: string) => void) {
25    this.links_ = new Map<string, ObservedPropertyAbstract<any>>();
26    this.id_ = SubscriberManager.MakeId();
27    SubscriberManager.Add(this);
28    this.aviliable_ = false;
29    this.notifier_ = notifier;
30  }
31
32  public keys(): Array<string> {
33    let result = [];
34    const it = this.links_.keys();
35    let val = it.next();
36
37    while (!val.done) {
38      result.push(val.value);
39      val = it.next();
40    }
41
42    return result;
43  }
44
45
46  public distributeProp<T>(propName: string, defaultValue: T): void {
47    if (this.link(propName, defaultValue)) {
48      stateMgmtConsole.debug(`DistributedStorage: writing '${propName}' - '${this.links_.get(propName)}' to storage`);
49    }
50  }
51
52  public distributeProps(properties: {
53    key: string,
54    defaultValue: any
55  }[]): void {
56    properties.forEach(property => this.link(property.key, property.defaultValue));
57  }
58
59  public link<T>(propName: string, defaultValue: T): boolean {
60    if (defaultValue == null || defaultValue == undefined) {
61      stateMgmtConsole.error(`DistributedStorage: linkProp for ${propName} called with 'null' or 'undefined' default value!`);
62      return false;
63    }
64    if (this.links_.get(propName)) {
65      stateMgmtConsole.warn(`DistributedStorage: linkProp: ${propName} is already exist`);
66        return false;
67    }
68    let link = AppStorage.Link(propName, this);
69    if (link) {
70      stateMgmtConsole.debug(`DistributedStorage: linkProp ${propName} in AppStorage, using that`);
71        this.links_.set(propName, link);
72        this.setDistributedProp(propName, defaultValue);
73    }
74    else {
75        let returnValue = defaultValue;
76        if (this.aviliable_) {
77            let newValue = this.getDistributedProp(propName);
78            if (newValue == null) {
79              stateMgmtConsole.debug(`DistributedStorage: no entry for ${propName}, will initialize with default value`);
80                this.setDistributedProp(propName, defaultValue);
81            }
82            else {
83                returnValue = newValue;
84            }
85        }
86        link = AppStorage.SetAndLink(propName, returnValue, this);
87        this.links_.set(propName, link);
88        stateMgmtConsole.debug(`DistributedStorage: created new linkProp prop for ${propName}`);
89    }
90    return true;
91  }
92
93  public deleteProp(propName: string): void {
94    let link = this.links_.get(propName);
95    if (link) {
96      link.aboutToBeDeleted();
97      this.links_.delete(propName);
98      if (this.aviliable_) {
99        this.storage_.delete(propName);
100      }
101    } else {
102      stateMgmtConsole.warn(`DistributedStorage: '${propName}' is not a distributed property warning.`);
103    }
104  }
105
106  private write(key: string): void {
107    let link = this.links_.get(key);
108    if (link) {
109      this.setDistributedProp(key, link.get());
110    }
111  }
112
113
114  // public required by the interface, use the static method instead!
115  public aboutToBeDeleted(): void {
116    stateMgmtConsole.debug("DistributedStorage: about to be deleted");
117    this.links_.forEach((val, key, map) => {
118      stateMgmtConsole.debug(`DistributedStorage: removing ${key}`);
119      val.aboutToBeDeleted();
120    });
121
122    this.links_.clear();
123    SubscriberManager.Delete(this.id__());
124  }
125
126  public id__(): number {
127    return this.id_;
128  }
129
130  public propertyHasChanged(info?: PropertyInfo): void {
131    stateMgmtConsole.debug("DistributedStorage: property changed");
132    this.write(info);
133  }
134
135  public onDataOnChange(propName: string): void {
136    let link = this.links_.get(propName);
137    let newValue = this.getDistributedProp(propName);
138    if (link && newValue != null) {
139        stateMgmtConsole.info(`DistributedStorage: dataOnChange[${propName}-${newValue}]`);
140        link.set(newValue)
141    }
142  }
143
144  public onConnected(status): void {
145    stateMgmtConsole.info(`DistributedStorage onConnected: status = ${status}`);
146    if (!this.aviliable_) {
147        this.syncProp();
148        this.aviliable_ = true;
149    }
150    if (this.notifier_ != null) {
151        this.notifier_(status);
152    }
153  }
154
155  private syncProp(): void {
156    this.links_.forEach((val, key) => {
157        let newValue = this.getDistributedProp(key);
158        if (newValue == null) {
159            this.setDistributedProp(key, val.get());
160        } else {
161            val.set(newValue);
162        }
163    });
164  }
165
166  private setDistributedProp(key, value): void {
167    if (!this.aviliable_) {
168      stateMgmtConsole.warn(`DistributedStorage is not aviliable`);
169        return;
170    }
171    stateMgmtConsole.error(`DistributedStorage value is object ${key}-${JSON.stringify(value)}`);
172    if (typeof value == 'object') {
173        this.storage_.set(key, JSON.stringify(value));
174        return;
175    }
176    this.storage_.set(key, value);
177  }
178
179  private getDistributedProp(key): any {
180    let value = this.storage_.get(key);
181    if (typeof value == 'string') {
182        try {
183            let returnValue = JSON.parse(value);
184            return returnValue;
185        }
186        finally {
187            return value;
188        }
189    }
190    return value;
191  }
192};
193