• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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