backup
[platform/upstream/libzypp.git] / zypp / CapMatchHelper.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/CapMatchHelper.h
10  *
11 */
12 #ifndef ZYPP_CAPMATCHHELPER_H
13 #define ZYPP_CAPMATCHHELPER_H
14
15 #include "zypp/base/Algorithm.h"
16 #include "zypp/base/Function.h"
17 #include "zypp/ResPool.h"
18
19 ///////////////////////////////////////////////////////////////////
20 namespace zypp
21 { /////////////////////////////////////////////////////////////////
22
23   /** Functor testing whether argument matches a certain Capability.
24    * \ingroup g_Functor
25    * \ingroup CAPFILTERS
26   */
27   class MatchesCapability
28   {
29   public:
30     MatchesCapability( const Capability & lhs_r )
31     : _lhs( lhs_r )
32     {}
33
34     bool operator()( const CapAndItem & capitem_r ) const
35     { return operator()( capitem_r.cap ); }
36
37     bool operator()( const Capability & rhs_r ) const
38     { return( _lhs.matches( rhs_r ) == CapMatch::yes ); }
39
40   private:
41     const Capability & _lhs;
42   };
43
44   /** \defgroup CAPMATCHHELPER Find matching Capabilities.
45    * \ingroup g_Algorithm
46   */
47   //@{
48
49   /** Algorithm invoking \c action_r on each \ref CapSet entry
50    * that matches a given \ref Capability.
51   */
52   inline int forEachMatchIn( CapSet::const_iterator begin_r,
53                              CapSet::const_iterator end_r,
54                              const Capability & lhs_r,
55                              function<bool(const Capability &)> action_r )
56   {
57     std::string index( lhs_r.index() );
58     return invokeOnEach( begin_r, end_r,
59                          MatchesCapability( lhs_r ), // filter
60                          action_r );
61   }
62
63   /** Algorithm invoking \c action_r on each \ref CapSet entry
64    * that matches a given \ref Capability.
65   */
66   inline int forEachMatchIn( const CapSet & capset_r,
67                              const Capability & lhs_r,
68                              function<bool(const Capability &)> action_r )
69   {
70     return invokeOnEach( capset_r.begin(), capset_r.end(),
71                          MatchesCapability( lhs_r ), // filter
72                          action_r );
73   }
74
75   /** Algorithm invoking \c action_r on each matching \ref Capability
76    * in a \ref ResPool.
77    *
78    * \code
79    * // Returns wheter willing to collect more items.
80    * bool consume( const CapAndItem & cai_r );
81    *
82    * ResPool    _pool;
83    * Capability _cap;
84    * // Invoke consume on all provides that match _cap
85    * forEachMatchIn( _pool, Dep::PROVIDES, _cap, consume );
86    * \endcode
87    *
88    * \relates ResPool.
89    * \see ForEachMatchInPool
90   */
91   inline int forEachMatchIn( const ResPool & pool_r, const Dep & dep_r,
92                              const Capability & lhs_r,
93                              function<bool(const CapAndItem &)> action_r )
94   {
95     std::string index( lhs_r.index() );
96     return invokeOnEach( pool_r.byCapabilityIndexBegin( index, dep_r ),
97                          pool_r.byCapabilityIndexEnd( index, dep_r ),
98                          MatchesCapability( lhs_r ), // filter
99                          action_r );
100   }
101
102
103   ///////////////////////////////////////////////////////////////////
104
105   /** Functor invoking \c action_r on each matching \ref Capability
106    *  in a \ref CapSet.
107    *
108    * Functor is provided to ease using \ref forEachMatchIn as action
109    * in other algorithms (nested loop over two CapSets).
110   */
111   class ForEachMatchInCapSet
112   {
113   public:
114     typedef function<bool(const Capability &, const Capability &)> Action;
115
116   public:
117     ForEachMatchInCapSet( const CapSet & set_r, const Action & action_r )
118     : _set( set_r )
119     , _action( action_r )
120     {}
121
122     bool operator()( const Capability & cap_r ) const
123     {
124       return( forEachMatchIn( _set, cap_r, bind( _action, _1, cap_r ) )
125               >= 0 ); // i.e. _action did not return false
126     }
127
128   private:
129     const CapSet & _set;
130     Action         _action;
131   };
132
133   /** Invoke \c action_r on each matching pair of Capabilities within
134    * two CapSets. */
135   inline int forEachMatchIn( const CapSet & lhs_r,
136                              const CapSet & rhs_r,
137                              function<bool(const Capability &, const Capability &)> action_r )
138   {
139     return invokeOnEach( lhs_r.begin(), lhs_r.end(),
140                          ForEachMatchInCapSet( rhs_r, action_r ) );
141   }
142   ///////////////////////////////////////////////////////////////////
143
144   namespace capmatch_detail {
145     struct AlwaysFalse
146     {
147       bool operator()( const Capability &, const Capability & ) const
148       { return false; }
149       bool operator()( const Capability & ) const
150       { return false; }
151     };
152   }
153
154   /** Return \c true if the CapSet contains at least one Capabilitiy
155    *  that matches.
156   */
157   inline bool hasMatches( const CapSet & lhs_r, const Capability & rhs_r )
158   {
159     return( forEachMatchIn( lhs_r, rhs_r, capmatch_detail::AlwaysFalse() ) < 0 );
160   }
161
162   /** Return \c true if the CapSets contain at least one pair of
163    *  Capabilities that match.
164   */
165   inline bool hasMatches( const CapSet & lhs_r, const CapSet & rhs_r )
166   {
167     return( forEachMatchIn( lhs_r, rhs_r, capmatch_detail::AlwaysFalse() ) < 0 );
168   }
169
170   ///////////////////////////////////////////////////////////////////
171
172
173   /** Functor invoking \c action_r on each matching \ref Capability
174    *  in a \ref ResPool.
175    *
176    * Functor is provided to ease using \ref forEachMatchIn as action
177    * in other algorithms.
178    *
179    * \code
180    * bool consume( const CapAndItem & cai_r );
181    *
182    * ResPool  _pool;
183    * PoolItem _pi;
184    *
185    * // Invoke consume on all PoolItems obsoleted by pi.
186    * // short: forEachPoolItemMatchedBy( _pool, _pi, Dep::OBSOLETES, consume );
187    * for_each( _pi->dep(Dep::OBSOLETES).begin(),
188    *           _pi->dep(Dep::OBSOLETES).end(),
189    *           ForEachMatchInPool( _pool, Dep::PROVIDES, consume ) );
190    *
191    * // Invoke consume on all PoolItems obsoleting pi.
192    * // short: forEachPoolItemMatching( _pool, Dep::OBSOLETES, _pi, consume );
193    * for_each( pi->dep(Dep::PROVIDES).begin(),
194    *           pi->dep(Dep::PROVIDES).end(),
195    *           ForEachMatchInPool( _pool, Dep::OBSOLETES, consume ) );
196    *
197    * \endcode
198    *
199    * \ingroup g_Functor
200    * \ingroup CAPFILTERS
201    * \relates ResPool.
202    * \see forEachPoolItemMatchedBy
203    * \see forEachPoolItemMatching
204   */
205   class ForEachMatchInPool
206   {
207   public:
208     typedef function<bool(const CapAndItem &)> Action;
209
210   public:
211     ForEachMatchInPool( const ResPool & pool_r,
212                         const Dep &     dep_r,
213                         const Action &  action_r )
214     : _pool  ( pool_r )
215     , _dep   ( dep_r )
216     , _action( action_r )
217     {}
218
219     bool operator()( const Capability & cap_r ) const
220     {
221       return( forEachMatchIn( _pool, _dep, cap_r, _action )
222               >= 0 ); // i.e. _action did not return false
223     }
224
225   private:
226     ResPool _pool;
227     Dep     _dep;
228     Action  _action;
229   };
230
231   /** Find all items in a ResPool matched by a certain PoolItems
232    *  dependency set.
233    *
234    * Iterates <tt>poolitem_r->dep(poolitemdep_r)</tt>
235    * and invokes \c action_r on each item in \c pool_r,
236    * that provides a match.
237    * \code
238    * bool consume( const CapAndItem & cai_r );
239    *
240    * ResPool  _pool;
241    * PoolItem _pi;
242    *
243    * // Invoke consume on all PoolItems obsoleted by pi.
244    * forEachPoolItemMatchedBy( _pool, _pi, Dep::OBSOLETES, consume );
245    * \endcode
246    *
247    * \note \c action_r is invoked for each matching Capability. So if
248    * the same PoolItem provides multiple matches, \c action_r refers
249    * to the same PoolItem multiple times. It may as well be that
250    * \c poolitem_r provides a matching Capability. Use \ref OncePerPoolItem
251    * to compensate this if neccessary.
252   */
253   inline int forEachPoolItemMatchedBy( const ResPool &  pool_r,
254                                         const PoolItem & poolitem_r,
255                                         const Dep &      poolitemdep_r,
256                                         function<bool(const CapAndItem &)> action_r )
257   {
258     return invokeOnEach( poolitem_r->dep(poolitemdep_r).begin(),
259                          poolitem_r->dep(poolitemdep_r).end(),
260                          ForEachMatchInPool( pool_r, Dep::PROVIDES, action_r ) );
261   }
262
263   /** Find all items in a ResPool matching a certain PoolItem.
264    *
265    * Iterates <tt>poolitem_r->dep(Dep::PROVIDES)</tt>
266    * and invoking \c action_r on each item in \c pool_r,
267    * that provides a match.
268    * \code
269    * bool consume( const CapAndItem & cai_r );
270    *
271    * ResPool  _pool;
272    * PoolItem _pi;
273    *
274    * // Invoke consume on all PoolItems obsoleting pi.
275    * forEachPoolItemMatching( _pool, Dep::OBSOLETES, _pi, consume );
276    * \endcode
277    *
278    * \note \c action_r is invoked for each matching Capability. So if
279    * the same PoolItem provides multiple matches, \c action_r refers
280    * to the same PoolItem multiple times. It may as well be that
281    * \c poolitem_r provides a matching Capability. Use \ref OncePerPoolItem
282    * to compensate this if neccessary.
283   */
284   inline int forEachPoolItemMatching( const ResPool &  pool_r,
285                                       const Dep &      pooldep_r,
286                                       const PoolItem & poolitem_r,
287                                       function<bool(const CapAndItem &)> action_r )
288   {
289     return invokeOnEach( poolitem_r->dep(Dep::PROVIDES).begin(),
290                          poolitem_r->dep(Dep::PROVIDES).end(),
291                          ForEachMatchInPool( pool_r, pooldep_r, action_r ) );
292   }
293
294   /** Functor translating \ref CapAndItem actions into \ref PoolItem
295    *  actions avoiding multiple invocations for the same \ref PoolItem.
296    *
297    * Additionally you may omit invocation of \a action_r for a
298    * specific PoolItem.
299    *
300    * Even if no _action is given, the PoolItems that would have been
301    * processed are collected in a std::set, available via
302    * \ref collectedItems.
303    *
304    * \code
305    * bool consume( const CapAndItem & cai_r );
306    * bool consumePi( const PoolItem & pi_r );
307    *
308    * ResPool  _pool;
309    * PoolItem _pi;
310    *
311    * // Invoke consume on all PoolItems obsoleted by pi.
312    * // Once for each matching Capability, thus the same PoolItem
313    * // might be involved mutiple times.
314    * forEachPoolItemMatchedBy( _pool, _pi, Dep::OBSOLETES,
315    *                           consume );
316    *
317    * // Invoke consume on all PoolItems obsoleted by pi.
318    * // Once for each PoolItem, still including _pi in case
319    * // it provides a match by itself.
320    * forEachPoolItemMatchedBy( _pool, _pi, Dep::OBSOLETES,
321    *                           OncePerPoolItem( consumePi ) );
322    *
323    * // Invoke consume on all PoolItems obsoleted by pi.
324    * // Once for each PoolItem, omitting invokation for
325    * // _pi (in case it obsoletes itself).
326    * forEachPoolItemMatchedBy( _pool, _pi, Dep::OBSOLETES,
327    *                           OncePerPoolItem( consumePi, _pi ) );
328    * \endcode
329    * \ingroup g_Functor
330    * \ingroup CAPFILTERS
331   */
332   struct OncePerPoolItem
333   {
334   public:
335     typedef function<bool(const PoolItem &)> Action;
336
337   public:
338     explicit
339     OncePerPoolItem( const PoolItem & self_r = PoolItem() )
340     : _self  ( self_r )
341     , _uset  ( new std::set<PoolItem> )
342     {}
343
344     OncePerPoolItem( const Action & action_r,
345                      const PoolItem & self_r = PoolItem() )
346     : _action( action_r )
347     , _self  ( self_r )
348     , _uset  ( new std::set<PoolItem> )
349     {}
350
351     bool operator()( const CapAndItem & cai_r ) const
352     {
353       if ( cai_r.item == _self ) // omit _self
354         return true;
355       // intentionally collect items in _uset even
356       // if no _action specified.
357       if ( _uset->insert( cai_r.item ).second
358            && _action )
359         return _action( cai_r.item );
360
361       return true;
362     }
363
364     const std::set<PoolItem> & collectedItems() const
365     { return *_uset; }
366
367   private:
368     Action   _action;
369     PoolItem _self;
370     shared_ptr<std::set<PoolItem> > _uset;
371   };
372
373
374   //@}
375
376   /////////////////////////////////////////////////////////////////
377 } // namespace zypp
378 ///////////////////////////////////////////////////////////////////
379 #endif // ZYPP_CAPMATCHHELPER_H