- Create the cache directly from the schema (installed) file.
[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     };
150   }
151
152   /** Return \c true if the CapSets contain at least one pair of
153    *  Capabilities that match.
154   */
155   inline bool hasMatches( const CapSet & lhs_r, const CapSet & rhs_r )
156   {
157     return( forEachMatchIn( lhs_r, rhs_r, capmatch_detail::AlwaysFalse() ) < 0 );
158   }
159
160   ///////////////////////////////////////////////////////////////////
161
162
163   /** Functor invoking \c action_r on each matching \ref Capability
164    *  in a \ref ResPool.
165    *
166    * Functor is provided to ease using \ref forEachMatchIn as action
167    * in other algorithms.
168    *
169    * \code
170    * bool consume( const CapAndItem & cai_r );
171    *
172    * ResPool  _pool;
173    * PoolItem _pi;
174    *
175    * // Invoke consume on all PoolItems obsoleted by pi.
176    * // short: forEachPoolItemMatchedBy( _pool, _pi, Dep::OBSOLETES, consume );
177    * for_each( _pi->dep(Dep::OBSOLETES).begin(),
178    *           _pi->dep(Dep::OBSOLETES).end(),
179    *           ForEachMatchInPool( _pool, Dep::PROVIDES, consume ) );
180    *
181    * // Invoke consume on all PoolItems obsoleting pi.
182    * // short: forEachPoolItemMatching( _pool, Dep::OBSOLETES, _pi, consume );
183    * for_each( pi->dep(Dep::PROVIDES).begin(),
184    *           pi->dep(Dep::PROVIDES).end(),
185    *           ForEachMatchInPool( _pool, Dep::OBSOLETES, consume ) );
186    *
187    * \endcode
188    *
189    * \ingroup g_Functor
190    * \ingroup CAPFILTERS
191    * \relates ResPool.
192    * \see forEachPoolItemMatchedBy
193    * \see forEachPoolItemMatching
194   */
195   class ForEachMatchInPool
196   {
197   public:
198     typedef function<bool(const CapAndItem &)> Action;
199
200   public:
201     ForEachMatchInPool( const ResPool & pool_r,
202                         const Dep &     dep_r,
203                         const Action &  action_r )
204     : _pool  ( pool_r )
205     , _dep   ( dep_r )
206     , _action( action_r )
207     {}
208
209     bool operator()( const Capability & cap_r ) const
210     {
211       return( forEachMatchIn( _pool, _dep, cap_r, _action )
212               >= 0 ); // i.e. _action did not return false
213     }
214
215   private:
216     ResPool _pool;
217     Dep     _dep;
218     Action  _action;
219   };
220
221   /** Find all items in a ResPool matched by a certain PoolItems
222    *  dependency set.
223    *
224    * Iterates <tt>poolitem_r->dep(poolitemdep_r)</tt>
225    * and invokes \c action_r on each item in \c pool_r,
226    * that provides a match.
227    * \code
228    * bool consume( const CapAndItem & cai_r );
229    *
230    * ResPool  _pool;
231    * PoolItem _pi;
232    *
233    * // Invoke consume on all PoolItems obsoleted by pi.
234    * forEachPoolItemMatchedBy( _pool, _pi, Dep::OBSOLETES, consume );
235    * \endcode
236    *
237    * \note \c action_r is invoked for each matching Capability. So if
238    * the same PoolItem provides multiple matches, \c action_r refers
239    * to the same PoolItem multiple times. It may as well be that
240    * \c poolitem_r provides a matching Capability. Use \ref OncePerPoolItem
241    * to compensate this if neccessary.
242   */
243   inline int forEachPoolItemMatchedBy( const ResPool &  pool_r,
244                                         const PoolItem & poolitem_r,
245                                         const Dep &      poolitemdep_r,
246                                         function<bool(const CapAndItem &)> action_r )
247   {
248     return invokeOnEach( poolitem_r->dep(poolitemdep_r).begin(),
249                          poolitem_r->dep(poolitemdep_r).end(),
250                          ForEachMatchInPool( pool_r, Dep::PROVIDES, action_r ) );
251   }
252
253   /** Find all items in a ResPool matching a certain PoolItem.
254    *
255    * Iterates <tt>poolitem_r->dep(Dep::PROVIDES)</tt>
256    * and invoking \c action_r on each item in \c pool_r,
257    * that provides a match.
258    * \code
259    * bool consume( const CapAndItem & cai_r );
260    *
261    * ResPool  _pool;
262    * PoolItem _pi;
263    *
264    * // Invoke consume on all PoolItems obsoleting pi.
265    * forEachPoolItemMatching( _pool, Dep::OBSOLETES, _pi, consume );
266    * \endcode
267    *
268    * \note \c action_r is invoked for each matching Capability. So if
269    * the same PoolItem provides multiple matches, \c action_r refers
270    * to the same PoolItem multiple times. It may as well be that
271    * \c poolitem_r provides a matching Capability. Use \ref OncePerPoolItem
272    * to compensate this if neccessary.
273   */
274   inline int forEachPoolItemMatching( const ResPool &  pool_r,
275                                       const Dep &      pooldep_r,
276                                       const PoolItem & poolitem_r,
277                                       function<bool(const CapAndItem &)> action_r )
278   {
279     return invokeOnEach( poolitem_r->dep(Dep::PROVIDES).begin(),
280                          poolitem_r->dep(Dep::PROVIDES).end(),
281                          ForEachMatchInPool( pool_r, pooldep_r, action_r ) );
282   }
283
284   /** Functor translating \ref CapAndItem actions into \ref PoolItem
285    *  actions avoiding multiple invocations for the same \ref PoolItem.
286    *
287    * Additionally you may omit invocation of \a action_r for a
288    * specific PoolItem.
289    *
290    * Even if no _action is given, the PoolItems that would have been
291    * processed are collected in a std::set, available via
292    * \ref collectedItems.
293    *
294    * \code
295    * bool consume( const CapAndItem & cai_r );
296    * bool consumePi( const PoolItem & pi_r );
297    *
298    * ResPool  _pool;
299    * PoolItem _pi;
300    *
301    * // Invoke consume on all PoolItems obsoleted by pi.
302    * // Once for each matching Capability, thus the same PoolItem
303    * // might be involved mutiple times.
304    * forEachPoolItemMatchedBy( _pool, _pi, Dep::OBSOLETES,
305    *                           consume );
306    *
307    * // Invoke consume on all PoolItems obsoleted by pi.
308    * // Once for each PoolItem, still including _pi in case
309    * // it provides a match by itself.
310    * forEachPoolItemMatchedBy( _pool, _pi, Dep::OBSOLETES,
311    *                           OncePerPoolItem( consumePi ) );
312    *
313    * // Invoke consume on all PoolItems obsoleted by pi.
314    * // Once for each PoolItem, omitting invokation for
315    * // _pi (in case it obsoletes itself).
316    * forEachPoolItemMatchedBy( _pool, _pi, Dep::OBSOLETES,
317    *                           OncePerPoolItem( consumePi, _pi ) );
318    * \endcode
319    * \ingroup g_Functor
320    * \ingroup CAPFILTERS
321   */
322   struct OncePerPoolItem
323   {
324   public:
325     typedef function<bool(const PoolItem &)> Action;
326
327   public:
328     explicit
329     OncePerPoolItem( const PoolItem & self_r = PoolItem() )
330     : _self  ( self_r )
331     , _uset  ( new std::set<PoolItem> )
332     {}
333
334     OncePerPoolItem( const Action & action_r,
335                      const PoolItem & self_r = PoolItem() )
336     : _action( action_r )
337     , _self  ( self_r )
338     , _uset  ( new std::set<PoolItem> )
339     {}
340
341     bool operator()( const CapAndItem & cai_r ) const
342     {
343       if ( cai_r.item == _self ) // omit _self
344         return true;
345       // intentionally collect items in _uset even
346       // if no _action specified.
347       if ( _uset->insert( cai_r.item ).second
348            && _action )
349         return _action( cai_r.item );
350
351       return true;
352     }
353
354     const std::set<PoolItem> & collectedItems() const
355     { return *_uset; }
356
357   private:
358     Action   _action;
359     PoolItem _self;
360     shared_ptr<std::set<PoolItem> > _uset;
361   };
362
363
364   //@}
365
366   /////////////////////////////////////////////////////////////////
367 } // namespace zypp
368 ///////////////////////////////////////////////////////////////////
369 #endif // ZYPP_CAPMATCHHELPER_H