811d60ee7a8727a96cbc342aba70f8c9256be03f
[platform/upstream/libzypp.git] / zypp / sat / SolvIterMixin.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/sat/SolvIterMixin.h
10  *
11 */
12 #ifndef ZYPP_SAT_SOLVITERMIXIN_H
13 #define ZYPP_SAT_SOLVITERMIXIN_H
14
15 #include <iosfwd>
16
17 #include "zypp/base/PtrTypes.h"
18 #include "zypp/base/Iterator.h"
19 #include "zypp/base/Tr1hash.h"
20
21 #include "zypp/sat/Solvable.h"
22
23 ///////////////////////////////////////////////////////////////////
24 namespace zypp
25 { /////////////////////////////////////////////////////////////////
26
27   class PoolItem;
28   class asPoolItem; // transform functor
29
30   namespace ui
31   {
32     class asSelectable; // transform functor
33   }
34
35   ///////////////////////////////////////////////////////////////////
36   namespace sat
37   { /////////////////////////////////////////////////////////////////
38
39     class Solvable;
40     class asSolvable; // transform functor
41
42     namespace solvitermixin_detail
43     {
44       /** Unify by \c ident \c (kind:name).
45        * Return true on the 1st appearance of a new \c ident. This is
46        * used in \ref SolvIterMixin when mapping a  Solvable iterator
47        * to a Selectable iterator.
48       */
49       struct UnifyByIdent
50       {
51         bool operator()( const Solvable & solv_r ) const;
52
53         typedef std::tr1::unordered_set<unsigned> Uset;
54         UnifyByIdent()
55           : _uset( new Uset )
56         {}
57         shared_ptr<Uset> _uset;
58       };
59
60
61     } // namespace solvitermixin_detail
62
63
64     ///////////////////////////////////////////////////////////////////
65     //
66     //  CLASS NAME : SolvIterMixin<Derived,DerivedSolvable_iterator>
67     //
68     /** Base class providing common iterator types based on a \ref Solvable iterator.
69      *
70      * A class deriving from \ref SolvIterMixin must provide two methods
71      * \c begin and \c end returning iterator over \ref sat::Solvable.
72      *
73      * \ref SolvIterMixin will then provide iterators over the corresponding
74      * \ref PoolItem and \ref ui::Selectable_Ptr.
75      *
76      * \ref SolvIterMixin will also provide default implementations for \ref empty
77      * and \ref size by iterating from \c begin to \c end. In case \c Derived is
78      * able to provide a more efficient implementation, the methods should be overloaded.
79      *
80      * \note You will sometimes face the problem, that when using the \ref PoolItem
81      * iterator you hit multiple version of the same package, while when using the
82      * \ref ui::Selectable iterator the information which of the available candidates
83      * actually matched got lost. In this case class \ref PoolItemBest may help you.
84      * Use it to pick the best version only.
85      *
86      * \code
87      *     namespace detail
88      *     {
89      *       class WhatProvidesIterator;
90      *     }
91      *
92      *     class WhatProvides : public SolvIterMixin<WhatProvides,detail::WhatProvidesIterator>
93      *     {
94      *       public:
95      *         typedef detail::WhatProvidesIterator const_iterator;
96      *
97      *         // Iterator pointing to the first Solvable.
98      *         const_iterator begin() const;
99      *
100      *         // Iterator pointing behind the last Solvable.
101      *         const_iterator end() const;
102      *
103      *     };
104      *
105      *     namespace detail
106      *     {
107      *       class WhatProvidesIterator : public boost::iterator_adaptor<
108      *           WhatProvidesIterator          // Derived
109      *          , const detail::IdType *       // Base
110      *          , const Solvable               // Value
111      *          , boost::forward_traversal_tag // CategoryOrTraversal
112      *          , const Solvable               // Reference
113      *       >
114      *       {
115      *          ...
116      *       };
117      *     }
118      * \endcode
119      * \ingroup g_CRTP
120      */
121     template <class Derived,class DerivedSolvable_iterator>
122     class SolvIterMixin
123     {
124       public:
125         typedef size_t size_type;
126
127       public:
128         /** \name Convenience methods.
129          * In case \c Derived is able to provide a more efficient implementation,
130          * the methods should be overloaded.
131          */
132         //@{
133         /** Whether the collection is epmty. */
134         bool empty() const
135         { return( self().begin() == self().end() ); }
136
137         /** Size of the collection. */
138         size_type size() const
139         { size_type s = 0; for_( it, self().begin(), self().end() ) ++s; return s;}
140
141         /** Whether collection contains a specific \ref Solvable. */
142         template<class _Solv>
143         bool contains( const _Solv & solv_r ) const
144         {
145           Solvable solv( asSolvable()( solv_r ) );
146           for_( it, self().begin(), self().end() )
147             if ( *it == solv )
148               return true;
149           return false;
150         }
151         //@}
152
153       public:
154         /** \name Iterate as Solvable */
155         //@{
156         typedef  DerivedSolvable_iterator Solvable_iterator;
157         Solvable_iterator solvableBegin() const
158         { return self().begin(); }
159         Solvable_iterator solvableEnd() const
160         { return self().end(); }
161         //@}
162
163         /** \name Iterate as PoolItem */
164         //@{
165         typedef transform_iterator<asPoolItem,Solvable_iterator> PoolItem_iterator;
166         PoolItem_iterator poolItemBegin() const
167         { return make_transform_iterator( solvableBegin(), asPoolItem() ); }
168         PoolItem_iterator poolItemEnd() const
169         { return make_transform_iterator( solvableEnd(), asPoolItem() ); }
170         //@}
171
172       private:
173         typedef filter_iterator<solvitermixin_detail::UnifyByIdent,Solvable_iterator> UnifiedSolvable_iterator;
174       public:
175         /** \name Iterate ui::Selectable::Ptr */
176         //@{
177         typedef transform_iterator<ui::asSelectable,UnifiedSolvable_iterator> Selectable_iterator;
178         Selectable_iterator selectableBegin() const
179         { return make_transform_iterator( unifiedSolvableBegin(), ui::asSelectable() ); }
180         Selectable_iterator selectableEnd() const
181         { return make_transform_iterator( unifiedSolvableEnd(), ui::asSelectable() ); }
182         //@}
183
184       private:
185         /** \name Iterate unified Solbvables to be transformed into Selectable. */
186         //@{
187         UnifiedSolvable_iterator unifiedSolvableBegin() const
188         { return make_filter_iterator( solvitermixin_detail::UnifyByIdent(), solvableBegin(), solvableEnd() ); }
189         UnifiedSolvable_iterator unifiedSolvableEnd() const
190         { return make_filter_iterator( solvitermixin_detail::UnifyByIdent(), solvableEnd(), solvableEnd() );; }
191         //@}
192       private:
193         const Derived & self() const
194         { return *static_cast<const Derived*>( this ); }
195       protected:
196         SolvIterMixin() {}
197         ~SolvIterMixin() {}
198         SolvIterMixin(const SolvIterMixin &) {}
199         void operator=(const SolvIterMixin &) {}
200      };
201     ///////////////////////////////////////////////////////////////////
202
203     /////////////////////////////////////////////////////////////////
204   } // namespace sat
205   ///////////////////////////////////////////////////////////////////
206   /////////////////////////////////////////////////////////////////
207 } // namespace zypp
208 ///////////////////////////////////////////////////////////////////
209 #endif // ZYPP_SAT_SOLVITERMIXIN_H