WvStreams
unilistgen.cc
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 2002 Net Integration Technologies, Inc.
00004  *
00005  * UniListGen is a UniConf generator to allow multiple generators to be
00006  * stacked in a priority sequence for get/set/etc.
00007  * 
00008  */
00009 #include "unilistgen.h"
00010 #include "wvmoniker.h"
00011 #include "wvtclstring.h"
00012 #include "wvstringlist.h"
00013 #include "wvlinkerhack.h"
00014 
00015 WV_LINK(UniListGen);
00016 
00017 
00018 
00019 class UniListGen::IterIter : public UniConfGen::Iter
00020 {
00021 protected:
00022     DeclareWvScatterTable(UniConfKey);
00023     DeclareWvList2(IterList, UniConfGen::Iter);
00024     
00025     IterList l;
00026     IterList::Iter *i;
00027     UniConfKeyTable d;
00028     
00029 public:
00030     IterIter(UniListGen *gen, const UniConfKey &key);
00031     virtual ~IterIter() { delete i; }
00032     
00033     virtual void rewind();
00034     virtual bool next();
00035     virtual UniConfKey key() const;
00036     virtual WvString value() const;
00037 };
00038 
00039 
00040 
00041 static IUniConfGen *creator(WvStringParm s, IObject *_obj)
00042 {
00043     UniConfGenList *l = new UniConfGenList();
00044 
00045     WvStringList gens;
00046     wvtcl_decode(gens, s);
00047     WvStringList::Iter i(gens);
00048 
00049     for (i.rewind(); i.next();)
00050     {
00051         if (_obj) _obj->addRef();
00052         IUniConfGen *gen = wvcreate<IUniConfGen>(i(), _obj);
00053         if (gen)
00054             l->append(gen, true);
00055     }
00056     if (_obj) _obj->release();
00057 
00058     return new UniListGen(l);
00059 }
00060  
00061 static WvMoniker<IUniConfGen> reg("list", creator);
00062 
00063 UniListGen::UniListGen(UniConfGenList *_l) : l(_l)
00064 {
00065     UniConfGenList::Iter i(*l);
00066     for (i.rewind(); i.next(); )
00067         i->add_callback(this, wv::bind(&UniListGen::gencallback, this, _1, _2));
00068 }
00069 
00070 
00071 UniListGen::~UniListGen()
00072 {
00073     UniConfGenList::Iter i(*l);
00074     for (i.rewind(); i.next(); )
00075         i->del_callback(this);
00076     delete l;
00077 }
00078 
00079 
00080 void UniListGen::commit()
00081 {
00082     UniConfGenList::Iter i(*l);
00083     for (i.rewind(); i.next();)
00084         i->commit();
00085 }
00086 
00087 
00088 bool UniListGen::refresh()
00089 {
00090     bool result = true;
00091 
00092     UniConfGenList::Iter i(*l);
00093     for (i.rewind(); i.next();)
00094         result = i->refresh() && result;
00095     return result;
00096 }
00097 
00098 
00099 WvString UniListGen::get(const UniConfKey &key)
00100 {
00101     UniConfGenList::Iter i(*l);
00102     for (i.rewind(); i.next(); )
00103         if (i->exists(key))
00104             return i->get(key);
00105     return WvString::null;
00106 }
00107 
00108 
00109 // we try to set *all* our generators.  Read-only ones will ignore us.
00110 void UniListGen::set(const UniConfKey &key, WvStringParm value)
00111 {
00112     UniConfGenList::Iter i(*l);
00113     for (i.rewind(); i.next(); )
00114         i->set(key, value);
00115 }
00116 
00117 
00118 void UniListGen::setv(const UniConfPairList &pairs)
00119 {
00120     UniConfGenList::Iter i(*l);
00121     for (i.rewind(); i.next(); )
00122         i->setv(pairs);
00123 }
00124 
00125 
00126 bool UniListGen::exists(const UniConfKey &key)
00127 {
00128     UniConfGenList::Iter i(*l);
00129     for (i.rewind(); i.next();)
00130     {
00131         if (i->exists(key))
00132             return true;
00133     }
00134     return false;
00135 }
00136 
00137 
00138 bool UniListGen::haschildren(const UniConfKey &key)
00139 {
00140     UniConfGenList::Iter i(*l);
00141     for (i.rewind(); i.next();)
00142     {
00143         if (i->haschildren(key))
00144             return true;
00145     }
00146     return false;
00147 }
00148 
00149 
00150 bool UniListGen::isok()
00151 {
00152     UniConfGenList::Iter i(*l);
00153     for (i.rewind(); i.next();)
00154     {
00155         if (!i->isok())
00156             return false;
00157     }
00158     return true;
00159 }
00160 
00161 
00162 void UniListGen::gencallback(const UniConfKey &key, WvStringParm value)
00163 {
00164     delta(key, get(key));
00165 }
00166 
00167 
00168 UniConfGen::Iter *UniListGen::iterator(const UniConfKey &key)
00169 {
00170     return new IterIter(this, key);
00171 }
00172 
00173 
00174 /***** UniListGen::IterIter *****/
00175 
00176 UniListGen::IterIter::IterIter(UniListGen *gen, const UniConfKey &key)
00177 {
00178     UniConfGenList::Iter geniter(*gen->l);
00179     for (geniter.rewind(); geniter.next(); )
00180     {
00181         Iter *it = geniter->iterator(key);
00182         if (it)
00183             l.append(it, true);
00184     }
00185 
00186     i = new IterList::Iter(l);
00187 }
00188 
00189 
00190 void UniListGen::IterIter::rewind()
00191 {
00192     for ((*i).rewind(); (*i).next(); )
00193         (*i)->rewind();
00194 
00195     i->rewind();
00196     i->next();
00197 
00198     d.zap();
00199 }
00200 
00201 
00202 bool UniListGen::IterIter::next()
00203 {
00204     if (l.isempty())
00205         return false;
00206 
00207     if ((*i)->next())
00208     {
00209         // When iterating, make sure each key value is only returned once
00210         // (from the top item in the list)
00211         if (!d[(*i)->key()])
00212         {
00213             d.add(new UniConfKey((*i)->key()), true);
00214             return true;
00215         }
00216         else
00217             return next();
00218     }
00219 
00220     if (!i->next())
00221         return false;
00222 
00223     return next();
00224 }
00225 
00226 
00227 UniConfKey UniListGen::IterIter::key() const
00228 {
00229     return (*i)->key();
00230 }
00231 
00232 
00233 WvString UniListGen::IterIter::value() const
00234 {
00235     return (*i)->value();
00236 }
00237 
00238