Imported Upstream version 16.3.2
[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/Hash.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::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 TSolv>
143         bool contains( const TSolv & 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         Iterable<Solvable_iterator> solvable() const
162         { return makeIterable( solvableBegin(), solvableEnd() ); }
163         //@}
164
165         /** \name Iterate as PoolItem */
166         //@{
167         typedef transform_iterator<asPoolItem,Solvable_iterator> PoolItem_iterator;
168         PoolItem_iterator poolItemBegin() const
169         { return make_transform_iterator( solvableBegin(), asPoolItem() ); }
170         PoolItem_iterator poolItemEnd() const
171         { return make_transform_iterator( solvableEnd(), asPoolItem() ); }
172         Iterable<PoolItem_iterator> poolItem() const
173         { return makeIterable( poolItemBegin(), poolItemEnd() ); }
174         //@}
175
176       private:
177         typedef filter_iterator<solvitermixin_detail::UnifyByIdent,Solvable_iterator> UnifiedSolvable_iterator;
178       public:
179         /** \name Iterate ui::Selectable::Ptr */
180         //@{
181         typedef transform_iterator<ui::asSelectable,UnifiedSolvable_iterator> Selectable_iterator;
182         Selectable_iterator selectableBegin() const
183         { return make_transform_iterator( unifiedSolvableBegin(), ui::asSelectable() ); }
184         Selectable_iterator selectableEnd() const
185         { return make_transform_iterator( unifiedSolvableEnd(), ui::asSelectable() ); }
186         Iterable<Selectable_iterator> selectable() const
187         { return makeIterable( selectableBegin(), selectableEnd() ); }
188         //@}
189
190       private:
191         /** \name Iterate unified Solbvables to be transformed into Selectable. */
192         //@{
193         UnifiedSolvable_iterator unifiedSolvableBegin() const
194         { return make_filter_iterator( solvitermixin_detail::UnifyByIdent(), solvableBegin(), solvableEnd() ); }
195         UnifiedSolvable_iterator unifiedSolvableEnd() const
196         { return make_filter_iterator( solvitermixin_detail::UnifyByIdent(), solvableEnd(), solvableEnd() ); }
197         Iterable<UnifiedSolvable_iterator> unifiedSolvable() const
198         { return makeIterable( unifiedSolvableBegin(), unifiedSolvableEnd() ); }
199         //@}
200       private:
201         const Derived & self() const
202         { return *static_cast<const Derived*>( this ); }
203       protected:
204         SolvIterMixin() {}
205         ~SolvIterMixin() {}
206         SolvIterMixin(const SolvIterMixin &) {}
207         void operator=(const SolvIterMixin &) {}
208      };
209     ///////////////////////////////////////////////////////////////////
210
211     /////////////////////////////////////////////////////////////////
212   } // namespace sat
213   ///////////////////////////////////////////////////////////////////
214   /////////////////////////////////////////////////////////////////
215 } // namespace zypp
216 ///////////////////////////////////////////////////////////////////
217 #endif // ZYPP_SAT_SOLVITERMIXIN_H