1 : /*
2 : * Classes handling tag patches
3 : *
4 : * Copyright (C) 2003--2006 Enrico Zini <enrico@debian.org>
5 : *
6 : * This library is free software; you can redistribute it and/or
7 : * modify it under the terms of the GNU Lesser General Public
8 : * License as published by the Free Software Foundation; either
9 : * version 2.1 of the License, or (at your option) any later version.
10 : *
11 : * This library is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this library; if not, write to the Free Software
18 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 : */
20 :
21 : #ifndef TAGCOLL_PATCHES_TCC
22 : #define TAGCOLL_PATCHES_TCC
23 :
24 : #include <tagcoll/patch.h>
25 : #include <wibble/singleton.h>
26 : #include <wibble/empty.h>
27 :
28 : using namespace std;
29 : using namespace wibble::operators;
30 :
31 : namespace tagcoll {
32 :
33 : template <typename ITEM, typename TAG>
34 : Patch<ITEM, TAG>::Patch(const ITEM& item, const std::set<TAG>& added, const std::set<TAG>& removed)
35 2 : : item(item), added(added-removed), removed(removed-added)
36 0 : {
37 2 : }
38 :
39 : template <typename ITEM, typename TAG> template<typename CONTA, typename CONTB>
40 2 : Patch<ITEM, TAG>::Patch(const ITEM& item, const CONTA& added, const CONTB& removed)
41 4 : : item(item)
42 : {
43 4 : std::copy(added.begin(), added.end(), inserter(this->added, this->added.begin()));
44 4 : std::copy(removed.begin(), removed.end(), inserter(this->removed, this->removed.begin()));
45 4 : }
46 :
47 : template <class ITEM, class TAG>
48 : void PatchList<ITEM, TAG>::addPatch(const Patch<ITEM, TAG>& patch)
49 : {
50 : // Filter out empty patches
51 15 : if (patch.added.empty() && patch.removed.empty())
52 0 : return;
53 :
54 15 : iterator i = this->find(patch.item);
55 15 : if (i == this->end())
56 13 : insert(make_pair<ITEM, Patch<ITEM, TAG> >(patch.item, patch));
57 : else
58 2 : i->second.mergeWith(patch);
59 : }
60 :
61 : template <class ITEM, class TAG>
62 : void PatchList<ITEM, TAG>::addPatch(const PatchList<ITEM, TAG>& patches)
63 : {
64 : for (typename PatchList<ITEM, TAG>::const_iterator i = patches.begin();
65 : i != patches.end(); i++)
66 : addPatch(i->second);
67 : }
68 :
69 : template <class ITEM, class TAG>
70 : void PatchList<ITEM, TAG>::addPatchInverted(const Patch<TAG, ITEM>& patch)
71 : {
72 : // Filter out empty patches
73 2 : if (patch.added.empty() && patch.removed.empty())
74 0 : return;
75 :
76 8 : for (typename std::set<ITEM>::const_iterator i = patch.added.begin();
77 : i != patch.added.end(); ++i)
78 2 : addPatch(Patch<ITEM, TAG>(*i, wibble::singleton(patch.item), wibble::Empty<TAG>()));
79 4 : for (typename std::set<ITEM>::const_iterator i = patch.removed.begin();
80 : i != patch.removed.end(); ++i)
81 0 : addPatch(Patch<ITEM, TAG>(*i, wibble::Empty<TAG>(), wibble::singleton(patch.item)));
82 : }
83 :
84 : template <class ITEM, class TAG>
85 : void PatchList<ITEM, TAG>::addPatchInverted(const PatchList<TAG, ITEM>& patches)
86 : {
87 4 : for (typename PatchList<TAG, ITEM>::const_iterator i = patches.begin();
88 : i != patches.end(); i++)
89 2 : addPatchInverted(i->second);
90 2 : }
91 :
92 :
93 : template <class ITEM, class TAG> template<typename COLL1, typename COLL2>
94 : void PatchList<ITEM, TAG>::addPatch(const COLL1& im1, const COLL2& im2)
95 : {
96 : // FIXME: if I could implement the guarantee that the collection iterators
97 : // iterate in sorted item order, then I wouldn't need to extract all the
98 : // items of im2
99 : std::set<ITEM> im2items = im2.getTaggedItems();
100 : for (typename COLL1::const_iterator i1 = im1.begin();
101 : i1 != im1.end(); ++i1)
102 : {
103 : im2items.erase(i1->first);
104 : std::set<TAG> ts2 = im2.getTagsOfItem(i1->first);
105 : std::set<TAG> added = ts2 - i1->second;
106 : std::set<TAG> removed = i1->second - ts2;
107 : if (!added.empty() || !removed.empty())
108 : addPatch(Patch<ITEM, TAG>(i1->first, added, removed));
109 : }
110 : for (typename std::set<ITEM>::const_iterator i = im2items.begin();
111 : i != im2items.end(); ++i)
112 : {
113 : addPatch(Patch<ITEM, TAG>(*i, im2.getTagsOfItem(*i), wibble::Empty<TAG>()));
114 : }
115 : }
116 :
117 : template <class ITEM, class TAG>
118 : void PatchList<ITEM, TAG>::removeRedundant(const ITEM& item, const std::set<TAG>& tags)
119 : {
120 4 : iterator i = this->find(item);
121 4 : if (i == this->end()) return;
122 4 : i->second.removeRedundant(tags);
123 : }
124 :
125 : template <class ITEM, class TAG>
126 : std::set<TAG> PatchList<ITEM, TAG>::patch(const ITEM& item, const std::set<TAG>& tagset) const
127 : {
128 : // Find the patch record for this item
129 14 : const_iterator p = this->find(item);
130 14 : if (p == this->end())
131 : // If there are no patches, return the tagset unchanged
132 13 : return tagset;
133 :
134 : // There are patches: apply them:
135 1 : return p->second.apply(tagset);
136 : }
137 :
138 : template <class ITEM, class TAG>
139 : PatchList<ITEM, TAG> PatchList<ITEM, TAG>::getReverse() const
140 : {
141 : PatchList<ITEM, TAG> res;
142 : for (typename PatchList<ITEM, TAG>::const_iterator i = this->begin();
143 : i != this->end(); i++)
144 : res.addPatch(i->second.getReverse());
145 : return res;
146 : }
147 :
148 : template<typename ITEM, typename TAG> template<typename OUT>
149 : void PatchList<ITEM, TAG>::output(OUT out) const
150 : {
151 6 : for (typename PatchList<ITEM, TAG>::const_iterator i = this->begin();
152 : i != this->end(); ++i)
153 : {
154 3 : *out = i->second;
155 3 : ++out;
156 : }
157 3 : }
158 :
159 :
160 6 : }
161 :
162 : #endif
163 :
164 : // vim:set ts=4 sw=4:
|