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 * SynchedPropertyObjectTwoWay 18 * 19 * all definitions in this file are framework internal 20 */ 21class SynchedPropertyObjectTwoWay<C extends Object> 22 extends ObservedPropertyObjectAbstract<C> 23 implements ISinglePropertyChangeSubscriber<C> { 24 25 private linkedParentProperty_: ObservedPropertyObjectAbstract<C>; 26 private changeNotificationIsOngoing_: boolean = false; 27 28 constructor(linkSource: ObservedPropertyObjectAbstract<C>, 29 owningChildView: IPropertySubscriber, 30 thisPropertyName: PropertyInfo) { 31 super(owningChildView, thisPropertyName); 32 this.linkedParentProperty_ = linkSource; 33 // register to the parent property 34 this.linkedParentProperty_.subscribeMe(this); 35 36 // register to the ObservedObject 37 ObservedObject.addOwningProperty(this.getObject(), this); 38 } 39 40 /* 41 like a destructor, need to call this before deleting 42 the property. 43 */ 44 aboutToBeDeleted() { 45 if (this.linkedParentProperty_) { 46 // unregister from parent of this link 47 this.linkedParentProperty_.unlinkSuscriber(this.id__()); 48 49 // unregister from the ObservedObject 50 ObservedObject.removeOwningProperty(this.getObject(), this); 51 } 52 super.aboutToBeDeleted(); 53 } 54 55 private getObject(): C { 56 this.notifyPropertyRead(); 57 return (this.linkedParentProperty_ ? this.linkedParentProperty_.get() : undefined); 58 } 59 60 private setObject(newValue: C): void { 61 if (this.linkedParentProperty_) { 62 this.linkedParentProperty_.set(newValue) 63 } 64 } 65 66 // this object is subscriber to ObservedObject 67 // will call this cb function when property has changed 68 hasChanged(newValue: C): void { 69 if (!this.changeNotificationIsOngoing_) { 70 stateMgmtConsole.debug(`SynchedPropertyObjectTwoWay[${this.id__()}, '${this.info() || "unknown"}']: contained ObservedObject hasChanged'.`) 71 this.notifyHasChanged(this.getObject()); 72 } 73 } 74 75 76 77 // get 'read through` from the ObservedProperty 78 public get(): C { 79 stateMgmtConsole.debug(`SynchedPropertyObjectTwoWay[${this.id__()}, '${this.info() || "unknown"}']: get`) 80 return this.getObject(); 81 } 82 83 // set 'writes through` to the ObservedProperty 84 public set(newValue: C): void { 85 if (this.getObject() == newValue) { 86 stateMgmtConsole.debug(`SynchedPropertyObjectTwoWay[${this.id__()}IP, '${this.info() || "unknown"}']: set with unchanged value '${newValue}'- ignoring.`); 87 return; 88 } 89 90 stateMgmtConsole.debug(`SynchedPropertyObjectTwoWay[${this.id__()}, '${this.info() || "unknown"}']: set to newValue: '${newValue}'.`); 91 92 ObservedObject.removeOwningProperty(this.getObject(), this); 93 94 // the purpose of the changeNotificationIsOngoing_ is to avoid 95 // circular notifications @Link -> source @State -> other but alos same @Link 96 this.changeNotificationIsOngoing_ = true; 97 this.setObject(newValue); 98 ObservedObject.addOwningProperty(this.getObject(), this); 99 this.notifyHasChanged(newValue); 100 this.changeNotificationIsOngoing_ = false; 101 } 102 103 /** 104 * These functions are meant for use in connection with the App Stoage and 105 * business logic implementation. 106 * the created Link and Prop will update when 'this' property value 107 * changes. 108 */ 109 public createLink(subscribeOwner?: IPropertySubscriber, 110 linkPropName?: PropertyInfo): ObservedPropertyAbstract<C> { 111 return new SynchedPropertyObjectTwoWay(this, subscribeOwner, linkPropName); 112 } 113 public createProp(subscribeOwner?: IPropertySubscriber, 114 linkPropName?: PropertyInfo): ObservedPropertyAbstract<C> { 115 throw new Error("Creating a 'Prop' property is unsupported for Object type property value."); 116 } 117 118} 119