00001 #ifndef TAGCOLL_ITEM_GROUPER_H
00002 #define TAGCOLL_ITEM_GROUPER_H
00003
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <tagcoll/Collection.h>
00027 #include <tagcoll/OpSet.h>
00028
00029 #include <map>
00030 #include <list>
00031
00032 namespace Tagcoll
00033 {
00034
00067 template<class ITEM, class TAG>
00068 class ItemGrouper : public Collection<ITEM, TAG>
00069 {
00070 protected:
00071 typedef typename std::map<OpSet<TAG>, OpSet<ITEM> > groups_t;
00072
00073
00074 groups_t groups;
00075
00076 virtual void consumeItem(const ITEM& item, const OpSet<TAG>& tags)
00077 {
00078 groups[tags] += item;
00079 }
00080 virtual void consumeItems(const OpSet<ITEM>& items, const OpSet<TAG>& tags)
00081 {
00082 groups[tags] += items;
00083 }
00084
00085 virtual OpSet<ITEM> getItemsHavingTag(const TAG& tag) const
00086 {
00087 OpSet<ITEM> res;
00088 for (typename groups_t::const_iterator i = groups.begin();
00089 i != groups.end(); i++)
00090 if (i->first.contains(tag))
00091 res += i->second;
00092 return res;
00093 }
00094 virtual OpSet<ITEM> getItemsHavingTags(const OpSet<TAG>& tags) const
00095 {
00096 OpSet<ITEM> res;
00097 for (typename groups_t::const_iterator i = groups.begin();
00098 i != groups.end(); i++)
00099 if (i->first.contains(tags))
00100 res += i->second;
00101 return res;
00102 }
00103
00104 virtual OpSet<TAG> getTagsOfItem(const ITEM& item) const
00105 {
00106 for (typename groups_t::const_iterator i = groups.begin();
00107 i != groups.end(); i++)
00108 if (i->second.contains(item))
00109 return i->first;
00110 return OpSet<TAG>();
00111 }
00112 virtual OpSet<TAG> getTagsOfItems(const OpSet<ITEM>& items) const
00113 {
00114 OpSet<TAG> res;
00115 for (typename groups_t::const_iterator i = groups.begin();
00116 i != groups.end(); i++)
00117 {
00118 OpSet<ITEM> found = i->second ^ items;
00119 if (!found.empty())
00120 res += i->first;
00121 }
00122 return res;
00123 }
00124
00125
00126 public:
00127 virtual ~ItemGrouper() throw () {}
00128
00129 virtual bool hasItem(const ITEM& item) const
00130 {
00131 for (typename groups_t::const_iterator i = groups.begin();
00132 i != groups.end(); i++)
00133 if (i->second.contains(item))
00134 return true;
00135 return false;
00136 }
00137 virtual bool hasTag(const TAG& tag) const
00138 {
00139 for (typename groups_t::const_iterator i = groups.begin();
00140 i != groups.end(); i++)
00141 if (i->first.contains(tag))
00142 return true;
00143 return false;
00144 }
00145
00146 virtual void applyChange(const PatchList<ITEM, TAG>& change)
00147 {
00148 OpSet<ITEM> involvedItems;
00149
00150
00151 for (typename PatchList<ITEM, TAG>::const_iterator i = change.begin(); i != change.end(); i++)
00152 involvedItems += i->first;
00153
00154
00155
00156 std::map< ITEM, OpSet<TAG> > involved;
00157 OpSet<ITEM> extraItems = involvedItems;
00158 std::list< typename groups_t::iterator > toremove;
00159 for (typename groups_t::iterator i = groups.begin();
00160 i != groups.end(); i++)
00161 {
00162 OpSet<ITEM> found = i->second ^ involvedItems;
00163 extraItems -= found;
00164 if (!found.empty())
00165 {
00166 i->second -= found;
00167 for (typename OpSet<ITEM>::const_iterator j = found.begin();
00168 j != found.end(); j++)
00169 involved.insert(make_pair(*j, change.patch(*j, i->first)));
00170 if (i->second.empty())
00171 toremove.push_back(i);
00172 }
00173 }
00174 for (typename std::list< typename groups_t::iterator >::const_iterator i = toremove.begin();
00175 i != toremove.end(); i++)
00176 groups.erase(*i);
00177
00178
00179 for (typename OpSet<ITEM>::const_iterator i = extraItems.begin();
00180 i != extraItems.end(); i++)
00181 {
00182 typename PatchList<ITEM, TAG>::const_iterator found = change.find(*i);
00183 if (found != change.end())
00184 involved.insert(make_pair(*i, found->second.getAdded()));
00185 }
00186
00187
00188 for (typename std::map< ITEM, OpSet<TAG> >::const_iterator i = involved.begin();
00189 i != involved.end(); i++)
00190 groups[i->second] += i->first;
00191 }
00192
00193
00194 virtual OpSet<ITEM> getTaggedItems() const
00195 {
00196 OpSet<ITEM> res;
00197 for (typename groups_t::const_iterator i = groups.begin();
00198 i != groups.end(); i++)
00199 res += i->second;
00200 return res;
00201 }
00202
00203 virtual OpSet<TAG> getAllTags() const
00204 {
00205 OpSet<TAG> res;
00206 for (typename groups_t::const_iterator i = groups.begin();
00207 i != groups.end(); i++)
00208 res += i->first;
00209 return res;
00210 }
00211
00212 virtual OpSet<TAG> getCompanionTags(const OpSet<TAG>& tags) const
00213 {
00214 OpSet<TAG> res;
00215 for (typename groups_t::const_iterator i = groups.begin();
00216 i != groups.end(); i++)
00217 if (i->first.contains(tags))
00218 res += i->first;
00219 return res - tags;
00220 }
00221
00222 virtual OpSet<ITEM> getRelatedItems(const OpSet<TAG>& tags, int maxdistance = 1) const
00223 {
00224 OpSet<ITEM> packages;
00225
00226 for (typename groups_t::const_iterator i = groups.begin();
00227 i != groups.end(); i++)
00228 {
00229 int dist = tags.distance(i->first);
00230 if (dist >= 0 && dist <= maxdistance)
00231 packages += i->second;
00232 }
00233
00234 return packages;
00235 }
00236
00237 virtual void output(Consumer<ITEM, TAG>& consumer) const
00238 {
00239 for (typename groups_t::const_iterator i = groups.begin();
00240 i != groups.end(); i++)
00241 if (i->first.empty())
00242 consumer.consume(i->second);
00243 else
00244 consumer.consume(i->second, i->first);
00245 }
00246
00251 void outputReversed(Consumer<TAG, ITEM>& consumer) const
00252 {
00253 for (typename groups_t::const_iterator i = groups.begin();
00254 i != groups.end(); i++)
00255 consumer.consume(i->first, i->second);
00256 }
00257
00258 virtual void outputHavingTags(const OpSet<TAG>& tags, Consumer<ITEM, TAG>& consumer) const
00259 {
00260 for (typename groups_t::const_iterator i = groups.begin();
00261 i != groups.end(); i++)
00262 if (i->first.contains(tags))
00263 consumer.consume(i->second, i->first);
00264 }
00265
00269 void clear() { groups.clear(); }
00270 };
00271
00272 };
00273
00274
00275 #endif