• 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
16/**
17 * Singleton class SubscriberManager implements IPropertySubscriberLookup
18 * public API to manage IPropertySubscriber
19 */
20
21class SubscriberManager {
22
23  private subscriberById_: Map<number, WeakRef<IPropertySubscriber>>;
24
25  private static instance_: SubscriberManager;
26
27  private static nextId_: number = 0;
28
29  private static finalizationRegistry_ = new FinalizationRegistry(subscriberId => {
30    SubscriberManager.GetInstance().subscriberById_?.delete(subscriberId);
31  });
32
33  /**
34    * check subscriber is known
35    * same as ES6 Map.prototype.has()
36    *
37    * @since 9
38    */
39  public static Has(id: number): boolean {
40    return SubscriberManager.GetInstance().has(id);
41  }
42
43  /**
44   *
45   * retrieve subscriber by id
46   * same as ES6 Map.prototype.get()
47   *
48   *  @since 9
49   */
50  public static Find(id: number): IPropertySubscriber {
51    return SubscriberManager.GetInstance().get(id);
52  }
53
54  /**
55   * unregister a subscriber
56   * same as ES6 Map.prototype.delete()
57   * @return boolean success or failure to delete
58   *
59   *  @since 9
60   */
61  public static Delete(id: number): boolean {
62    return SubscriberManager.GetInstance().delete(id);
63  }
64
65  /**
66  * add a new subscriber.
67  * The subscriber must have a new (unused) id (@see MakeId() )
68  * for add() to succeed.
69  * same as Map.prototype.set()
70  *
71  *  @since 9
72  */
73  public static Add(newSubsriber: IPropertySubscriber): boolean {
74    return SubscriberManager.GetInstance().add(newSubsriber);
75  }
76
77  /**
78   * Update recycle custom node element id.
79   */
80  public static UpdateRecycleElmtId(oldId: number, newId: number): boolean {
81    return SubscriberManager.GetInstance().updateRecycleElmtId(oldId, newId);
82  }
83
84  /**
85  *
86  * @returns a globally unique id to be assigned to a IPropertySubscriber objet
87  * Use MakeId() to assign a IPropertySubscriber object an id before calling @see add() .
88  *
89  *  @since 9
90 */
91  public static MakeId(): number {
92    return SubscriberManager.GetInstance().makeId();
93  }
94
95  /**
96   *
97   * @returns a global unique id for state variables.
98   * Unlike MakeId, no need to get id from native side.
99   *
100   * @since 12
101   */
102  public static MakeStateVariableId(): number {
103    return SubscriberManager.nextId_--;
104  }
105
106  /**
107   * Check number of registered Subscriber / registered IDs.
108   * @returns number of registered unique ids.
109   *
110   *  @since 9
111   */
112
113  public static NumberOfSubscribers(): number {
114    return SubscriberManager.GetInstance().numberOfSubscribers();
115  }
116
117  /**
118   *
119   * internal (non-SDK) methods below
120   *
121  */
122
123    /**
124   * Get singleton, create it on first call
125   * @returns SubscriberManager singleton
126   *
127   * internal function
128   * This function will be removed soon, use static functions instead!
129   * Note: Fnction gets used by transpiler output for both full update and partial update
130   */
131   public static Get() : SubscriberManager {
132    if (!SubscriberManager.instance_) {
133      SubscriberManager.instance_ = new SubscriberManager();
134    }
135    return SubscriberManager.instance_;
136   }
137
138  /**
139   * Get singleton, create it on first call
140   * @returns SubscriberManager singleton
141   *
142   * internal function
143   */
144  private static GetInstance() : SubscriberManager {
145    if (!SubscriberManager.instance_) {
146      SubscriberManager.instance_ = new SubscriberManager();
147    }
148    return SubscriberManager.instance_;
149  }
150
151  /**
152   * for debug purposes dump all known subscriber's info to comsole
153   *
154   * not a public / sdk function
155   */
156  public static DumpSubscriberInfo(): void {
157    SubscriberManager.GetInstance().dumpSubscriberInfo();
158  }
159
160  /**
161   * not a public / sdk function
162   * @see Has
163   */
164  public has(id: number): boolean {
165    return !!this.subscriberById_.get(id)?.deref();
166  }
167
168  /**
169   * not a public / sdk function
170   * @see Get
171   */
172  public get(id: number): IPropertySubscriber {
173    return this.subscriberById_.get(id)?.deref();
174  }
175
176  /**
177 * not a public / sdk function
178 * @see Delete
179 */
180  public delete(id: number): boolean {
181    const subscriber = this.get(id);
182    if (!subscriber) {
183      stateMgmtConsole.warn(`SubscriberManager.delete unknown id ${id} `);
184      return false;
185    }
186    SubscriberManager.finalizationRegistry_.unregister(subscriber);
187    return this.subscriberById_.delete(id);
188  }
189
190  /**
191 * not a public / sdk function
192 * @see Add
193 */
194  public add(newSubscriber: IPropertySubscriber): boolean {
195    if (this.has(newSubscriber.id__())) {
196      return false;
197    }
198    this.set(newSubscriber.id__(), newSubscriber);
199    return true;
200  }
201
202  private set(id: number, subscriber: IPropertySubscriber): void {
203    SubscriberManager.finalizationRegistry_.unregister(subscriber);
204    SubscriberManager.finalizationRegistry_.register(subscriber, id, subscriber);
205    this.subscriberById_.set(id, new WeakRef(subscriber));
206  }
207
208  public updateRecycleElmtId(oldId: number, newId: number): boolean {
209    if (!this.has(oldId)) {
210      return false;
211    }
212    const subscriber = this.get(oldId);
213    this.delete(oldId);
214    this.set(newId, subscriber);
215    return true;
216  }
217
218  /**
219   * Method for testing purposes
220   * @returns number of subscribers
221   *
222   * not a public / sdk function
223   */
224  public numberOfSubscribers(): number {
225    return this.subscriberById_.size;
226  }
227
228  /**
229   * for debug purposes dump all known subscriber's info to comsole
230   *
231   * not a public / sdk function
232   */
233  public dumpSubscriberInfo(): void {
234    stateMgmtConsole.debug('Dump of SubscriberManager +++ (sart)');
235    for (let [id, weakRef] of this.subscriberById_) {
236      stateMgmtConsole.debug(`Id: ${id} -> ${weakRef.deref()?.['info'] ? weakRef.deref()?.['info']() : 'unknown'}`);
237    }
238    stateMgmtConsole.debug('Dump of SubscriberManager +++ (end)');
239  }
240
241  /**
242   *
243   * @returns a globally unique id to be assigned to a Subscriber
244   */
245  makeId(): number {
246    return ViewStackProcessor.MakeUniqueId();
247  }
248
249  /**
250   * SubscriberManager is a singleton created by the framework
251   * do not use
252   *
253   * internal method
254   */
255  private constructor() {
256    this.subscriberById_ = new Map<number, WeakRef<IPropertySubscriber>>();
257    stateMgmtConsole.debug('SubscriberManager has been created.');
258  }
259}
260