• 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
16
17/**
18 * ObservedPropertyAbstract base class for the implementation o all state variables
19 * Its base class SubscribedAbstractProperty<T> provides all public / SDK functions.
20 *
21 * This class and all other definitons in this file are framework
22 * internal / non-SDK.
23 *
24 */
25
26type SynchedPropertyFactoryFunc = <T>(source: ObservedPropertyAbstract<T>) => ObservedPropertyAbstract<T>;
27
28/*
29   manage subscriptions to a property
30   managing the property is left to sub
31   classes
32   Extended by ObservedProperty, SyncedPropertyOneWay
33   and SyncedPropertyTwoWay
34*/
35abstract class ObservedPropertyAbstract<T> extends SubscribedAbstractProperty<T> {
36  protected subscribers_: Set<number>
37  private id_: number;
38  protected info_?: PropertyInfo;
39
40  constructor(subscribeMe?: IPropertySubscriber, info?: PropertyInfo) {
41    super();
42    this.subscribers_ = new Set<number>();
43    this.id_ = SubscriberManager.MakeId();
44    SubscriberManager.Add(this);
45    if (subscribeMe) {
46      this.subscribers_.add(subscribeMe.id__());
47    }
48    if (info) {
49      this.info_ = info;
50    }
51  }
52
53  aboutToBeDeleted() {
54    SubscriberManager.Delete(this.id__())
55  }
56
57  id__(): number {
58    return this.id_;
59  }
60
61  public info(): PropertyInfo {
62    return this.info_;
63  }
64
65  public setInfo(propName: PropertyInfo) {
66    if (propName && propName != "") {
67      this.info_ = propName;
68    }
69  }
70
71  public abstract get(): T;
72
73  // Partial Update "*PU" classes will overwrite
74  public getUnmonitored(): T {
75    return this.get();
76  }
77
78  public abstract set(newValue: T): void;
79
80
81  public subscribeMe(subscriber: ISinglePropertyChangeSubscriber<T>): void {
82    stateMgmtConsole.debug(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']: subscribeMe: Property new subscriber '${subscriber.id__()}'`);
83    this.subscribers_.add(subscriber.id__());
84  }
85
86  /*
87    the inverse function of createOneWaySync or createTwoWaySync
88  */
89  public unlinkSuscriber(subscriberId: number): void {
90    this.subscribers_.delete(subscriberId);
91  }
92
93  protected notifyHasChanged(newValue: T) {
94    stateMgmtConsole.debug(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']: notifyHasChanged, notifying.`);
95    this.subscribers_.forEach((subscribedId) => {
96      var subscriber: IPropertySubscriber = SubscriberManager.Find(subscribedId)
97      if (subscriber) {
98        if ('hasChanged' in subscriber) {
99          (subscriber as ISinglePropertyChangeSubscriber<T>).hasChanged(newValue);
100        }
101        if ('propertyHasChanged' in subscriber) {
102          (subscriber as IMultiPropertiesChangeSubscriber).propertyHasChanged(this.info_);
103        }
104      } else {
105        stateMgmtConsole.warn(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']: notifyHasChanged: unknown subscriber ID '${subscribedId}' error!`);
106      }
107    });
108  }
109
110  protected notifyPropertyRead() {
111    stateMgmtConsole.debug(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']: propertyRead.`)
112    this.subscribers_.forEach((subscribedId) => {
113      var subscriber: IPropertySubscriber = SubscriberManager.Find(subscribedId)
114      if (subscriber) {
115        if ('propertyRead' in subscriber) {
116          (subscriber as IMultiPropertiesReadSubscriber).propertyRead(this.info_);
117        }
118      }
119    });
120  }
121
122  /*
123  return numebr of subscribers to this property
124  mostly useful for unit testin
125  */
126  public numberOfSubscrbers(): number {
127    return this.subscribers_.size;
128  }
129
130
131  /**
132   * These functions are meant for use in connection with the App Stoage and
133   * business logic implementation.
134   * the created Link and Prop will update when 'this' property value
135   * changes.
136   *
137   * These functions are depreciated and will be removed
138   * these are replaced with createSync
139   */
140  public abstract createLink(subscribeOwner?: IPropertySubscriber,
141    linkPropName?: PropertyInfo): ObservedPropertyAbstract<T>;
142  public abstract createProp(subscribeOwner?: IPropertySubscriber,
143    linkPropName?: PropertyInfo): ObservedPropertyAbstract<T>;
144
145  /**
146   * provide a factory function that creates a SynchedPropertyXXXX of choice
147   * that uses 'this' as source
148   * @param factoryFunc
149   * @returns
150   */
151  public createSync(factoryFunc: SynchedPropertyFactoryFunc): ObservedPropertyAbstract<T> {
152    return factoryFunc<T>(this);
153  }
154
155  /**
156   * depreciated SDK function, not used anywhere by the framework
157   */
158  public createTwoWaySync(subscribeMe?: IPropertySubscriber, info?: string): SubscribedAbstractProperty<T> {
159    stateMgmtConsole.warn("Using depreciated method 'createTwoWaySync'!")
160    return this.createLink(subscribeMe, info);
161  }
162
163  /**
164   * depreciated SDK function, not used anywhere by the framework
165   */
166  public createOneWaySync(subscribeMe?: IPropertySubscriber, info?: string): SubscribedAbstractProperty<T> {
167    stateMgmtConsole.warn("Using depreciated method 'createOneWaySync' !")
168    return this.createProp(subscribeMe, info);
169  }
170
171  /**
172   * factory function for concrete 'object' or 'simple' ObservedProperty object
173   * depending if value is Class object
174   * or simple type (boolean | number | string)
175   * @param value
176   * @param owningView
177   * @param thisPropertyName
178   * @returns either
179   */
180  static CreateObservedObject<C>(value: C, owningView: IPropertySubscriber, thisPropertyName: PropertyInfo)
181    : ObservedPropertyAbstract<C> {
182    return (typeof value === "object") ?
183      new ObservedPropertyObject(value, owningView, thisPropertyName)
184      : new ObservedPropertySimple(value, owningView, thisPropertyName);
185  }
186}
187