#include <Dictionary.h> template <class T> class DictionaryObserver { public: virtual void onAdd(std::string name, T& item) {} virtual void onRemove( std::string name, T& item) {} }; template <class T> class CDictionaryObserverManager { void addObserver(DictionaryObserver<T>* observer); void removeObserver(DictionaryObserver<T>* observer); void invokeAdd(const std::string name, T& item); void invokeRemove(const std::string name, T& item); }; template <class T> class CDictionary { DictionaryIterator Lookup(std::string sName); ConstDictionaryIterator Lookup(std::string sName); template<class Predicate> DictionaryIterator FindMatch(Predicate p); template<class Predicate> ConstDictionaryIterator FindMatch(Predicate p); void Enter(std::string sName, T& Item); void Remove(std::string rsName); DictionaryIterator begin(); ConstDictionaryIterator begin() const; DictionaryIterator end(); ConstDictionaryIterator end() const ; UInt_t size() const; void addObserver(DictionaryObserver<T>* observer); void removeObserver(DictionaryObserver<T>* observer); };
#include <DictionaryException> class CDictionaryException : public CException { public: enum { knDuplicateKey, knDuplicateId, knNoSuchId, knNoSuchKey, knWrongGateType }; public: CDictionaryException(Int_t nReason, const char* pDoing, const char* pName); CDictionaryException(Int_t nReason, const char* pDoing, const std::string& rName); CDictionaryException(Int_t nReason, const std::string& rDoing, const char* pName); CDictionaryException(Int_t nReason, const std::string& rDoing, const std::string& rName); CDictionaryException(Int_t nReason, const char* pDoing, UInt_t nId) ; CDictionaryException(Int_t nReason, const std::string& rDoing, UInt_t nId) ; virtual const char* ReasonText () const; virtual Int_t ReasonCode () const ; };
#include <CFitDictionary.h> class CFitDictionary { public: typedef std::map<std::string, CSpectrumFit*> FitMap; typedef FitMap::iterator iterator; class CObserver { public: virtual void Add(CSpectrumFit& fit) =0; virtual void Delete(CSpectrumFit& fit) = 0; virtual void Update(CSpectrumFit& fit) = 0; }; typedef std::list<CObserver*> ObserverList; static CFitDictionary& getInstance(); void add(CSpectrumFit& fit); void addOrReplace(CSpectrumFit& fit); void Delete(std::string name); iterator begin(); iterator end(); size_t size(); iterator find(std::string name); void erase(iterator here); void erase(iterator first, iterator last); void updateFits(std::string name=std::string("*")); void addObserver(CObserver& obs); void removeObserver(CObserver& obs); };
This page describes SpecTcl dictionaries and their related classes.
The CDictionary
class is a templated
class that associates names with arbitrary objects. It adds to the
std::map
class the ability to maintain
a set of observers. Observers are objects
that are informed of changes in the dictionary (specifically
the addition and removal of items from the dictionary).
Closely related to the CDictionary
class,
therefore are DictionaryObserver
, the
templated base class of observers. Applications will subclass this
and provide the appropriate template arguments for the dictionary
used to make use of them. Note that in most cases where SpecTcl
uses a dictionary, it provides a typedef for the observer base class
that already has provided the template parameters.
CDictionaryObserverManager
is actually
usable by wrapers of any name/value container (e.g. hashes and
multimaps). It maintains a list of observer and provides
methods to invoke the observers it maintains.
The CDictionaryException
class provides
an exception derived from CException
SpecTcl throws for many dictionary use violations. These
are not normally thrown by the dictionary itself but by SpecTcl
code that provides a higher level API to specific dictionaries.
For example, the CHistogrammer
throws these
if there is an attempt to duplicate the name or id of a dictionary
entry.
The CFitDictionary
provides a dictionary
that manages SpecTcl fit objects. In addition, the observers
maintained by fit dictionaries, contain a callback that is invoked
if a fit is modified, as well as if it is added or removed
from the dictionary.
void addObserver( DictionaryObserver<T>* observer);
Adds an observer
to the list of observers managed by
this object. Observers are an ordered list. The
new observer
is added to the
end of the list.
void removeObserver( DictionaryObserver<T>* observer);
Removes an observer
from the
list of observers managed by this object. Note that
while it is pathalogical, it is legal to register
the same observer object more than once. If
removeObserver
is asked to
remove an observer that is multiply registered,
all instances of that observer are removed.
void invokeAdd(const std::string name, T& item);
Iterates over the list of observer objects this object
maintains. For each observer, the
onAdd
method is invoked
with the parameters passed to invokeAdd
.
void invokeRemove(const std::string name, T& item);
Same as invokeAddd
but each object's onRemove
is called instead.
Note that this is a base class. Real observers are classes that inherit from this one.
virtual void onAdd( std::string name, T& item);
This method is invoked when an item is added to a
dictionary. name
is the name of
the item (dictionary key), item
refers to the item about to be added. Note that
the base class implementation does nothing. If you
don't need to observe dictionary additions simply don't
override this method.
virtual void onRemove( std::string name, T& item);
This method is invoked when an item is about to be
removed from a dictionary. name
is the name (dictionary index) of the item and
item
refers to the item.
At the time this method is called, the item is still in the dictionary. The item is only removed from the dictionary after all observers have been invoked.
The base class implementation is empty. Therefore if your observer does not need to observer dictionary removals, simply don't override the implementation of this method.
DictionaryIterator Lookup( std::string sName);
,
ConstDictionaryIterator Lookup( std::string sName);
Returns a DictionaryIterator
that points to a
std::pair<std::string, T>
object that has a name that is the same as
sName
. The first item of the
pair should be equal to sName
and is the name of the item in the dictionary.
The second item of the pair should be the item which is
associated with that key.
This method requires that T
have a copy constructor or be trivially copy constructable.
If there is no match for sName
in the dictionary, the value returned by
end
is returned.
template<class Predicate> DictionaryIterator FindMatch( Predicate p);
,
template<class Predicate> ConstDictionaryIterator FindMatch( Predicate p);
Performs an search using an arbitrary predicate;
p
as the matching criterion.
The return value is a dictionary iterator as
described in Lookup
above.
p
is any class that implements
the operator()
taking as a
single parameter a
std::pair<std::string, T>
object. The first item of the pair is the name of some
entry in the dictionary. The second is the entry with
that name. The predicate must return a
value that can be converte to bool. If
the return is true, the item
is treated as satisfying the match. If not iteration
continues with different pairs until either the entire
container has been checked or a match is found.
void Enter( std::string sName, T& Item);
Adds Item
to the dictionary indexed
by sName
. If an item already
exists with that name it's overwitten. If
T is a pointer to dynamically allocated
objets, this results in memory leaks unless the
dictionary is encapsulated by a derived class or front-ended
by an API.
Many SpecTcl dictionaries live privately in enclosing
classes like CHistogram
.
In some cases (e.g. the parameter and spectrum
dictionaries), these classes impose an API that throws
errors if duplicate entries are attempted.
void Remove( std::string rsName);
Removes the entry whose index is
rsName
. This does nothing
if there is no entry with the index
rsName
.
Many SpecTcl dictionaries are encapsulated by other classes. In some cases those classes throw exceptions if attempts are made to remove nonexistent objects.
DictionaryIterator begin();
,
const ConstDictionaryIterator begin ();
,
DictionaryIterator end();
,
const ConstDictionaryIterator end ();
These methods support iteration over dictionary contents.
DictionaryIterator
and
ConstDictionaryIterator
are
pointer like objects. They 'point' to
std::pair<std::string, T>
objects. The first item of the pair is a dictionary
key. The second, the object stored at that key.
begin
returns an iterator
to the first element of the container. Currently,
this is the one with the key that collates earliest.
Incrementing an iterator points it to another element
of the container. Currently, the iterator traverses
the container in increasing collation order with respect
to the key.
If an iterator points to the last element of the
dict, incrementing it results in the same value
returned from the end
method. The iterators returned by these methods
are compatible with the C++ standard library algorithms
that accept container iterators.
const UInt_t size();
Returns the number of elements stored in the dictionary.
void addObserver( DictionaryObserver<T>* observer);
,
void removeObserver( DictionaryObserver<T>* observer);
These methods support observation of the dictionary.
addObserver
adds an
observer
that will be called when items are added
or removed from the dictionary. Observers have been
previously described.
removeObserver
removes the
observer
from the list of
observers that monitor the dictionary.
While it is pathalogical, addObserver
does not prevent you from adding the same observer object
more than once. If have added a specific observer more
than onece, removeObserver
removes all instances of that observer from
the dictionary's CDictionaryObserverManager
object.
Before providing reference material to CDictionaryException
,
Let's first look at the public enum that provides the valid
values for the reason code in the destructor:
enum { knDuplicateKey, knDuplicateId, knNoSuchId, knNoSuchKey, knWrongGateType };
Not all values are used by the APIs in front of all dictionaries. These values have the following meanings:
An attempt was made to insert an entry with a key that already exists in the dictionary.
For dictionaries whose entries have unique integer ids stored in their objects: This value indicates an attempt to add an entry that has an id that matches an existing element of the dictionary. For example; Adding two parameters with the same Id throws this error.
This reason is used after a search by id results in no matching items. Note that other dictionary APIs may indicate without an error that there is no match (e.g. returning a null pointer or an end iterator)
Similar to knNoSuchId this is thrown when a search for an item by name fails to locate a match.
This is not used in SpecTcl. It is intended for use when a gate of an incompatible type for some operation is selected.
CDictionaryException
is essentially an
CException
class whose
ReasonText
and
ReasonCode
interpret the
nReason
code used to construct it as
a member of the enum described above.
The class has as rich set of constructors. For the most part
these match the constructors available for
CException
. The parameters
nReason
should be chosen from the
reason enum described above. The pName
and rName
parameters are names of items
nId
parameters are relevant object Ids.
CFitDictionary
is a specialized dictionary
that holds fits. It also provides an extended observer as
a nested class; CFitDictionary::CObserver
.
The observer base class for fit dictionaries have the following
pure virtual methods.
virtual =0 void Add( CSpectrumFit& fit);
Called when a fit is added to the dictionary. fit
is the object that was added. Note that this object
provides the needed methods to get the name of the
fit as well as the name of the spectrum on which the
fit is defined.
virtual = 0 void Delete( CSpectrumFit& fit);
Called when a fit is deleted (removed from the
dictionary). This is called prior to the actual
removal of the fit
from
the dictionary.
virtual = 0 void Update(( CSpectrumFit& fit);
Called when a fit is updated. Updating a fit means
that its parameters are recomputed based on the current
data in a spectrum. If a
fit
was created and then
additional or new data were acquired, updating the
fit is necessary to make the fit reflect the new
channel values in the region of interest.
This method is called just after the update has been computed. One use is to maintain the display of a fit on a spectrum by a displayer.
Note that the fit dictionary is also a singleton class and therefore has private constructors and destructors.
static CFitDictionary& getInstance();
Returns the singleton instance of this class. If the dictionary has not yet been created, this will create it. If it has, a reference to the existing dictionary is returned.
void add( CSpectrumFit& fit);
Adds a new fit to the dictionary. Note that if the
dictionary already has a fit named the same as
fit
, a
CDictionaryException
is thrown
with the reason
CDictionaryException::knDuplicateKey.
See addOrReplace
below as well.
void addOrReplace( CSpectrumFit& fit);
Adds fit
to the dictionary. If
a fit with that name already exists it is replaced
by this new fit. In that case observer
Delete
methods are called.
void Delete( std::string name);
Delets any fit with the name
name
. If there is no such
fit, CDictionaryException
with the reason
CDictionaryException::knNoSuchkey
is thrown.
iterator begin();
,
iterator end();
These methods support iteration over the container
that holds the fit dictionary.
CFitDictionary::iterator
is an pointer like object that points at
std::pair<std::string, CSpectrumFit*>
objects. The first element of the pair is the name of the
fit while the second is a pointer to the fit object.
begin
returns an iterator that
points to the first element of the dictionary. Incrementing
an iterator results in an interator that points at the next
element of the dictionary. If the iterator points to
the last element of the dictionary, incrementing it
produces the value returned by
end
These iterators are suitable for use in any of the C++ standard library algorithms that require iterators.
size_t size();
Returns the number of elements in the dictionary.
iterator find( std::string name);
Returns an iterator to the dictionary entry
pair with the index name
.
If name
is not found,
the value returned from
end
is returned:
CFitDictionary& fitDict(CFitDictionary::getInstance()); CFitDictionary::iterator p = fitDict->find("foo"); if (p != fitDict.end()) { std::string name = p->first; CSpectrumFit* fit = p->second; // Do something with what was found. } else { j // Item was not found. }
void erase( iterator here);
,
void erase( iterator first, iterator last);
Removes items from the dictionary based on iterators.
here
is an iterator that points to
the item to remove> first
and
last
are iterators that define a
range of items to remove. All items from first
up to but not including last
are removed.
Note that erase
invalidates
the iterator(s) it receives as parameters.
void updateFits( std::string name = std::string("*"));
Recomputes fits with current spectrum data for all
fit names that match the glob pattter
name
. Note that the default
value for this parameter, *,
matches all fits.
Fits are defined on regions of interest in spectra. As spectra accumulate or are cleared and a new data set analyzed, they can be recomputed on the current data. SpecTcl establishes observers that propagate the changes to the fit information to its displayers so that the fitlines displayed on those spectra also automatically update.
void addObserver( CObserver& obs);
,
void removeObserver( CObserver& obs);
These methods manage observers that are monitoring
the fit dictionary. addObserver
adds the observer obs
to end of the
list of observers. removeObserver
removes all instances of ojbs
from
the list of observers maintained by the dictionary.