Siena Simplification Library Documentation (v. 1.1.4)

ssimp_types.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 //  This file is part of Siena, a wide-area event notification system.
00004 //  See http://www.cs.colorado.edu/serl/siena/
00005 //
00006 //  Authors: See the file AUTHORS for full details.
00007 //
00008 //  Copyright (C) 2002-2004 University of Colorado
00009 //
00010 //  This program is free software; you can redistribute it and/or
00011 //  modify it under the terms of the GNU General Public License
00012 //  as published by the Free Software Foundation; either version 2
00013 //  of the License, or (at your option) any later version.
00014 //
00015 //  This program is distributed in the hope that it will be useful,
00016 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 //  GNU General Public License for more details.
00019 //
00020 //  You should have received a copy of the GNU General Public License
00021 //  along with this program; if not, write to the Free Software
00022 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
00023 //  USA, or send email to [email protected].
00024 //
00025 // $Id: ssimp_types.h,v 1.8 2006/05/05 13:53:47 carzanig Exp $
00026 //
00027 #ifndef SIMP_TYPES_H
00028 #define SIMP_TYPES_H
00029 
00030 #include <map>
00031 #include <set>
00032 #include <sstream>
00033 #include <string>
00034 #include "siena/simplify.h"
00035 
00046 class Constraint : public siena::constraint
00047 {
00048   class Value
00049   {
00050   public:
00051     Value( bool b )
00052       : m_type( siena::bool_id ), m_bool( b ),
00053         m_bytesize( sizeof( siena::type_id ) + sizeof( bool ) ) {}
00054 
00055     Value( double d )
00056       : m_type( siena::double_id ), m_double( d ),
00057         m_bytesize( sizeof( siena::type_id ) + sizeof( double ) ) {}
00058 
00059     Value( int i )
00060       : m_type( siena::int_id ), m_int( i ),
00061         m_bytesize( sizeof( siena::type_id ) + sizeof( int ) ) {}
00062 
00063     Value( const std::string& s )
00064       : m_type( siena::string_id ), m_string( s ),
00065         m_bytesize( sizeof( siena::type_id ) + s.length() ) {}
00066 
00067     Value()
00068       : m_type( siena::anytype_id ), m_int( 0 ),
00069         m_bytesize( sizeof( siena::type_id ) ) {}
00070 
00071     Value( const Value& v )
00072     {
00073       m_type = v.m_type;
00074       switch( m_type )
00075         {
00076         case siena::bool_id: m_bool = v.m_bool; break;
00077         case siena::double_id: m_double = v.m_double; break;
00078         case siena::anytype_id:
00079         case siena::int_id: m_int = v.m_int; break;
00080         default: m_string = v.m_string;
00081         }
00082       m_bytesize = v.m_bytesize;
00083     }
00084 
00085     const Value& operator= ( const Value& v )
00086     {
00087       m_type = v.m_type;
00088       switch( m_type )
00089         {
00090         case siena::bool_id: m_bool = v.m_bool; break;
00091         case siena::double_id: m_double = v.m_double; break;
00092         case siena::anytype_id:
00093         case siena::int_id: m_int = v.m_int; break;
00094         default: m_string = v.m_string;
00095         }
00096       m_bytesize = v.m_bytesize;
00097       return (*this);
00098     }
00099 
00100     bool operator== ( const Value& v ) const
00101     {
00102       if( m_type != v.m_type ) { return false; }
00103       switch( m_type )
00104         {
00105         case siena::bool_id: return m_bool == v.m_bool;
00106         case siena::double_id: return m_double == v.m_double;
00107         case siena::int_id: return m_int == v.m_int;
00108         case siena::anytype_id: return true;
00109         default: return m_string == v.m_string;
00110         }
00111     }
00112 
00113     bool operator< ( const Value& v ) const
00114     {
00115       if( m_type != v.m_type ) { return m_type < v.m_type; }
00116       switch( m_type )
00117         {
00118         case siena::bool_id: return m_bool < v.m_bool;
00119         case siena::double_id: return m_double < v.m_double;
00120         case siena::int_id: return m_int < v.m_int;
00121         case siena::anytype_id: return false;
00122         default: return m_string < v.m_string;
00123         }
00124     }
00125 
00126     bool operator> ( const Value& v ) const
00127     {
00128       if( m_type != v.m_type ) { return m_type > v.m_type; }
00129       switch( m_type )
00130         {
00131         case siena::bool_id: return m_bool > v.m_bool;
00132         case siena::double_id: return m_double > v.m_double;
00133         case siena::int_id: return m_int > v.m_int;
00134         case siena::anytype_id: return false;
00135         default: return m_string > v.m_string;
00136         }
00137     }
00138 
00139     bool operator<= ( const Value& v ) const
00140     {
00141       if( m_type != v.m_type ) { return m_type <= v.m_type; }
00142       switch( m_type )
00143         {
00144         case siena::bool_id: return m_bool <= v.m_bool;
00145         case siena::double_id: return m_double <= v.m_double;
00146         case siena::int_id: return m_int <= v.m_int;
00147         case siena::anytype_id: return true;
00148         default: return m_string <= v.m_string;
00149         }
00150     }
00151 
00152     bool operator>= ( const Value& v ) const
00153     {
00154       if( m_type != v.m_type ) { return m_type >= v.m_type; }
00155       switch( m_type )
00156         {
00157         case siena::bool_id: return m_bool >= v.m_bool;
00158         case siena::double_id: return m_double >= v.m_double;
00159         case siena::int_id: return m_int >= v.m_int;
00160         case siena::anytype_id: return true;
00161         default: return m_string >= v.m_string;
00162         }
00163     }
00164 
00165     bool operator!= ( const Value& v ) const
00166     {
00167       if( m_type != v.m_type ) { return true; }
00168       switch( m_type )
00169         {
00170         case siena::bool_id: return m_bool != v.m_bool;
00171         case siena::double_id: return m_double != v.m_double;
00172         case siena::int_id: return m_int != v.m_int;
00173         case siena::anytype_id: return false;
00174         default: return m_string != v.m_string;
00175         }
00176     }
00177 
00178     size_t bytesize() const { return m_bytesize; }
00179 
00180     siena::type_id m_type;
00181     union
00182     {
00183       bool m_bool;
00184       double m_double;
00185       int m_int;
00186     };
00187     std::string m_string;
00188     size_t m_bytesize;
00189   };
00190 
00191 public:
00195   Constraint( const std::string& name, siena::operator_id op, siena::bool_t b )
00196     : m_name( name ), m_op( op ), m_value( b ),
00197       m_bytesize( name.length() + sizeof( siena::operator_id ) + m_value.bytesize() ) {}
00198 
00202   Constraint( const std::string& name, siena::operator_id op, siena::double_t d )
00203     : m_name( name ), m_op( op ), m_value( d ),
00204       m_bytesize( name.length() + sizeof( siena::operator_id ) + m_value.bytesize() ) {}
00205 
00209   Constraint( const std::string& name, siena::operator_id op, siena::int_t i )
00210     : m_name( name ), m_op( op ), m_value( (int)i ),
00211       m_bytesize( name.length() + sizeof( siena::operator_id ) + m_value.bytesize() ) {}
00212 
00216   Constraint( const std::string& name, siena::operator_id op, const std::string& s )
00217     : m_name( name ), m_op( op ), m_value( s ),
00218       m_bytesize( name.length() + sizeof( siena::operator_id ) + m_value.bytesize() ) {}
00219 
00222   Constraint( const std::string& name )
00223     : m_name( name ), m_op(siena::any_id), m_value(),
00224       m_bytesize( name.length() + sizeof( siena::operator_id ) ) {}
00225 
00228   Constraint( const Constraint& c )
00229     : m_name( c.m_name ), m_op( c.m_op ), m_value( c.m_value ),
00230       m_bytesize( c.m_bytesize ) {}
00231 
00234   const Constraint& operator=( const Constraint& c )
00235   {
00236     m_name = c.m_name; m_op = c.m_op;
00237     m_value = c.m_value; m_bytesize = c.m_bytesize;
00238     return *this;
00239   }
00240 
00246   bool operator==( const Constraint& c ) const
00247   { return m_name == c.m_name && m_op == c.m_op && m_value == c.m_value; }
00248 
00254   bool operator<( const Constraint& c ) const
00255   {
00256     if( m_name != c.m_name ) { return m_name < c.m_name; }
00257     else if( m_op != c.m_op ) { return m_op < c.m_op; }
00258     else { return m_value < c.m_value; }
00259   }
00260 
00261   ~Constraint() {}
00262 
00268   siena::bool_t bool_value() const
00269   { return m_value.m_bool; }
00270 
00276   siena::double_t double_value() const
00277   { return m_value.m_double; }
00278 
00285   size_t bytesize() const
00286   { return m_bytesize; }
00287 
00293   siena::int_t int_value() const
00294   { return m_value.m_int; }
00295 
00298   siena::string_t name() const
00299   { return siena::string_t( m_name.c_str(), m_name.length() ); }
00300 
00303   siena::operator_id op() const
00304   { return m_op; }
00305 
00309   std::ostream& sff(std::ostream& out) const;
00310 
00314   std::string str() const;
00315 
00321   siena::string_t string_value() const
00322   { return siena::string_t( m_value.m_string.c_str(), m_value.m_string.length() ); }
00323 
00326   siena::type_id type() const
00327   { return m_value.m_type; }
00328 
00329 private:
00330   std::string           m_name;
00331   siena::operator_id    m_op;
00332   Value                 m_value;
00333   size_t                m_bytesize;
00334 };
00335 
00336 inline std::ostream& operator<< ( std::ostream& out, const Constraint& c )
00337 { return out << c.str(); }
00338 
00343 template<bool Simplify> class TFilter : public siena::filter
00344 {
00345 public:
00348   class Iterator : public siena::filter::iterator
00349   {
00350   public:
00351     Iterator( std::set<Constraint>::iterator begin, std::set<Constraint>::iterator end )
00352       : m_end( end ), m_index( begin ) {}
00353 
00354     ~Iterator() {}
00355 
00356     siena::bool_t bool_value() const
00357     { return (*m_index).bool_value(); }
00358 
00359     siena::double_t double_value() const
00360     { return (*m_index).double_value(); }
00361 
00362     siena::int_t int_value() const
00363     { return (*m_index).int_value(); }
00364 
00365     siena::string_t name() const
00366     { return (*m_index).name(); }
00367 
00368     bool next()
00369     {
00370       if( m_index == m_end || ++m_index == m_end ) { return false; }
00371       else { return true; }
00372     }
00373 
00374     siena::operator_id op() const
00375     { return (*m_index).op(); }
00376 
00377     std::ostream& sff(std::ostream& out) const;
00378 
00379     std::string str() const
00380     { return (*m_index).str(); }
00381 
00382     siena::string_t string_value() const
00383     { return (*m_index).string_value(); }
00384 
00385     siena::type_id type() const
00386     { return (*m_index).type(); }
00387 
00388   private:
00389     std::set<Constraint>::iterator m_end;
00390     std::set<Constraint>::iterator m_index;
00391   };
00392 
00393   TFilter()
00394     : m_conflicted( false ), m_bytesize( 0 ) {}
00395 
00396   ~TFilter() {}
00397 
00398   TFilter( const TFilter& f )
00399     : m_conflicted( f.m_conflicted ), m_constraints( f.m_constraints ),
00400       m_bytesize( f.m_bytesize ) {}
00401 
00402   const TFilter& operator=( const TFilter& f )
00403   {
00404     m_conflicted = f.m_conflicted;
00405     m_constraints = f.m_constraints;
00406     m_bytesize = f.m_bytesize;
00407     return (*this);
00408   }
00409 
00410   bool operator<( const TFilter& f ) const
00411   { 
00412     /*
00413      * not sure that the extra test with the size is necessary...
00414      */
00415     if( m_constraints.size() != f.m_constraints.size() )
00416       { return m_constraints.size() < f.m_constraints.size(); }
00417     return m_constraints < f.m_constraints;
00418   }
00419 
00420   bool operator== ( const TFilter& f ) const
00421   { return m_constraints == f.m_constraints; }
00422 
00423   void add( const Constraint& c )
00424   {
00425     if( Simplify )
00426       {
00427         // once a filter is conflicted there is no point in adding
00428         // constraints to it.
00429         if( m_conflicted )
00430           {
00431             return;
00432           }
00433         std::set<Constraint>::iterator i = m_constraints.begin(); 
00434         while ( i != m_constraints.end() )
00435           {
00436             if( conflicting( (*i), c ) )
00437               {
00438                 m_conflicted = true;
00439                 m_constraints.clear();
00440                 m_bytesize = 0;
00441                 return;
00442               }
00443             if( siena::covers( c, (*i) ) )
00444               {
00445                 return;
00446               }
00447             if( siena::covers( (*i), c ) )
00448               {
00449                 m_bytesize -= (*i).bytesize();
00450                 m_constraints.erase( i++ );
00451               }
00452             else 
00453               {
00454                 ++i;
00455               }
00456           }
00457       }
00458     if( m_constraints.insert( c ).second )
00459       {
00460         m_bytesize += c.bytesize();
00461       }
00462   }
00463 
00464   Iterator* first() const
00465   {
00466     if( m_constraints.empty() )  { return NULL; }
00467     return new Iterator( m_constraints.begin(), m_constraints.end() );
00468   }
00469 
00470   const std::set<Constraint>& getConstraints() const
00471   { return m_constraints; }
00472 
00473   size_t bytesize() const { return m_bytesize; }
00474 
00475   std::ostream& sff(std::ostream& out) const
00476   {
00477     std::set<Constraint>::const_iterator i;
00478     for( i = m_constraints.begin(); i != m_constraints.end(); ++i )
00479       {
00480         if( i != m_constraints.begin() )
00481           {
00482             out <<  ", ";
00483           }
00484         (*i).sff(out);
00485       }
00486     return out;
00487   }
00488 
00489   int size() const { return m_constraints.size(); }
00490 
00491   std::string str() const
00492   {
00493     std::ostringstream oss;
00494     oss << "[Filter: constraints={";
00495     std::set<Constraint>::const_iterator i;
00496     for( i = m_constraints.begin(); i != m_constraints.end(); ++i )
00497       {
00498         if( i != m_constraints.begin() )
00499           {
00500             oss <<  ",";
00501           }
00502         oss <<  (*i).str();
00503       }
00504     oss << "}]";
00505     return oss.str();
00506   }
00507 
00508 private:
00509   bool                  m_conflicted;
00510   std::set<Constraint>  m_constraints;
00511   size_t                m_bytesize;
00512 };
00513 
00514 template<bool Simplify> inline std::ostream& operator<<( std::ostream& out, const TFilter<Simplify>& f )
00515 { return out << f.str(); }
00516 
00519 typedef TFilter<false> BasicFilter;
00522 typedef TFilter<true> SimplifyingFilter;
00523 
00528 template<bool Simplify> class TPredicate : public siena::predicate
00529 {
00530 public:
00531   typedef TFilter<Simplify> filter_type;
00532   typedef typename filter_type::Iterator filter_iterator;
00533   typedef typename std::set<filter_type>::iterator filter_set_iterator;
00534   typedef typename std::set<filter_type>::const_iterator const_filter_set_iterator;
00535 
00538   class Iterator : public siena::predicate::iterator
00539   {
00540   public:
00541     Iterator( filter_set_iterator begin, filter_set_iterator end )
00542       : m_end( end ), m_index( begin ) {}
00543 
00544     filter_iterator* first() const
00545     { return (*m_index).first(); }
00546 
00547     ~Iterator() {}
00548 
00549     bool next()
00550     {
00551       if( m_index == m_end || ++m_index == m_end ) { return false; }
00552       else { return true; }
00553     }
00554 
00555     std::string str() const
00556     { return (*m_index).str(); }
00557 
00558   private:
00559     filter_set_iterator m_end;
00560     filter_set_iterator m_index;
00561   };
00562 
00563   TPredicate() : m_bytesize( 0 ) {}
00564 
00565   TPredicate( const TPredicate& p )
00566     : m_filters( p.m_filters ), m_bytesize( p.m_bytesize ) {}
00567 
00568   ~TPredicate() {}
00569 
00570   const TPredicate& operator= ( const TPredicate& p )
00571   {
00572     m_filters = p.m_filters;
00573     m_bytesize = p.m_bytesize;
00574     return *this;
00575   }
00576 
00577   bool operator== ( const TPredicate& p ) const
00578   { return m_filters == p.m_filters; }
00579 
00580   void add( const TPredicate& p );
00581 
00582   void add( const filter_type& f );
00583 
00584   void clear()
00585   { m_bytesize = 0; m_filters.clear(); }
00586 
00587   Iterator* first() const
00588   {
00589     if( m_filters.empty() ) { return NULL; }
00590     return new Iterator( m_filters.begin(), m_filters.end() );
00591   }
00592 
00593   size_t bytesize() const
00594   { return m_bytesize; }
00595 
00596   const std::set<filter_type>& getFilters() const
00597   { return m_filters; }
00598 
00599   std::ostream& sff(std::ostream& out) const;
00600 
00601   int size()  const
00602   { return m_filters.size(); }
00603 
00604   std::string str() const;
00605 private:
00606   std::set<filter_type> m_filters;
00607   size_t                m_bytesize;
00608 };
00609 
00610 template<bool Simplify> inline void TPredicate<Simplify> :: add( const TPredicate<Simplify>& p )
00611 {
00612   const_filter_set_iterator i;
00613   for( i = p.m_filters.begin(); i != p.m_filters.end(); ++i )
00614     {
00615       add( *i );
00616     }
00617 }
00618 
00619 template<bool Simplify> inline void TPredicate<Simplify> :: add( const TPredicate<Simplify>::filter_type& f )
00620 {
00621   if( Simplify )
00622     {
00623       // no point in adding empty filters
00624       if( ! f.size() )
00625         {
00626           return;
00627         }
00628       filter_set_iterator i = m_filters.begin();
00629       while ( i != m_filters.end() )
00630         {
00631           if( siena::covers( (*i), f ) )
00632             {
00633               return;
00634             }
00635           if( siena::covers( f, (*i) ) )
00636             {
00637               m_bytesize -= (*i).bytesize();
00638               m_filters.erase( i++ );
00639             }
00640           else
00641             {
00642               ++i;
00643             }
00644         }
00645     }
00646   if( m_filters.insert( f ).second )
00647     {
00648       m_bytesize += f.bytesize();
00649     }
00650 }
00651 
00652 template<bool Simplify> inline std::ostream& TPredicate<Simplify> :: sff(std::ostream& out) const
00653 {
00654   const_filter_set_iterator i;
00655   for( i = m_filters.begin(); i != m_filters.end(); ++i )
00656     {
00657       if( i != m_filters.begin() )
00658         {
00659           out << std::endl << " | ";
00660         }
00661       (*i).sff(out);
00662     }
00663   return out;
00664 }
00665 
00666 template<bool Simplify> inline std::string TPredicate<Simplify> :: str() const
00667 {
00668   std::ostringstream oss;
00669   oss << "[Predicate: bytesize=" << m_bytesize << ",filters={";
00670   const_filter_set_iterator i;
00671   for( i = m_filters.begin(); i != m_filters.end(); ++i )
00672     {
00673       if( i != m_filters.begin() )
00674         {
00675           oss <<  ",";
00676         }
00677       oss <<  (*i).str();
00678     }
00679   oss << "}]";
00680   return oss.str();
00681 }
00682 
00683 template<bool Simplify> inline std::ostream& operator<<( std::ostream& out, const TPredicate<Simplify>& p )
00684 { return out << p.str(); }
00685 
00688 typedef TPredicate<false> BasicPredicate;
00689 
00692 typedef TPredicate<true> SimplifyingPredicate;
00693 
00696 class Message : public siena::message
00697 {
00698 public:
00701   class Value
00702   {
00703   public:
00704     Value(bool b) : type(siena::bool_id), b_value(b) { }
00705     Value(double d) : type(siena::double_id), d_value(d) { }
00706     Value(int i) : type(siena::int_id), i_value(i) { }
00707     Value(std::string s) : type(siena::string_id), s_value(s) { }
00708 
00709     Value( const Value& v )
00710     {
00711       type = v.type;
00712       switch( v.type )
00713         {
00714         case siena::bool_id: b_value = v.b_value; break;
00715         case siena::double_id: d_value = v.d_value; break;
00716         case siena::int_id: i_value = v.i_value; break;
00717         default: s_value = v.s_value;
00718         }
00719     }
00720 
00721     const Value& operator= ( const Value& v )
00722     {
00723       type = v.type;
00724       switch( v.type )
00725         {
00726         case siena::bool_id: b_value = v.b_value; break;
00727         case siena::double_id: d_value = v.d_value; break;
00728         case siena::int_id: i_value = v.i_value; break;
00729         default: s_value = v.s_value;
00730         }
00731       return *this;
00732     }
00733 
00734     size_t bytesize() const;
00735 
00736     std::string str() const;
00737 
00738     siena::type_id type;
00739     union
00740     {
00741       bool b_value;
00742       double d_value;
00743       int i_value;
00744     };
00745     std::string s_value;
00746   };
00747 
00751   class Iterator : public siena::message::iterator
00752   {
00753     std::map<std::string,Value>::const_iterator m_itr;
00754     std::map<std::string,Value>::const_iterator m_end;
00755   public:
00756     Iterator( std::map<std::string,Value>::const_iterator itr,
00757               std::map<std::string,Value>::const_iterator end )
00758       : m_itr( itr ), m_end( end ) {}
00759     
00760     ~Iterator() {}
00761 
00762     siena::bool_t bool_value() const
00763     {
00764       if( (*m_itr).second.type != siena::bool_id ) { return false; }
00765       return (*m_itr).second.b_value;
00766     }
00767 
00768     siena::double_t double_value() const
00769     {
00770       if( (*m_itr).second.type != siena::double_id ) { return 0.0; }
00771       return (*m_itr).second.d_value;
00772     }
00773 
00774     siena::int_t int_value() const
00775     {
00776       if( (*m_itr).second.type != siena::int_id ) { return 0; }
00777       return (*m_itr).second.i_value;
00778     }
00779 
00780     siena::string_t string_value() const
00781     {
00782       return siena::string_t( (*m_itr).second.s_value.c_str(), 
00783                               (*m_itr).second.s_value.length() );
00784     }
00785 
00786     siena::type_id type() const
00787     { return (*m_itr).second.type; }
00788 
00789     siena::string_t name() const
00790     { return siena::string_t( (*m_itr).first.c_str(), (*m_itr).first.length() ); }
00791 
00792     bool next()
00793     {
00794       if( m_itr == m_end )
00795         {
00796           return false;
00797         }
00798       return ++m_itr != m_end;
00799     }
00800   };
00801 
00804   Message() {}
00805 
00808   Message( const Message& m ) : m_attrMap( m.m_attrMap ) {}
00809 
00810   ~Message() {}
00811 
00814   const Message& operator= ( const Message& m )
00815   { m_attrMap = m.m_attrMap; return (*this); }
00816 
00820   void add( const std::string& name, bool val )
00821   {
00822     m_attrMap.insert(make_pair(name, Value(val)));
00823   }
00824 
00828   void add( const std::string& name, double val )
00829   {
00830     m_attrMap.insert(make_pair(name, Value(val)));
00831   }
00832 
00836   void add( const std::string& name, int val )
00837   {
00838     m_attrMap.insert(make_pair(name, Value(val)));
00839   }
00840     
00844   void add( const std::string& name, const std::string& val )
00845   {
00846     m_attrMap.insert(make_pair(name, Value(val)));
00847   }
00848 
00852   bool contains( const siena::string_t& name ) const
00853   { return m_attrMap.find( std::string( name.begin, name.length() ) ) != m_attrMap.end(); }
00854 
00858   siena::message::iterator* first() const
00859   {
00860     if( m_attrMap.size() == 0 ) { return NULL; }
00861     return new Message::Iterator( m_attrMap.begin(), m_attrMap.end() );
00862   }
00863 
00869   siena::attribute* find( const siena::string_t& name ) const
00870   {
00871     std::map<std::string,Value>::const_iterator itr = m_attrMap.find( std::string( name.begin, name.length() ) );
00872     if( itr != m_attrMap.end() )
00873       {
00874         return new Message::Iterator( itr, m_attrMap.end() );
00875       }
00876     else
00877       {
00878         return NULL;
00879       }
00880   }
00881 
00884   const std::map<std::string,Value>& getAttributes() const
00885   { return m_attrMap; }
00886 
00889   size_t bytesize() const;
00890 
00893   int size() const
00894   { return m_attrMap.size(); }
00895 
00900   std::string str() const;
00901 private:
00902   std::map<std::string,Value> m_attrMap;
00903 };
00904 
00905 inline std::ostream& operator<< ( std::ostream& out, const Message& m )
00906 { return out << m.str(); }
00907 
00908 #endif // SIMP_TYPES_H