1 /* 2 * Copyright (c) 2024 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 #ifndef META_SRC_OBJECT_HIERARCHY_OBSERVER_H 16 #define META_SRC_OBJECT_HIERARCHY_OBSERVER_H 17 18 #include <shared_mutex> 19 20 #include <base/containers/unordered_map.h> 21 22 #include <meta/api/event_handler.h> 23 #include <meta/base/interface_macros.h> 24 #include <meta/base/namespace.h> 25 #include <meta/ext/event_impl.h> 26 #include <meta/interface/builtin_objects.h> 27 #include <meta/interface/intf_attachment.h> 28 #include <meta/interface/intf_object_hierarchy_observer.h> 29 30 #include "object.h" 31 32 META_BEGIN_NAMESPACE() 33 34 class ObjectHierarchyObserver; 35 36 class ObjectChangeListener final { 37 public: 38 META_NO_COPY_MOVE(ObjectChangeListener) 39 ObjectChangeListener() = delete; 40 ~ObjectChangeListener(); 41 42 ObjectChangeListener(const IObject::Ptr& object, HierarchyChangeObjectType myType, const IObject::WeakPtr& parent, 43 ObjectHierarchyObserver* observer, HierarchyChangeModeValue mode); 44 GetType()45 HierarchyChangeObjectType GetType() const 46 { 47 return type_; 48 } 49 50 private: 51 bool Subscribe(HierarchyChangeModeValue mode); 52 void Unsubscribe(); 53 54 void SubscribeContainer(const IObject::Ptr& object); 55 void SubscribeAttachment(const IObject::Ptr& object); 56 57 IObject::WeakPtr object_; 58 HierarchyChangeObjectType type_; 59 IObject::WeakPtr parent_; 60 61 // Currently IContent does not support "OnChanging" and so the content might be destroyed already 62 // which would make it impossible to notify about 63 IObject::Ptr content_; 64 65 ObjectHierarchyObserver* observer_ {}; 66 BASE_NS::vector<EventHandler> handlers_; 67 bool containerPreTransaction_ { false }; 68 bool attachmentPreTransaction_ { false }; 69 70 void NotifyObjectChangedOp(); 71 void NotifyContainerChangeOp( 72 const ChildChangedInfo& info, HierarchyChangeType operation, HierarchyChangeObjectType objectType); 73 void NotifyContainerMoveOp( 74 const ChildChangedInfo& info, HierarchyChangeType operation, HierarchyChangeObjectType objectType); 75 void NotifyContentChangeOp(); 76 }; 77 78 class ObjectHierarchyObserver final : public IntroduceInterfaces<MetaObject, IObjectHierarchyObserver, IAttachment> { 79 META_OBJECT(ObjectHierarchyObserver, ClassId::ObjectHierarchyObserver, IntroduceInterfaces) 80 public: 81 void HierarchyChanged(const HierarchyChangedInfo& info, ObjectChangeListener* listener); 82 83 META_BEGIN_STATIC_DATA() 84 META_STATIC_EVENT_DATA(IObjectHierarchyObserver, IOnHierarchyChanged, OnHierarchyChanged) 85 META_STATIC_PROPERTY_DATA(IAttachment, IObject::WeakPtr, DataContext) 86 META_STATIC_PROPERTY_DATA(IAttachment, IAttach::WeakPtr, AttachedTo, {}) 87 META_END_STATIC_DATA() 88 META_IMPLEMENT_EVENT(IOnHierarchyChanged, OnHierarchyChanged) 89 META_IMPLEMENT_READONLY_PROPERTY(IObject::WeakPtr, DataContext) 90 META_IMPLEMENT_READONLY_PROPERTY(IAttach::WeakPtr, AttachedTo) 91 92 protected: // LifeCycle 93 bool Build(const IMetadata::Ptr&) override; 94 void Destroy() override; 95 96 protected: // IObjectHierarchyObserver 97 void SetTarget(const IObject::Ptr& root, HierarchyChangeModeValue mode) override; 98 IObject::Ptr GetTarget() const override; 99 BASE_NS::vector<IObject::Ptr> GetAllObserved() const override; 100 101 protected: // IAttachment 102 bool Attaching(const META_NS::IAttach::Ptr& target, const META_NS::IObject::Ptr& dataContext) override; 103 bool Detaching(const META_NS::IAttach::Ptr& target) override; 104 105 private: 106 void Subscribe(const IObject::Ptr& root, HierarchyChangeObjectType type, const IObject::WeakPtr& parent = nullptr); 107 void Unsubscribe(const IObject::Ptr& root); 108 void ClearSubscriptions(); 109 void NotifyOnDetach(); 110 111 HierarchyChangeModeValue mode_ {}; 112 IObject::WeakPtr root_; 113 114 struct Subscription final { 115 META_NO_COPY(Subscription) Subscriptionfinal116 Subscription(IObject::WeakPtr object, BASE_NS::unique_ptr<ObjectChangeListener>&& listener) 117 : object_(BASE_NS::move(object)), listener_(BASE_NS::move(listener)) 118 {} 119 ~Subscription() = default; 120 Subscription(Subscription&& other) noexcept = default; 121 Subscription& operator=(Subscription&& other) = default; 122 IObject::WeakPtr object_; 123 BASE_NS::unique_ptr<ObjectChangeListener> listener_; 124 }; 125 126 void AddSubscription(const IObject::Ptr& object, HierarchyChangeObjectType type, const IObject::WeakPtr& parent); 127 void RemoveSubscription(const IObject::Ptr& object); 128 129 void AddImmediateChild(const HierarchyChangedInfo& info); 130 void RemoveImmediateChild(const HierarchyChangedInfo& info); 131 132 BASE_NS::unordered_map<ObjectChangeListener*, Subscription> subscriptions_; 133 struct ImmediateChild { 134 BASE_NS::weak_ptr<IObject> object; 135 HierarchyChangeObjectType type {}; 136 }; 137 bool keepTrackOfImmediate_ {}; 138 BASE_NS::vector<ImmediateChild> immediateChildren_; 139 mutable std::shared_mutex mutex_; 140 }; 141 142 META_END_NAMESPACE() 143 144 #endif // META_SRC_OBJECT_HIERARCHY_OBSERVER_H 145