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