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