• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 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 ContentStorage {
17  private storage_: Map<string, ObservedPropertyAbstract<any>>;
18
19  constructor() {
20    this.storage_ = new Map<string, ObservedPropertyAbstract<any>>();
21  }
22
23  public has(propName: string): boolean {
24    return this.storage_.has(propName);
25  }
26
27  public get<T>(key: string): T | undefined {
28    var p: ObservedPropertyAbstract<T> | undefined = this.storage_.get(key);
29    return (p) ? p.get() : undefined;
30  }
31
32  public set<T>(propName: string, newValue: T): boolean {
33    var p: ObservedPropertyAbstract<T> | undefined = this.storage_.get(propName);
34    if (p) {
35      p.set(newValue);
36      return true;
37    } else {
38      return false;
39    }
40  }
41
42 public setOrCreate<T>(propName: string, newValue: T, linkUser?: IPropertySubscriber): void {
43    var p: ObservedPropertyAbstract<T> = this.storage_.get(propName);
44    if (p) {
45      console.log(`ContentStorage.setOrCreate(${propName}, ${newValue}) update existing property`);
46      p.set(newValue);
47    } else {
48      console.log(`ContentStorage.setOrCreate(${propName}, ${newValue}) create new entry and set value`);
49      const newProp = (typeof newValue === "object") ?
50      new ObservedPropertyObject<T>(newValue, linkUser, propName)
51        : new ObservedPropertySimple<T>(newValue, linkUser, propName);
52      this.storage_.set(propName, newProp);
53    }
54  }
55
56  public delete(propName: string): boolean {
57    var p: ObservedPropertyAbstract<any> | undefined = this.storage_.get(propName);
58    if (p) {
59      if (p.numberOfSubscrbers()) {
60        console.error(`Attempt to delete property ${propName} that has ${p.numberOfSubscrbers()} subscribers. Subscribers need to unsubscribe before prop deletion.`);
61        return false;
62      }
63      p.aboutToBeDeleted();
64      this.storage_.delete(propName);
65      return true;
66    } else {
67      console.warn(`Attempt to delete unknown property ${propName}.`);
68      return false;
69    }
70  }
71
72  public keys(): IterableIterator<string> {
73    return this.storage_.keys();
74  }
75
76  public size(): number {
77    return this.storage_.size;
78  }
79
80  public aboutToBeDeleted(): boolean {
81    return this.clear();
82  }
83
84  public numberOfSubscribersTo(propName: string): number | undefined {
85    var p: ObservedPropertyAbstract<any> | undefined = this.storage_.get(propName);
86    if (p) {
87      return p.numberOfSubscrbers();
88    }
89    return undefined;
90  }
91
92  public subscribeToChangesOf<T>(propName: string, subscriber: ISinglePropertyChangeSubscriber<T>): boolean {
93    var p: ObservedPropertyAbstract<T> | undefined = this.storage_.get(propName);
94    if (p) {
95      p.subscribeMe(subscriber);
96      return true;
97    }
98    return false;
99  }
100
101  public unsubscribeFromChangesOf(propName: string, subscriberId: number): boolean {
102    var p: ObservedPropertyAbstract<any> | undefined = this.storage_.get(propName);
103    if (p) {
104      p.unlinkSuscriber(subscriberId);
105      return true;
106    }
107    return false;
108  }
109
110  public isMutable(key: string): boolean {
111    return true;
112  }
113
114  public clear(): boolean {
115    for (let propName of this.keys()) {
116      var p: ObservedPropertyAbstract<any> = this.storage_.get(propName);
117      if (p.numberOfSubscrbers()) {
118       console.error(`ContentStorage.deleteAll: Attempt to delete property ${propName} that has ${p.numberOfSubscrbers()} subscribers. Subscribers need to unsubscribe before prop deletion.`);
119        return false;
120      }
121    }
122    for (let propName of this.keys()) {
123      var p: ObservedPropertyAbstract<any> = this.storage_.get(propName);
124      p.aboutToBeDeleted();
125    }
126    console.error(`ContentStorage.deleteAll: success`);
127  }
128
129  public link<T>(propName: string, linkUser?: IPropertySubscriber): ObservedPropertyAbstract<T> | undefined {
130    var p: ObservedPropertyAbstract<T> | undefined = this.storage_.get(propName);
131    return (p) ? p.createLink(linkUser, propName) : undefined
132  }
133
134  public setAndLink<T>(propName: string, defaultValue: T, linkUser?: IPropertySubscriber): ObservedPropertyAbstract<T> {
135    var p: ObservedPropertyAbstract<T> | undefined = this.storage_.get(propName);
136    if (!p) {
137      this.setOrCreate(propName, defaultValue, linkUser);
138    }
139    return this.link(propName, linkUser);
140  }
141
142  public prop<S>(propName: string, propUser?: IPropertySubscriber): ObservedPropertyAbstract<S> | undefined {
143    var p: ObservedPropertyAbstract<S> | undefined = this.storage_.get(propName);
144    return (p) ? p.createProp(propUser, propName) : undefined
145  }
146
147  public setAndProp<S>(propName: string, defaultValue: S, propUser?: IPropertySubscriber): ObservedPropertyAbstract<S> {
148    var p: ObservedPropertyAbstract<S> | undefined = this.storage_.get(propName);
149
150    if (!p) {
151      if (typeof defaultValue === "boolean" ||
152        typeof defaultValue === "number" || typeof defaultValue === "string") {
153        this.setOrCreate(propName, defaultValue, propUser);
154      } else {
155        return undefined;
156      }
157    }
158    return this.prop(propName, propUser);
159  }
160}