• 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 * ObservedPropertyObjectPU
18 * implementation of @State and @Provide decorated variables of type class object
19 *
20 * all definitions in this file are framework internal
21 *
22 * class that holds an actual property value of type T
23 * uses its base class to manage subscribers to this
24 * property.
25*/
26
27class ObservedPropertyObjectPU<T extends Object> extends ObservedPropertyObjectAbstractPU<T>
28  implements PeerChangeEventReceiverPU<T>,
29  ObservedObjectEventsPUReceiver<T> {
30
31  private wrappedValue_: T;
32
33  constructor(value: T, owningView: IPropertySubscriber, propertyName: PropertyInfo) {
34    super(owningView, propertyName);
35    this.setValueInternal(value);
36  }
37
38  aboutToBeDeleted(unsubscribeMe?: IPropertySubscriber) {
39    this.unsubscribeFromOwningProperty();
40    if (unsubscribeMe) {
41      this.unlinkSuscriber(unsubscribeMe.id__());
42    }
43    super.aboutToBeDeleted();
44  }
45
46  /**
47   * Called by a SynchedPropertyObjectTwoWayPU (@Link, @Consume) that uses this as sync peer when it has changed
48   * @param eventSource
49   */
50  syncPeerHasChanged(eventSource : ObservedPropertyAbstractPU<T>) {
51    stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}']: syncPeerHasChanged peer '${eventSource.info()}'.`);
52    this.notifyPropertyHasChangedPU();
53  }
54
55  /**
56   * Wraped ObservedObjectPU has changed
57   * @param souceObject
58   * @param changedPropertyName
59   */
60  public objectPropertyHasChangedPU(souceObject: ObservedObject<T>, changedPropertyName : string) {
61    stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}']: \
62        objectPropertyHasChangedPU: contained ObservedObject property '${changedPropertyName}' has changed.`)
63    this.notifyPropertyHasChangedPU();
64  }
65
66
67  public objectPropertyHasBeenReadPU(souceObject: ObservedObject<T>, changedPropertyName : string) {
68    stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}']: \
69    objectPropertyHasBeenReadPU: contained ObservedObject property '${changedPropertyName}' has been read.`);
70    this.notifyPropertyHasBeenReadPU();
71  }
72
73  private unsubscribeFromOwningProperty() {
74    if (this.wrappedValue_) {
75      if (this.wrappedValue_ instanceof SubscribaleAbstract) {
76        (this.wrappedValue_ as SubscribaleAbstract).removeOwningProperty(this);
77      } else {
78        ObservedObject.removeOwningProperty(this.wrappedValue_, this);
79      }
80    }
81  }
82  /*
83    actually update this.wrappedValue_
84    called needs to do value change check
85    and also notify with this.aboutToChange();
86  */
87  private setValueInternal(newValue: T): boolean {
88    if (typeof newValue !== 'object') {
89      stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}'] new value is NOT an object. Application error. Ignoring set.`);
90      return false;
91    }
92
93    this.unsubscribeFromOwningProperty();
94
95    if (ObservedObject.IsObservedObject(newValue)) {
96      stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}'] new value is an ObservedObject already`);
97      ObservedObject.addOwningProperty(newValue, this);
98      this.wrappedValue_ = newValue;
99    } else if (newValue instanceof SubscribaleAbstract) {
100      stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}'] new value is an SubscribaleAbstract, subscribiung to it.`);
101      this.wrappedValue_ = newValue;
102      (this.wrappedValue_ as unknown as SubscribaleAbstract).addOwningProperty(this);
103    } else {
104      stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}'] new value is an Object, needs to be wrapped in an ObservedObject.`);
105      this.wrappedValue_ = ObservedObject.createNew(newValue, this);
106    }
107    return true;
108  }
109
110  public get(): T {
111    stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}']: get`);
112    this.notifyPropertyHasBeenReadPU();
113    return this.wrappedValue_;
114  }
115
116  public getUnmonitored(): T {
117    stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}']: getUnmonitored returns '${JSON.stringify(this.wrappedValue_)}' .`);
118    // unmonitored get access , no call to otifyPropertyRead !
119    return this.wrappedValue_;
120  }
121
122  public set(newValue: T): void {
123    if (this.wrappedValue_ == newValue) {
124      stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}']: set with unchanged value - ignoring.`);
125      return;
126    }
127    stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}']: set, changed`);
128    this.setValueInternal(newValue);
129    this.notifyPropertyHasChangedPU();
130  }
131}
132