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 * 19 * all definitions in this file are framework internal 20 * 21 * class that holds an actual property value of type T 22 * uses its base class to manage subscribers to this 23 * property. 24*/ 25 26class ObservedPropertyObjectPU<T extends Object> extends ObservedPropertyObjectAbstractPU<T> 27 implements ISinglePropertyChangeSubscriber<T> { 28 29 private wrappedValue_: T; 30 31 constructor(value: T, owningView: IPropertySubscriber, propertyName: PropertyInfo) { 32 super(owningView, propertyName); 33 this.setValueInternal(value); 34 } 35 36 aboutToBeDeleted(unsubscribeMe?: IPropertySubscriber) { 37 this.unsubscribeFromOwningProperty(); 38 if (unsubscribeMe) { 39 this.unlinkSuscriber(unsubscribeMe.id__()); 40 } 41 super.aboutToBeDeleted(); 42 } 43 44 // notification from ObservedObject value one of its 45 // props has chnaged. Implies the ObservedProperty has changed 46 // Note: this function gets called when in this case: 47 // thisProp.aObsObj.aProp = 47 a object prop gets changed 48 // It is NOT called when 49 // thisProp.aObsObj = new ClassA 50 hasChanged(newValue: T): void { 51 stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}']: hasChanged`); 52 this.notifyHasChanged(this.wrappedValue_); 53 } 54 55 private unsubscribeFromOwningProperty() { 56 if (this.wrappedValue_) { 57 if (this.wrappedValue_ instanceof SubscribaleAbstract) { 58 (this.wrappedValue_ as SubscribaleAbstract).removeOwningProperty(this); 59 } else { 60 ObservedObject.removeOwningProperty(this.wrappedValue_, this); 61 } 62 } 63 } 64 /* 65 actually update this.wrappedValue_ 66 called needs to do value change check 67 and also notify with this.aboutToChange(); 68 */ 69 private setValueInternal(newValue: T): boolean { 70 if (typeof newValue !== 'object') { 71 stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}'] new value is NOT an object. Application error. Ignoring set.`); 72 return false; 73 } 74 75 this.unsubscribeFromOwningProperty(); 76 77 if (ObservedObject.IsObservedObject(newValue)) { 78 stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}'] new value is an ObservedObject already`); 79 ObservedObject.addOwningProperty(newValue, this); 80 this.wrappedValue_ = newValue; 81 } else if (newValue instanceof SubscribaleAbstract) { 82 stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}'] new value is an SubscribaleAbstract, subscribiung to it.`); 83 this.wrappedValue_ = newValue; 84 (this.wrappedValue_ as unknown as SubscribaleAbstract).addOwningProperty(this); 85 } else { 86 stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}'] new value is an Object, needs to be wrapped in an ObservedObject.`); 87 this.wrappedValue_ = ObservedObject.createNew(newValue, this); 88 } 89 return true; 90 } 91 92 public get(): T { 93 stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}']: get`); 94 this.notifyPropertyRead(); 95 return this.wrappedValue_; 96 } 97 98 public getUnmonitored(): T { 99 stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}']: getUnmonitored returns '${JSON.stringify(this.wrappedValue_)}' .`); 100 // unmonitored get access , no call to otifyPropertyRead ! 101 return this.wrappedValue_; 102 } 103 104 public set(newValue: T): void { 105 if (this.wrappedValue_ == newValue) { 106 stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}']: set with unchanged value - ignoring.`); 107 return; 108 } 109 stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}']: set, changed`); 110 this.setValueInternal(newValue); 111 this.notifyHasChanged(newValue); 112 } 113} 114