Rewrote PoolQuery::Iterator (adapt to AttrMatcher, fixes and speedup)
[platform/upstream/libzypp.git] / zypp / PoolQuery.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/PoolQuery.h
10  *
11 */
12 #ifndef ZYPP_POOLQUERY_H
13 #define ZYPP_POOLQUERY_H
14
15 #include <iosfwd>
16 #include <set>
17 #include <map>
18
19 #include "zypp/base/Regex.h"
20 #include "zypp/base/PtrTypes.h"
21 #include "zypp/base/Function.h"
22
23 #include "zypp/sat/SolvIterMixin.h"
24 #include "zypp/sat/LookupAttr.h"
25 #include "zypp/sat/AttrMatcher.h"
26 #include "zypp/sat/Pool.h"
27
28 ///////////////////////////////////////////////////////////////////
29 namespace zypp
30 { /////////////////////////////////////////////////////////////////
31
32   namespace detail
33   {
34     class PoolQueryIterator;
35   }
36
37   ///////////////////////////////////////////////////////////////////
38   //
39   //  CLASS NAME : PoolQuery
40   //
41   /**
42    * Meta-data query API. Returns solvables of specified kinds from specified
43    * repositories with attributes matching the specified search strings.
44    *
45    * The search strings can be specified via \ref addString() and
46    * \ref addAttribute() methods. String matching type can be set using the
47    * setMatch*() methods. Multiple search strings for a particular attribute
48    * will be combined into a regex (see \ref addString() and
49    * \ref addAttribute() for more details).
50    *
51    * The begin() and end() methods return a PoolQueryIterator returning
52    * \ref sat::Solvable objects which can easily be turned into \ref Resolvable
53    * objects. Additionally, thanx to the \ref sat::SolvIterMixin, a Selectable
54    * and PoolItem iterators are automatically available.
55    *
56    * <code>
57    * PoolQuery q;
58    * q.addAttribute(sat::SolvAttr::name, "zypp*");
59    * q.addKind(ResKind::package);
60    * q.setMatchGlob();
61    *
62    * for (PoolQuery::Selectable_iterator it = q.selectableBegin();
63    *     it != q.selectableEnd(); ++it)
64    * {
65    *   ui::Selectable::constPtr s = *it;
66    *   // ...
67    * }
68    * </code>
69    *
70    * Performance considerations
71    *
72    * Results of simple queries like those using one string and/or one attribute
73    * and/or one repository are filtered by sat-solver's Dataiterator directly,
74    * and thus it is fast.
75    *
76    * Queries with multiple strings are implemented using regexes. Queries based
77    * on kinds, multiple repos, and multiple attributes are filtered inside
78    * the PoolQuery, so these tend to be slower.
79    *
80    * \see tests/zypp/PoolQuery_test.cc for more examples
81    * \see sat::SolvIterMixin
82    */
83   class PoolQuery : public sat::SolvIterMixin<PoolQuery, detail::PoolQueryIterator>
84   {
85   public:
86     typedef std::set<std::string>                           StrContainer;
87     typedef std::set<ResKind>                               Kinds;
88     typedef std::map<sat::SolvAttr, StrContainer>           AttrRawStrMap;
89     typedef std::map<sat::SolvAttr, std::string>            AttrCompiledStrMap;
90     typedef std::map<sat::SolvAttr, str::regex>             AttrRegexMap;
91
92     typedef detail::PoolQueryIterator                       const_iterator;
93     typedef unsigned int                                    size_type;
94
95   public:
96     typedef function<bool( const sat::Solvable & )> ProcessResolvable;
97
98     PoolQuery();
99     ~PoolQuery();
100
101     /** Query result accessers. */
102     //@{
103     /**
104      * Compile the query and return an iterator to the result.
105      *
106      * \return An iterator (\ref detail::PoolQueryIterator) returning
107      *         sat::Solvable objects pointing at the beginning of the query result.
108      * \throws sat::MatchInvalidRegexException if the query was about to use a regex which
109      *         failed to compile.
110      *
111      * \note Note that PoolQuery is derived from \ref sat::SolvIterMixin which
112      *       makes PoolItem and Selectable iterators automatically available.
113      * \see \ref sat::SolvIterMixin
114      */
115     const_iterator begin() const;
116
117     /** An iterator pointing to the end of the query result. */
118     const_iterator end() const;
119
120     /** Whether the result is empty. */
121     bool empty() const;
122
123     /** Number of solvables in the query result. */
124     size_type size() const;
125     //@}
126
127     /**
128      * Executes the query with the current settings.
129      * Results are yielded via the \a fnc callback.
130      */
131     void execute(ProcessResolvable fnc);
132
133     /**
134      * Filter by selectable kind.
135      *
136      * By default, all kinds will be returned. If addKind() is used,
137      * only the specified kinds will be returned (multiple kinds will be ORed).
138      *
139      * Pass ResKind constants to this method, (e.g. ResKind::package).
140      */
141     void addKind(const ResKind & kind);
142
143     /**
144      * Filter by repo.
145      *
146      * By default, all repos will be returned. If addRepo() is used,
147      * only the specified repo will be returned (multiple repos will be ORed).
148      */
149     void addRepo(const std::string &repoalias);
150
151     /** Installed status filter setters. */
152     //@{
153
154     /**
155      * Filter by status (installed uninstalled)
156      */
157     enum StatusFilter {
158       ALL = 0, // both install filter and uninstall filter bits are 0
159       INSTALLED_ONLY = 1,
160       UNINSTALLED_ONLY = 2
161     };
162
163     /** Return only @System repo packages */
164     void setInstalledOnly();
165     /** Return only packages from repos other than @System. */
166     void setUninstalledOnly();
167     /** Set status filter directly \see StatusFilter */
168     void setStatusFilterFlags( StatusFilter flags );
169
170     //@}
171
172     /**
173      * Add a global query string. The string added via this method is applied
174      * to all query attributes as if addAttribute(..., \value) was called
175      * for all of them.
176      *
177      * This method can be used multiple times in which case the query strings
178      * will be combined (together with strings added via addAttribute()) into
179      * a regex. Searched attribute value will match this regex if <b>any</b>
180      * of these strings will match the value. This can be changed by
181      * (not yet implemented) \ref setRequireAll() method.
182      */
183     void addString(const std::string & value);
184
185     /**
186      * Filter by the \a value of the specified \a attr attribute. This can
187      * be any of the available solvable attributes.
188      *
189      * This method can be used multiple times with the same \a attr in which
190      * case the query strings will be combined (together with strings added
191      * via addString()) into a regex. Searched attribute value will match
192      * this regex if <b>any</b> of these strings will match the value.
193      * This can be changed by (not yet implemented) \ref setRequireAll()
194      * method.
195      *
196      * \note Solvables of a kind not supporting the specified attribute will
197      * <b>not</b> be returned.
198      * \todo check the above
199      *
200      * \param attr Attribute identfier. Use sat::Solvattr::* constants
201      * \param value What to search for.
202      *
203      * \see sat::SolvAttr
204      */
205     void addAttribute(const sat::SolvAttr & attr, const std::string & value = "");
206
207     /**
208      * Set version condition. This will filter out solvables not matching
209      * <tt>solvableEdition \a op \a edition</tt>.
210      *
211      * \param edition Edition to look for.
212      * \param op      Found-wanted relation operator.
213      */
214     void setEdition(const Edition & edition, const Rel & op = Rel::EQ);
215
216     /** \name Text Matching Options
217      * \note The implementation treats an empty search string as
218      * <it>"match always"</it>. So if you want to actually match
219      * an empty value, try <tt>( "^$", setMatchRegex )</tt>.
220      */
221     //@{
222     /**
223      * Turn case sentitivity on or off (unsets or sets \ref SEARCH_NOCASE flag).
224      * PoolQuery defaults to case insensitive search unless this method
225      * is used.
226      *
227      * \param value Whether to turn the case sensitivity on (default) or off.
228      */
229     void setCaseSensitive( bool value = true );
230
231     /**
232      * If set (default), look at the full path when searching in filelists.
233      * Otherwise just match the the basenames.
234      * \see \ref Match::FILES
235      */
236     void setFilesMatchFullPath( bool value = true );
237     /** \overload */
238     void setFilesMatchBasename( bool value = true )
239     { setFilesMatchFullPath( !value ); }
240
241     /** Set to match exact string instead of substring.*/
242     void setMatchExact();
243     /** Set to substring (the default). */
244     void setMatchSubstring();
245     /** Set to match globs. */
246     void setMatchGlob();
247     /** Set to use the query strings as regexes */
248     void setMatchRegex();
249     /** Set to match words (uses regex) */
250     void setMatchWord();
251     //void setLocale(const Locale & locale);
252     //@}
253
254     /**
255      * Require that all of the values set by addString or addAttribute
256      * match the values of respective attributes.
257      *
258      * \todo doesn't work yet, don't use this function
259      */
260     void setRequireAll( bool require_all = true );
261
262
263     /** \name getters */
264     //@{
265
266     /** Search strings added via addString() */
267     const StrContainer & strings() const;
268     /**
269      * Map (map<SolvAttr, StrContainer>) of attribute values added via
270      * addAttribute(), addDep in string form */
271     const AttrRawStrMap & attributes() const;
272
273     const StrContainer & attribute(const sat::SolvAttr & attr) const;
274
275     const Kinds & kinds() const;
276
277     const StrContainer & repos() const;
278
279     const Edition edition() const;
280     const Rel editionRel() const;
281
282     /**
283      * returns true if search is case sensitive
284      */
285     bool caseSensitive() const;
286
287     /** Whether searching in filelists looks at the full path or just at the basenames. */
288     bool filesMatchFullPath() const;
289     /** \overload */
290     bool filesMatchBasename() const
291     { return !filesMatchFullPath(); }
292
293     bool matchExact() const;
294     bool matchSubstring() const;
295     bool matchGlob() const;
296     bool matchRegex() const;
297     bool matchWord() const;
298
299     /** Returns string matching mode as enum.
300      * \see \ref Match::Mode
301      */
302     Match::Mode matchMode() const
303     { return flags().mode(); }
304
305     /**
306      * Whether all values added via addString() or addAttribute() are required
307      * to match the values of the respective attributes.
308      */
309     bool requireAll() const;
310
311     StatusFilter statusFilterFlags() const;
312     //@}
313
314     /**
315      * Reads from stream query. Attributes is sepated by delim. Query is
316      * separated by two delim.
317      *
318      * \param str input stream which contains query
319      * \param delim delimeter for attributes
320      * \return true if non-empty query is recovered
321      *
322      * \see readPoolQueriesFromFile
323      */
324     bool recover( std::istream &str, char delim = '\n' );
325
326     /**
327      * Writes a machine-readable string representation of the query to stream.
328      * Use \a delim as attribute delimiter.
329      *
330      * \param str output stream to write to
331      * \param delim delimiter for attributes
332      *
333      * \see writePoolQueriesToFile
334      */
335     void serialize( std::ostream &str, char delim = '\n' ) const;
336
337     /** Return a human-readable description of the query */
338     std::string asString() const;
339
340     bool operator==(const PoolQuery& b) const;
341     bool operator!=(const PoolQuery& b) const { return !(*this == b ); }
342
343     // low level API
344
345     /**
346      * Free function to get the satsolver repo search
347      * flags.
348      *
349      * \see \ref Match
350      */
351     Match flags() const;
352
353     /**
354      * Free function to set the satsolver repo search
355      * flags.
356      *
357      * \see \ref Match
358      */
359     void setFlags( const Match & flags );
360
361   public:
362     class Impl;
363
364     /** \deprecated unused, buggy and useless. */
365     ZYPP_DEPRECATED void setMatchFiles() {}
366     /** \deprecated unused, buggy and useless. */
367     ZYPP_DEPRECATED bool matchFiles() const { return false; }
368     /** \deprecated There should be no need for this internal value. To
369      * switch across all match mode types, use the enum values returned
370      * by \ref matchMode().  \see \ref Match::Mode.
371      *
372      */
373     ZYPP_DEPRECATED int  matchType() const { return flags().modeval(); }
374
375
376   private:
377     /** Pointer to implementation */
378     RW_pointer<Impl> _pimpl;
379   };
380   ///////////////////////////////////////////////////////////////////
381
382   /** \relates PoolQuery Stream output. */
383   std::ostream & operator<<( std::ostream & str, const PoolQuery & obj );
384
385
386   ///////////////////////////////////////////////////////////////////
387   namespace detail
388   { /////////////////////////////////////////////////////////////////
389
390   class PoolQueryMatcher;
391
392   ///////////////////////////////////////////////////////////////////
393   //
394   //  CLASS NAME : PoolQuery::PoolQueryIterator
395   //
396   /** \ref PoolQuery iterator as returned by \ref PoolQuery::begin.
397   */
398   class PoolQueryIterator : public boost::iterator_adaptor<
399     PoolQueryIterator                  // Derived
400     , sat::LookupAttr::iterator        // Base
401     , const sat::Solvable              // Value
402     , boost::forward_traversal_tag     // CategoryOrTraversal
403     , const sat::Solvable              // Reference
404   >
405   {
406     public:
407       /** Default ctor is also \c end.*/
408       PoolQueryIterator()
409       {}
410
411       /** \Ref PoolQuery ctor. */
412       PoolQueryIterator( const shared_ptr<PoolQueryMatcher> & matcher_r )
413       : _matcher( matcher_r )
414       { increment(); }
415
416     private:
417       friend class boost::iterator_core_access;
418
419       sat::Solvable dereference() const
420       { return base_reference().inSolvable(); }
421
422       void increment();
423
424    private:
425       shared_ptr<PoolQueryMatcher> _matcher;
426   };
427   ///////////////////////////////////////////////////////////////////
428
429   /** \relates PoolQueryIterator Stream output. */
430   inline std::ostream & operator<<( std::ostream & str, const PoolQueryIterator & obj )
431   { return str << obj.base(); }
432
433   ///////////////////////////////////////////////////////////////////
434   } //namespace detail
435   ///////////////////////////////////////////////////////////////////
436
437   inline detail::PoolQueryIterator PoolQuery::end() const
438   { return detail::PoolQueryIterator(); }
439
440   /////////////////////////////////////////////////////////////////
441 } // namespace zypp
442 ///////////////////////////////////////////////////////////////////
443
444 #endif // ZYPP_POOLQUERY_H