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