18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci#ifndef META_SRC_OBJECT_HIERARCHY_OBSERVER_H
168bf80f4bSopenharmony_ci#define META_SRC_OBJECT_HIERARCHY_OBSERVER_H
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <shared_mutex>
198bf80f4bSopenharmony_ci
208bf80f4bSopenharmony_ci#include <base/containers/unordered_map.h>
218bf80f4bSopenharmony_ci
228bf80f4bSopenharmony_ci#include <meta/api/event_handler.h>
238bf80f4bSopenharmony_ci#include <meta/ext/event_impl.h>
248bf80f4bSopenharmony_ci#include <meta/interface/builtin_objects.h>
258bf80f4bSopenharmony_ci#include <meta/interface/intf_attachment.h>
268bf80f4bSopenharmony_ci#include <meta/interface/intf_object_hierarchy_observer.h>
278bf80f4bSopenharmony_ci
288bf80f4bSopenharmony_ci#include "object.h"
298bf80f4bSopenharmony_ci
308bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE()
318bf80f4bSopenharmony_ci
328bf80f4bSopenharmony_ciclass ObjectHierarchyObserver;
338bf80f4bSopenharmony_ci
348bf80f4bSopenharmony_ciclass ObjectChangeListener final {
358bf80f4bSopenharmony_cipublic:
368bf80f4bSopenharmony_ci    META_NO_COPY_MOVE(ObjectChangeListener)
378bf80f4bSopenharmony_ci    ObjectChangeListener() = delete;
388bf80f4bSopenharmony_ci    ~ObjectChangeListener();
398bf80f4bSopenharmony_ci
408bf80f4bSopenharmony_ci    ObjectChangeListener(const IObject::Ptr& object, HierarchyChangeObjectType myType, const IObject::WeakPtr& parent,
418bf80f4bSopenharmony_ci        ObjectHierarchyObserver* observer, HierarchyChangeModeValue mode);
428bf80f4bSopenharmony_ci
438bf80f4bSopenharmony_ci    HierarchyChangeObjectType GetType() const
448bf80f4bSopenharmony_ci    {
458bf80f4bSopenharmony_ci        return type_;
468bf80f4bSopenharmony_ci    }
478bf80f4bSopenharmony_ci
488bf80f4bSopenharmony_ciprivate:
498bf80f4bSopenharmony_ci    bool Subscribe(HierarchyChangeModeValue mode);
508bf80f4bSopenharmony_ci    void Unsubscribe();
518bf80f4bSopenharmony_ci
528bf80f4bSopenharmony_ci    void SubscribeContainer(const IObject::Ptr& object);
538bf80f4bSopenharmony_ci    void SubscribeAttachment(const IObject::Ptr& object);
548bf80f4bSopenharmony_ci
558bf80f4bSopenharmony_ci    IObject::WeakPtr object_;
568bf80f4bSopenharmony_ci    HierarchyChangeObjectType type_;
578bf80f4bSopenharmony_ci    IObject::WeakPtr parent_;
588bf80f4bSopenharmony_ci
598bf80f4bSopenharmony_ci    // Currently IContent does not support "OnChanging" and so the content might be destroyed already
608bf80f4bSopenharmony_ci    // which would make it impossible to notify about
618bf80f4bSopenharmony_ci    IObject::Ptr content_;
628bf80f4bSopenharmony_ci
638bf80f4bSopenharmony_ci    ObjectHierarchyObserver* observer_ {};
648bf80f4bSopenharmony_ci    BASE_NS::vector<EventHandler> handlers_;
658bf80f4bSopenharmony_ci    bool containerPreTransaction_ { false };
668bf80f4bSopenharmony_ci    bool attachmentPreTransaction_ { false };
678bf80f4bSopenharmony_ci
688bf80f4bSopenharmony_ci    void NotifyObjectChangedOp();
698bf80f4bSopenharmony_ci    void NotifyContainerChangeOp(
708bf80f4bSopenharmony_ci        const ChildChangedInfo& info, HierarchyChangeType operation, HierarchyChangeObjectType objectType);
718bf80f4bSopenharmony_ci    void NotifyContainerMoveOp(
728bf80f4bSopenharmony_ci        const ChildMovedInfo& info, HierarchyChangeType operation, HierarchyChangeObjectType objectType);
738bf80f4bSopenharmony_ci    void NotifyContentChangeOp();
748bf80f4bSopenharmony_ci};
758bf80f4bSopenharmony_ci
768bf80f4bSopenharmony_ciclass ObjectHierarchyObserver final : public Internal::MetaObjectFwd<ObjectHierarchyObserver,
778bf80f4bSopenharmony_ci                                          ClassId::ObjectHierarchyObserver, IObjectHierarchyObserver, IAttachment> {
788bf80f4bSopenharmony_ci    using Super = Internal::MetaObjectFwd<ObjectHierarchyObserver, ClassId::ObjectHierarchyObserver,
798bf80f4bSopenharmony_ci        IObjectHierarchyObserver, IAttachment>;
808bf80f4bSopenharmony_ci
818bf80f4bSopenharmony_cipublic:
828bf80f4bSopenharmony_ci    void HierarchyChanged(const HierarchyChangedInfo& info, ObjectChangeListener* listener);
838bf80f4bSopenharmony_ci
848bf80f4bSopenharmony_ciprotected: // LifeCycle
858bf80f4bSopenharmony_ci    bool Build(const IMetadata::Ptr&) override;
868bf80f4bSopenharmony_ci    void Destroy() override;
878bf80f4bSopenharmony_ci
888bf80f4bSopenharmony_ciprotected: // IObjectHierarchyObserver
898bf80f4bSopenharmony_ci    void SetTarget(const IObject::Ptr& root, HierarchyChangeModeValue mode) override;
908bf80f4bSopenharmony_ci    IObject::Ptr GetTarget() const override;
918bf80f4bSopenharmony_ci    BASE_NS::vector<IObject::Ptr> GetAllObserved() const override;
928bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_EVENT(IObjectHierarchyObserver, IOnHierarchyChanged, OnHierarchyChanged)
938bf80f4bSopenharmony_ci
948bf80f4bSopenharmony_ciprotected: // IAttachment
958bf80f4bSopenharmony_ci    bool Attaching(const META_NS::IAttach::Ptr& target, const META_NS::IObject::Ptr& dataContext) override;
968bf80f4bSopenharmony_ci    bool Detaching(const META_NS::IAttach::Ptr& target) override;
978bf80f4bSopenharmony_ci
988bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(IAttachment, IObject::WeakPtr, DataContext);
998bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(IAttachment, IAttach::WeakPtr, AttachedTo, {});
1008bf80f4bSopenharmony_ci
1018bf80f4bSopenharmony_ciprivate:
1028bf80f4bSopenharmony_ci    void Subscribe(const IObject::Ptr& root, HierarchyChangeObjectType type, const IObject::WeakPtr& parent = nullptr);
1038bf80f4bSopenharmony_ci    void Unsubscribe(const IObject::Ptr& root);
1048bf80f4bSopenharmony_ci    void ClearSubscriptions();
1058bf80f4bSopenharmony_ci    void NotifyOnDetach();
1068bf80f4bSopenharmony_ci
1078bf80f4bSopenharmony_ci    HierarchyChangeModeValue mode_ {};
1088bf80f4bSopenharmony_ci    IObject::WeakPtr root_;
1098bf80f4bSopenharmony_ci
1108bf80f4bSopenharmony_ci    struct Subscription final {
1118bf80f4bSopenharmony_ci        META_NO_COPY(Subscription)
1128bf80f4bSopenharmony_ci        Subscription(IObject::WeakPtr object, BASE_NS::unique_ptr<ObjectChangeListener>&& listener)
1138bf80f4bSopenharmony_ci            : object_(BASE_NS::move(object)), listener_(BASE_NS::move(listener))
1148bf80f4bSopenharmony_ci        {}
1158bf80f4bSopenharmony_ci        ~Subscription() = default;
1168bf80f4bSopenharmony_ci        Subscription(Subscription&& other) noexcept = default;
1178bf80f4bSopenharmony_ci        Subscription& operator=(Subscription&& other) = default;
1188bf80f4bSopenharmony_ci        IObject::WeakPtr object_;
1198bf80f4bSopenharmony_ci        BASE_NS::unique_ptr<ObjectChangeListener> listener_;
1208bf80f4bSopenharmony_ci    };
1218bf80f4bSopenharmony_ci
1228bf80f4bSopenharmony_ci    void AddSubscription(const IObject::Ptr& object, HierarchyChangeObjectType type, const IObject::WeakPtr& parent);
1238bf80f4bSopenharmony_ci    void RemoveSubscription(const IObject::Ptr& object);
1248bf80f4bSopenharmony_ci
1258bf80f4bSopenharmony_ci    void AddImmediateChild(const HierarchyChangedInfo& info);
1268bf80f4bSopenharmony_ci    void RemoveImmediateChild(const HierarchyChangedInfo& info);
1278bf80f4bSopenharmony_ci
1288bf80f4bSopenharmony_ci    BASE_NS::unordered_map<ObjectChangeListener*, Subscription> subscriptions_;
1298bf80f4bSopenharmony_ci    struct ImmediateChild {
1308bf80f4bSopenharmony_ci        BASE_NS::weak_ptr<IObject> object;
1318bf80f4bSopenharmony_ci        HierarchyChangeObjectType type {};
1328bf80f4bSopenharmony_ci    };
1338bf80f4bSopenharmony_ci    bool keepTrackOfImmediate_ {};
1348bf80f4bSopenharmony_ci    BASE_NS::vector<ImmediateChild> immediateChildren_;
1358bf80f4bSopenharmony_ci    mutable std::shared_mutex mutex_;
1368bf80f4bSopenharmony_ci};
1378bf80f4bSopenharmony_ci
1388bf80f4bSopenharmony_ciMETA_END_NAMESPACE()
1398bf80f4bSopenharmony_ci
1408bf80f4bSopenharmony_ci#endif // META_SRC_OBJECT_HIERARCHY_OBSERVER_H
141