You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
320 lines
10 KiB
C++
320 lines
10 KiB
C++
/***************************************************************************
|
|
* Copyright (C) gempa GmbH *
|
|
* All rights reserved. *
|
|
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
|
* *
|
|
* GNU Affero General Public License Usage *
|
|
* This file may be used under the terms of the GNU Affero *
|
|
* Public License version 3.0 as published by the Free Software Foundation *
|
|
* and appearing in the file LICENSE included in the packaging of this *
|
|
* file. Please review the following information to ensure the GNU Affero *
|
|
* Public License version 3.0 requirements will be met: *
|
|
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
|
* *
|
|
* Other Usage *
|
|
* Alternatively, this file may be used in accordance with the terms and *
|
|
* conditions contained in a signed written agreement between you and *
|
|
* gempa GmbH. *
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#ifndef SEISCOMP_DATAMODEL_NOTIFIER_H__
|
|
#define SEISCOMP_DATAMODEL_NOTIFIER_H__
|
|
|
|
|
|
#include <seiscomp/core.h>
|
|
#include <seiscomp/datamodel/publicobject.h>
|
|
#include <seiscomp/core/genericmessage.h>
|
|
#include <boost/thread/tss.hpp>
|
|
#include <list>
|
|
|
|
|
|
namespace Seiscomp {
|
|
namespace DataModel {
|
|
|
|
|
|
DEFINE_SMARTPOINTER(Notifier);
|
|
// Full namespace specifier needed due to a bug (?) in SWIG >1.3.27
|
|
DEFINE_MESSAGE_FOR(Seiscomp::DataModel::Notifier, NotifierMessage, SC_SYSTEM_CORE_API);
|
|
|
|
class SC_SYSTEM_CORE_API Notifier : public Seiscomp::Core::BaseObject {
|
|
DECLARE_SC_CLASS(Notifier);
|
|
DECLARE_SERIALIZATION;
|
|
DECLARE_METAOBJECT;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Enumerations
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
enum CompareResult {
|
|
CR_DIFFERENT,
|
|
CR_EQUAL,
|
|
CR_OPPOSITE,
|
|
CR_OVERRIDE,
|
|
CR_QUANTITY
|
|
};
|
|
|
|
// ------------------------------------------------------------------
|
|
// Types
|
|
// ------------------------------------------------------------------
|
|
private:
|
|
typedef std::list<NotifierPtr> Pool;
|
|
typedef Pool::iterator PoolIterator;
|
|
typedef Pool::const_iterator PoolConstIterator;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Xstruction
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
/**
|
|
* Constructs a notifier. This custom created notifier will not be
|
|
* inserted into the notifier pool. The user is responsible for
|
|
* sending the notifier in a message.
|
|
*/
|
|
Notifier(const std::string& parentID, Operation, Object* object);
|
|
|
|
protected:
|
|
//! Constructor
|
|
Notifier();
|
|
|
|
public:
|
|
//! Destructor
|
|
~Notifier();
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Interface
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
//! Enables the notifier pool.
|
|
static void Enable();
|
|
|
|
//! Disables the notifier pool. No notifications will be
|
|
//! created at all.
|
|
static void Disable();
|
|
|
|
//! Sets the state of the notifier pool
|
|
static void SetEnabled(bool);
|
|
|
|
//! Returns the notification pool state.
|
|
//! The default is TRUE.
|
|
static bool IsEnabled();
|
|
|
|
//! Enables/disables checking previous inserted notifiers
|
|
//! when a new notifiers is about to be queued. When
|
|
//! enabled, and OP_ADD and OP_UPDATE of the same object
|
|
//! results in only one OP_ADD notifier.
|
|
static void SetCheckEnabled(bool);
|
|
|
|
//! Returns the current 'check' state
|
|
static bool IsCheckEnabled();
|
|
|
|
|
|
/**
|
|
* Returns a message holding all notifications since the
|
|
* last call. All stored notifications will be removed from
|
|
* the notification pool.
|
|
* @param allNotifier Defines whether to return one message
|
|
* including all notifier or one message
|
|
* including one notifier
|
|
* @return The message object, if there is one. If each
|
|
* notifier is send by its own message one should
|
|
* call this method until it returns nullptr.
|
|
*/
|
|
static NotifierMessage* GetMessage(bool allNotifier = true);
|
|
|
|
//! Returns the size of the notifier objects currently stored.
|
|
static size_t Size();
|
|
|
|
//! Clears all buffered notifiers.
|
|
static void Clear();
|
|
|
|
/**
|
|
* Creates a notifier object managed by the global notifier pool.
|
|
* If the notifier pool is disabled no notifier instance will
|
|
* be created.
|
|
* @param parentID The publicId of the parent object that is target
|
|
* of the operation
|
|
* @param op The operation applied to the parent object
|
|
* @param object The object that is the operation's "operand"
|
|
* @return The notifier object. The returned object MUST NOT be
|
|
* deleted by the caller explicitly. Nevertheless one can
|
|
* store a smartpointer to the object.
|
|
*/
|
|
static Notifier* Create(const std::string& parentID,
|
|
Operation op,
|
|
Object* object);
|
|
|
|
/**
|
|
* Creates a notifier object managed by the global notifier pool.
|
|
* If the notifier pool is disabled no notifier instance will
|
|
* be created.
|
|
* @param parent The parent object that is target of the operation
|
|
* @param op The operation applied to the parent object
|
|
* @param object The object that is the operation's "operand"
|
|
* @return The notifier object. The returned object MUST NOT be
|
|
* deleted by the caller explicitly. Nevertheless one can
|
|
* store a smartpointer to the object.
|
|
*/
|
|
static Notifier* Create(PublicObject* parent,
|
|
Operation op,
|
|
Object* object);
|
|
|
|
//! Apply the notification
|
|
bool apply() const;
|
|
|
|
|
|
//! Sets the publicID of the parent object
|
|
void setParentID(const std::string &);
|
|
|
|
//! Returns publicId of the parent object
|
|
const std::string& parentID() const;
|
|
|
|
|
|
//! Sets the operation
|
|
void setOperation(Operation);
|
|
|
|
//! Returns the operation defined for the notifier
|
|
Operation operation() const;
|
|
|
|
|
|
//! Sets the object regarding the operation
|
|
void setObject(Object* object);
|
|
|
|
//! Returns the object regarding the operation
|
|
Object* object() const;
|
|
|
|
/**
|
|
* Compares to notifier by each other and returns the
|
|
* result. Notifier can be EQUAL, that means they express
|
|
* the same thing. They can be DIFFERENT, which means that
|
|
* they do not have anything in common and they can be
|
|
* OPPOSITE to each other meaning they neutralize each other.
|
|
* E.g. n1 = ABCNotifier(OP_ADD, myObject)
|
|
* n2 = ABCNotifier(OP_REMOVE, myObject)
|
|
* n1.cmp(n2) = CR_OPPOSITE
|
|
*/
|
|
CompareResult cmp(const Notifier*) const;
|
|
CompareResult cmp(const Notifier&) const;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Implementation
|
|
// ----------------------------------------------------------------------
|
|
private:
|
|
std::string _parentID;
|
|
Operation _operation;
|
|
ObjectPtr _object;
|
|
|
|
static boost::thread_specific_ptr<bool> _lock;
|
|
static Pool _notifiers;
|
|
static bool _checkOnCreate;
|
|
|
|
DECLARE_SC_CLASSFACTORY_FRIEND(Notifier);
|
|
};
|
|
|
|
|
|
/**
|
|
* \brief A visitor that creates notifiers for a given subtree
|
|
* \brief and appends them to the global notifier pool.
|
|
*/
|
|
class NotifierCreator : public Visitor {
|
|
// ----------------------------------------------------------------------
|
|
// Xstruction
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
//! C'tor
|
|
NotifierCreator(Operation op);
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Interface
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
bool visit(PublicObject*);
|
|
void visit(Object*);
|
|
|
|
private:
|
|
Operation _operation;
|
|
};
|
|
|
|
|
|
/**
|
|
* \brief A visitor that creates notifiers for a given subtree
|
|
* \brief and appends them to a local list
|
|
*/
|
|
template <class T>
|
|
class NotifierStoreAppender : public Visitor {
|
|
// ----------------------------------------------------------------------
|
|
// Xstruction
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
//! C'tor
|
|
NotifierStoreAppender(T &store, Operation op, const std::string &parentID = "")
|
|
: Visitor(op == OP_REMOVE?TM_BOTTOMUP:TM_TOPDOWN),
|
|
_store(&store), _operation(op), _parentID(parentID) {}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Interface
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
bool visit(PublicObject *po) {
|
|
if ( po->parent() == nullptr ) {
|
|
if ( _parentID.empty() )
|
|
return false;
|
|
_store->push_back(new Notifier(_parentID, _operation, po));
|
|
}
|
|
else
|
|
_store->push_back(new Notifier(po->parent()->publicID(), _operation, po));
|
|
return true;
|
|
}
|
|
|
|
void visit(Object *o) {
|
|
if ( o->parent() == nullptr ) {
|
|
if ( _parentID.empty() )
|
|
return;
|
|
_store->push_back(new Notifier(_parentID, _operation, o));
|
|
}
|
|
else
|
|
_store->push_back(new Notifier(o->parent()->publicID(), _operation, o));
|
|
}
|
|
|
|
private:
|
|
T *_store;
|
|
Operation _operation;
|
|
const std::string &_parentID;
|
|
};
|
|
|
|
|
|
template <class T>
|
|
void AppendNotifier(T &store, Operation op, Object *o, const std::string parentID = "") {
|
|
// Remember the size of the store before any modifications
|
|
size_t endPos = store.size();
|
|
|
|
// Create a store appender and visit all child objects
|
|
NotifierStoreAppender<T> nsa(store, op, parentID);
|
|
o->accept(&nsa);
|
|
|
|
// If a parent id was specified and elements have been added to the
|
|
// store, override the parent id of the first object (o). Note: The
|
|
// position of the Notifier of o depends on the operation
|
|
// (OP_ADD vs. OP_REMOVE). It is either the first or the last element
|
|
// added to the store.
|
|
if ( !parentID.empty() && store.size() > endPos ) {
|
|
size_t pos = op == OP_REMOVE ? store.size()-1 : endPos;
|
|
NotifierPtr n = store.at(pos);
|
|
n->setParentID(parentID);
|
|
}
|
|
}
|
|
|
|
|
|
} // of NS DataModel
|
|
} // of NS Seiscomp
|
|
|
|
|
|
#endif
|