Menu

ComparableAttributeSet.h

Go to the documentation of this file.
00001 /*******************************************************************************
00002  *
00003  * Copyright (c) 2008-2010 Michael Schulze <mschulze@ivs.cs.uni-magdeburg.de>
00004  *               2009-2010 Michael Kriese <kriese@cs.uni-magdeburg.de>
00005  * All rights reserved.
00006  *
00007  *    Redistribution and use in source and binary forms, with or without
00008  *    modification, are permitted provided that the following conditions
00009  *    are met:
00010  *
00011  *    * Redistributions of source code must retain the above copyright
00012  *      notice, this list of conditions and the following disclaimer.
00013  *
00014  *    * Redistributions in binary form must reproduce the above copyright
00015  *      notice, this list of conditions and the following disclaimer in
00016  *      the documentation and/or other materials provided with the
00017  *      distribution.
00018  *
00019  *    * Neither the name of the copyright holders nor the names of
00020  *      contributors may be used to endorse or promote products derived
00021  *      from this software without specific prior written permission.
00022  *
00023  *
00024  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00025  *    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00026  *    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00027  *    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00028  *    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00029  *    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00030  *    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00031  *    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00032  *    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  *    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  *
00037  * $Id$
00038  *
00039  ******************************************************************************/
00040 #ifndef _ComparableAttributeSet_h_
00041 #define _ComparableAttributeSet_h_
00042 
00043 #include <boost/shared_ptr.hpp>
00044 #include <boost/shared_array.hpp>
00045 #include <boost/noncopyable.hpp>
00046 #include <boost/mpl/list.hpp>
00047 #include <boost/asio/buffer.hpp>
00048 #include "mw/attributes/AttributeSet.h"
00049 #include "mw/attributes/filter/greater_than_or_equal_to.h"
00050 #include "mw/attributes/filter/less_than_or_equal_to.h"
00051 #include "mw/nl/awds/AWDS_Packet.h"
00052 #include "mw/nl/awds/logging.h"
00053 
00054 #include "mw/attributes/access/Attribute_RT.h"
00055 #include "mw/attributes/access/AttributeSet_RT.h"
00056 
00057 namespace famouso {
00058     namespace mw {
00059         namespace nl {
00060             namespace awds {
00061                 namespace detail {
00066                     template< typename Comparator >
00067                     struct op_printer {
00068                             static const char* op() {
00069                                 return (" ? ");
00070                             }
00071                     };
00072                     template< >
00073                     struct op_printer<famouso::mw::attributes::filter::less_than_or_equal_to> {
00074                             static const char* op() {
00075                                 return (" <= ");
00076                             }
00077                     };
00078                     template< >
00079                     struct op_printer<famouso::mw::attributes::filter::greater_than_or_equal_to> {
00080                             static const char* op() {
00081                                 return (" >= ");
00082                             }
00083                     };
00084                 } /* namespace detail */
00085 
00086                 /* \brief A class for holding attributes of publisher, subscriber or network.
00087                  *
00088                  * \tparam AttrSet An AttributesSet containing a list of attributes.
00089                  */
00090                 template< class AttrSet = famouso::mw::attributes::AttributeSet<> >
00091                 class ComparableAttributeSet: boost::noncopyable {
00092 
00093                     public:
00095                         typedef typename AttrSet::sequence AttrSeq;
00096 
00097                     private:
00099                         typedef boost::shared_array<uint8_t> pData;
00100 
00101                         pData data; 
00109                         template< class Seq, class Itr = typename boost::mpl::begin<Seq>::type >
00110                         class AttributeIterator {
00111 
00113                                 typedef typename boost::mpl::deref<Itr>::type attrib;
00114 
00116                                 typedef typename attrib::comparator cmp;
00117 
00119                                 typedef typename boost::mpl::end<Seq>::type end;
00120 
00124                                 static void echo(::logging::loggingReturnType &out, attrib *a) {
00125                                     if (a)
00126                                         out << (intmax_t) a->getValue();
00127                                     else
00128                                         out << "nd";
00129                                 }
00130 
00142                                 static bool match(const attrib *a, const attrib *b) {
00143                                     // if attrib b is empty check is always true
00144                                     if (!b)
00145                                         return true;
00146 
00147                                     // if attrib b is not empty, attrib a has to be not empty too, so check if it matches
00148                                     if (a && cmp::apply_runtime(a->getValue(), b->getValue()))
00149                                         return true;
00150 
00151                                     // attributes doesn't match
00152                                     return false;
00153                                 }
00154 
00155                             public:
00156 
00166                                 static bool match(AttrSet &a, AttrSet &b) {
00167                                     // find attributes
00168                                     attrib *l = a.template find_rt<attrib> ();
00169                                     attrib *r = b.template find_rt<attrib> ();
00170 
00171                                     ::logging::loggingReturnType &out = log::emit<ATTR>();
00172 
00173                                     out << "matching " << (int) attrib::id << ": ";
00174                                     echo(out, l);
00175                                     out << detail::op_printer<cmp>::op();
00176                                     echo(out, r);
00177                                     out << log::endl;
00178 
00179                                     // match attribute
00180                                     if (!match(l, r)) {
00181                                         log::emit<ATTR>() << "unsuccessfull" << log::endl;
00182                                         return false; // if attribs not match
00183                                     }
00184 
00185                                     // Check the next attribute in list
00186                                     return AttributeIterator<Seq, typename boost::mpl::next<Itr>::type>::match(a, b);
00187                                 }
00188 
00195                                 static void print(::logging::loggingReturnType &out, AttrSet &a) {
00196                                     // find the attribute
00197                                     attrib *attr = a.template find_rt<attrib> ();
00198                                     if (attr) {
00199                                         // found, so print name and value
00200                                         out << " [" << (int) attrib::id << "]={" << (intmax_t) attr->getValue() << "}";
00201                                     }
00202 
00203                                     // print next attribute in list
00204                                     AttributeIterator<Seq, typename boost::mpl::next<Itr>::type>::print(out, a);
00205                                 }
00206                         };
00207 
00213                         template< class Seq >
00214                         class AttributeIterator<Seq, typename boost::mpl::end<Seq>::type> {
00215                             public:
00216 
00217                                 static bool match(const AttrSet &a, const AttrSet &b) {
00218                                     log::emit<ATTR>() << "successfull" << log::endl;
00219                                     return true;
00220                                 }
00221 
00222                                 static void print(::logging::loggingReturnType &out, const AttrSet &a) {
00223                                 }
00224                         };
00225 
00226                         /* \brief Copy the data to this instance.
00227                          *
00228                          * \param d the data pointer
00229                          * \param s the size of the data
00230                          */
00231                         void set(uint8_t *d, uint16_t s) {
00232                             static uint8_t p[1] = { 0 };
00233 
00234                             if (s <= 0) {
00235                                 s = 1;
00236                                 d = p;
00237                             }
00238                             data = pData(new uint8_t[s]);
00239                             std::memcpy(data.get(), d, s);
00240 
00241                         }
00242 
00247                         static uint16_t size(uint8_t* data) {
00248 
00249                             if (!data) // just to be a little secure.
00250                                 return 0;
00251 
00252                             typedef famouso::mw::attributes::access::AttributeSet_RT *AS;
00253 
00254                             const AS set_rt = reinterpret_cast<const AS> (&data[0]);
00255 
00256                             return set_rt->length();
00257                         }
00258 
00264                         ComparableAttributeSet() {
00265                             set(NULL, 0);
00266                         }
00267 
00272                         AttrSet &getSet() {
00273                             return *reinterpret_cast<AttrSet*> (data.get());
00274                         }
00275 
00276                     public:
00278                         typedef boost::shared_ptr<ComparableAttributeSet> type;
00279 
00285                         void set(awds::AWDS_Packet &p) {
00286                             // if this is not an attributes packet
00287                             if (p.header.type != AWDS_Packet::constants::packet_type::attributes)
00288                                 return;
00289 
00290                             set(p.data, size(p.data));
00291                         }
00292 
00304                         static bool match(const type & a, const type & b) {
00305                             return AttributeIterator<AttrSeq>::match(a->getSet(), b->getSet());
00306                         }
00307 
00312                         void print(::logging::loggingReturnType &out) {
00313                             out << ::logging::log::dec;
00314                             AttributeIterator<AttrSeq>::print(out, getSet());
00315                         }
00316 
00321                         type clone() {
00322                             type res = create(getSet());
00323                             return res;
00324                         }
00325 
00331                         template< class Attrib >
00332                         Attrib *find() {
00333                             return getSet().template find_rt<Attrib> ();
00334                         }
00335 
00340                         operator boost::asio::const_buffer() {
00341                             uint8_t *d = data.get();
00342                             return boost::asio::buffer(d, size(d));
00343                         }
00344 
00345 
00350                         uint16_t size(){
00351                             return size(data.get());
00352                         }
00353 
00358                         static type create() {
00359                             type res = type(new ComparableAttributeSet());
00360                             return res;
00361                         }
00362 
00368                         static type create(AWDS_Packet &p) {
00369                             type res = create();
00370                             res->set(p);
00371                             return res;
00372                         }
00373 
00382                         template< class AttrSeq2 >
00383                         static type create(famouso::mw::attributes::AttributeSet<AttrSeq2> &p) {
00384                             type res = create();
00385                             uint8_t *d = reinterpret_cast<uint8_t*> (&p);
00386                             res->set(d, size(d));
00387                             return res;
00388                         }
00389 
00397                         static type create(uint8_t *d) {
00398                             type res = create();
00399                             if (d)
00400                                 res->set(d, size(d));
00401                             return res;
00402                         }
00403                 };
00404 
00405             } /* namespace awds */
00406         } /* namespace nl */
00407     } /* namespace mw */
00408 } /* namespace famouso */
00409 
00410 namespace logging {
00411     using famouso::mw::nl::awds::ComparableAttributeSet;
00412 
00421     template< class AttrSeq >
00422     inline ::logging::loggingReturnType &operator<<(loggingReturnType &out, const boost::shared_ptr<ComparableAttributeSet<AttrSeq> > &att) {
00423         att->print(out);
00424         return out;
00425     }
00426 
00427 } /* namespace logging */
00428 #endif /* _ComparableAttributeSet_ */