• 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 * SynchedPropertyObjectTwoWayPU
18 * implementation of @Link and @Consume decorated variables of type class object
19 *
20 * all definitions in this file are framework internal
21 */
22class SynchedPropertyObjectTwoWayPU<C extends Object>
23  extends ObservedPropertyObjectAbstractPU<C>
24  implements PeerChangeEventReceiverPU<C>,
25  ObservedObjectEventsPUReceiver<C> {
26
27  private linkedParentProperty_: ObservedPropertyObjectAbstract<C>;
28  private changeNotificationIsOngoing_: boolean = false;
29
30  constructor(linkSource: ObservedPropertyObjectAbstract<C>,
31    owningChildView: IPropertySubscriber,
32    thisPropertyName: PropertyInfo) {
33    super(owningChildView, thisPropertyName);
34    this.linkedParentProperty_ = linkSource;
35    if (this.linkedParentProperty_) {
36      // register to the parent property
37      this.linkedParentProperty_.subscribeMe(this);
38    }
39
40    // register to the ObservedObject
41    ObservedObject.addOwningProperty(this.linkedParentProperty_.get(), this);
42  }
43
44  /*
45  like a destructor, need to call this before deleting
46  the property.
47  */
48  aboutToBeDeleted() {
49    // unregister from parent of this link
50    if (this.linkedParentProperty_) {
51        this.linkedParentProperty_.unlinkSuscriber(this.id__());
52
53        // unregister from the ObservedObject
54        ObservedObject.removeOwningProperty(this.linkedParentProperty_.getUnmonitored(), this);
55    }
56    super.aboutToBeDeleted();
57  }
58
59  private setObject(newValue: C): void {
60    if (!this.linkedParentProperty_) {
61        stateMgmtConsole.warn(`SynchedPropertyObjectTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: setObject, no linked parent property.`);
62        return;
63    }
64    this.linkedParentProperty_.set(newValue)
65  }
66
67  /**
68   * Called when sync peer ObservedPropertyObject or SynchedPropertyObjectTwoWay has chnaged value
69   * that peer can be in either parent or child component if 'this' is used for a @Link
70   * that peer can be in either acestor or descendant component if 'this' is used for a @Consume
71   * @param eventSource
72   */
73  syncPeerHasChanged(eventSource : ObservedPropertyAbstractPU<C>) {
74    if (!this.changeNotificationIsOngoing_) {
75      stateMgmtConsole.debug(`SynchedPropertyObjectTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: propertyHasChangedPU: contained ObservedObject '${eventSource.info()}' hasChanged'.`)
76      this.notifyPropertyHasChangedPU();
77    }
78  }
79
80  /**
81   * called when wrapped ObservedObject has changed poperty
82   * @param souceObject
83   * @param changedPropertyName
84   */
85  public objectPropertyHasChangedPU(souceObject: ObservedObject<C>, changedPropertyName : string) {
86    stateMgmtConsole.debug(`SynchedPropertyObjectTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: \
87        objectPropertyHasChangedPU: contained ObservedObject property '${changedPropertyName}' has changed.`)
88    this.notifyPropertyHasChangedPU();
89  }
90
91  public objectPropertyHasBeenReadPU(souceObject: ObservedObject<C>, changedPropertyName : string) {
92    stateMgmtConsole.debug(`SynchedPropertyObjectTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: \
93    objectPropertyHasBeenReadPU: contained ObservedObject property '${changedPropertyName}' has been read.`);
94    this.notifyPropertyHasBeenReadPU();
95  }
96
97  public getUnmonitored(): C {
98    stateMgmtConsole.debug(`SynchedPropertyObjectTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: getUnmonitored returns '${(this.linkedParentProperty_ ? JSON.stringify(this.linkedParentProperty_.getUnmonitored()) : "undefined")}' .`);
99    // unmonitored get access , no call to otifyPropertyRead !
100    return (this.linkedParentProperty_ ? this.linkedParentProperty_.getUnmonitored() : undefined);
101  }
102
103  // get 'read through` from the ObservedProperty
104  public get(): C {
105    stateMgmtConsole.debug(`SynchedPropertyObjectTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: get`)
106    this.notifyPropertyHasBeenReadPU()
107    return this.getUnmonitored();
108  }
109
110  // set 'writes through` to the ObservedProperty
111  public set(newValue: C): void {
112    if (this.getUnmonitored() == newValue) {
113      stateMgmtConsole.debug(`SynchedPropertyObjectTwoWayPU[${this.id__()}IP, '${this.info() || "unknown"}']: set with unchanged value '${newValue}'- ignoring.`);
114      return;
115    }
116
117    stateMgmtConsole.debug(`SynchedPropertyObjectTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: set to newValue: '${newValue}'.`);
118
119    ObservedObject.removeOwningProperty(this.getUnmonitored(), this);
120
121    // avoid circular notifications @Link -> source @State -> other but also back to same @Link
122    this.changeNotificationIsOngoing_ = true;
123    this.setObject(newValue);
124    ObservedObject.addOwningProperty(this.getUnmonitored(), this);
125    this.notifyPropertyHasChangedPU();
126    this.changeNotificationIsOngoing_ = false;
127  }
128}
129