#ifndef __AlertMatricies_h_ #define __AlertMatricies_h_ #include "BlackList.h" #include "../misc_framework/GenericDataNodes.h" #include "AlertBase.h" #include "../../fast_alert_search/DataFormat.h" // In the Dephi version TAlertCategory was just a base class. It could be // extended to have more information. In principal, the GUI version and the // database version are both valid extensions. However, in practice, we never // used it that way. We extended the GUI version to make the database version. // Here I'm just making one single class to cover the base mechanism, and the // extra stuff needed for the database. This version is simpler; most // importantly we don't need to use pointers since we have only one class. // An AlertCategory is like a column in a market view. struct AlertCategory { DataNodeArgument factory; std::string alertType; bool isAlert() const { return !alertType.empty(); } bool forTopList() const { return alertType.empty(); } }; // This, too, could be overriden in the Delphi code. But it never was. // An AlertInputs is like a row in a market view. class AlertInputs { private: std::string _symbol; public: // The object created by the default constructor is not very interesting. // I created it mostly so that AlertEvent could be a simple struct, with // no explicit constructor. AlertInputs(std::string symbol = "") : _symbol(symbol) { } AlertInputs(char const *symbol) : _symbol(symbol) { } DataNodeArgument doReplacements(DataNodeArgument factory) const; std::string getSymbol() const { return _symbol; } }; class AlertEvent : public Request { public: AlertEvent() : Request(NULL) { } RecordBuilder recordBuilder; bool isAlert; // false ==> top list entry. // We explicitly do not send the alert inputs or alert category any more. // This was a neat idea -- it was very flexible -- but it wasn't necessary. // And it might have caused problems. AlertCategory contains a // DataNodeArgument, and DataNodeArgument objects are not thread safe. // We never actually saw a failure, but the code was inappropriate. }; // This replaces TAlertQueue in the Delphi version. A simpler listener // seems sufficient. I'd expect the "live" version of the code to pack this // into a request and send it to a different thread; we already have message // queues for that. A debug version of the code would not even need to run // in its own thread; it could simply send each response to the log file. If // we ever needed some other type of queue, it would be easy to create one with // STL. class AlertMatrixListener { public: // When we give this pointer to the listener, the listener is responsible // for deleting it. virtual void onAlert(AlertEvent *event) =0; virtual ~AlertMatrixListener() { } }; class AlertBackgroundData; // This is a lot simpler than the Delphi version. This keeps the basic idea // that we have a set of symbols, and a set of alert factories. This object // creates a set of alert objects which are the cross product of these two // sets. However, we are missing the ability to delete individual symbols // or factories. And we don't make any effort to split up large jobs into // smaller jobs. And we don't try to detect and ignore duplicates in the // inputs. class AlertMatrix { private: AlertMatrixListener *const _externalListener; std::vector< AlertCategory > _categoryList; std::vector< AlertInputs > _inputsList; class Listener : NoCopy, NoAssign, public DataNodeListener { private: const AlertCategory _category; const AlertInputs _inputs; AlertMatrixListener *const _externalListener; Alert *_alertNode; DataNodeLink *_alertLink; AlertBackgroundData *_backgroundData; DataNodeLink *_backgroundLink; BlackList *_blackListData; DataNodeLink *_blackListLink; void onWakeup(int msgId); public: Listener(AlertCategory const &category, AlertInputs const &inputs, AlertMatrixListener *externalListener); ~Listener(); }; std::vector< Listener * > _listeners; void add(AlertCategory const &category, AlertInputs const &inputs); public: AlertMatrix(AlertMatrixListener *listener); ~AlertMatrix(); void add(AlertCategory const &category); void add(AlertInputs const &inputs); bool empty() const { return _categoryList.empty() && _inputsList.empty(); } }; #endif