fixup Fix to build with libxml 2.12.x (fixes #505)
[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/base/StrMatcher.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    * \note You will sometimes face the problem, that when using the \ref PoolItem
57    * iterator you hit multiple version of the same package, while when using the
58    * \ref ui::Selectable iterator the information which of the available candidates
59    * actually matched got lost. In this case class \ref PoolItemBest may help you.
60    * Use it to pick the best version only.
61    *
62    * <code>
63    * PoolQuery q;
64    * q.addAttribute(sat::SolvAttr::name, "zypp*");
65    * q.addKind(ResKind::package);
66    * q.setMatchGlob();
67    *
68    * for (PoolQuery::Selectable_iterator it = q.selectableBegin();
69    *     it != q.selectableEnd(); ++it)
70    * {
71    *   ui::Selectable::constPtr s = *it;
72    *   // ...
73    * }
74    * </code>
75    *
76    * Performance considerations
77    *
78    * Results of simple queries like those using one string and/or one attribute
79    * and/or one repository are filtered by sat-solver's Dataiterator directly,
80    * and thus it is fast.
81    *
82    * Queries with multiple strings are implemented using regexes. Queries based
83    * on kinds, multiple repos, and multiple attributes are filtered inside
84    * the PoolQuery, so these tend to be slower.
85    *
86    * \see detail::PoolQueryIterator on how to inspect matches in detail.
87    * \see tests/zypp/PoolQuery_test.cc for more examples
88    * \see sat::SolvIterMixin
89    */
90   class PoolQuery : public sat::SolvIterMixin<PoolQuery, detail::PoolQueryIterator>
91   {
92   public:
93     typedef std::set<ResKind>                               Kinds;
94     typedef std::set<std::string>                           StrContainer;
95     typedef std::map<sat::SolvAttr, StrContainer>           AttrRawStrMap;
96
97     typedef detail::PoolQueryIterator                       const_iterator;
98     typedef unsigned int                                    size_type;
99
100   public:
101     typedef function<bool( const sat::Solvable & )> ProcessResolvable;
102
103     PoolQuery();
104     ~PoolQuery();
105
106     /** Query result accessers. */
107     //@{
108     /**
109      * Compile the query and return an iterator to the result.
110      *
111      * \return An iterator (\ref detail::PoolQueryIterator) returning
112      *         sat::Solvable objects pointing at the beginning of the query result.
113      * \throws sat::MatchInvalidRegexException if the query was about to use a regex which
114      *         failed to compile.
115      *
116      * \note Note that PoolQuery is derived from \ref sat::SolvIterMixin which
117      *       makes PoolItem and Selectable iterators automatically available.
118      * \see \ref sat::SolvIterMixin
119      */
120     const_iterator begin() const;
121
122     /** An iterator pointing to the end of the query result. */
123     const_iterator end() const;
124
125     /** Whether the result is empty. */
126     bool empty() const;
127
128     /** Number of solvables in the query result. */
129     size_type size() const;
130     //@}
131
132     /**
133      * Executes the query with the current settings.
134      * Results are yielded via the \a fnc callback.
135      */
136     void execute(ProcessResolvable fnc);
137
138     /**
139      * Filter by selectable kind.
140      *
141      * By default, all kinds will be returned. If addKind() is used,
142      * only the specified kinds will be returned (multiple kinds will be ORed).
143      *
144      * \note This kind filter does not apply if you explicitly specify a ResKind
145      * when searching for \c sat::SolvAttr::name. The following will always match
146      * and include the kernel \c packages, no matter which kind filter is set.
147      * \code
148      *   addDependency( sat::SolvAttr::name, "package:kernel" );
149      * \endcode
150      *
151      * Pass ResKind constants to this method, (e.g. ResKind::package).
152      */
153     void addKind(const ResKind & kind);
154
155     /**
156      * Filter by repo.
157      *
158      * By default, all repos will be returned. If addRepo() is used,
159      * only the specified repo will be returned (multiple repos will be ORed).
160      */
161     void addRepo(const std::string &repoalias);
162
163     /** Installed status filter setters. */
164     //@{
165
166     /**
167      * Filter by status (installed uninstalled)
168      */
169     enum StatusFilter {
170       ALL = 0, // both install filter and uninstall filter bits are 0
171       INSTALLED_ONLY = 1,
172       UNINSTALLED_ONLY = 2
173     };
174
175     /** Return only @System repo packages */
176     void setInstalledOnly();
177     /** Return only packages from repos other than @System. */
178     void setUninstalledOnly();
179     /** Set status filter directly \see StatusFilter */
180     void setStatusFilterFlags( StatusFilter flags );
181
182     //@}
183
184     /**
185      * Add a global query string. The string added via this method is applied
186      * to all query attributes as if addAttribute(..., \value) was called
187      * for all of them.
188      *
189      * This method can be used multiple times in which case the query strings
190      * will be combined (together with strings added via addAttribute()) into
191      * a regex. Searched attribute value will match this regex if <b>any</b>
192      * of these strings will match the value.
193      */
194     void addString(const std::string & value);
195
196     /**
197      * Filter by the \a value of the specified \a attr attribute. This can
198      * be any of the available solvable attributes.
199      *
200      * This method can be used multiple times with the same \a attr in which
201      * case the query strings will be combined (together with strings added
202      * via addString()) into a regex. Searched attribute value will match
203      * this regex if <b>any</b> of these strings will match the value.
204      *
205      * \note Though it is possible to use dependency attributes like
206      * \ref Solv::Attr::provides here, note that the query string is
207      * matched against a dependencies \c "name" part only. Any
208      * <tt>"op edition"</tt> part of a \ref Capability is \b not
209      * considered at all. \see \ref addDependency on how to query for
210      * capabilities including edition ranges.
211      *
212      * \note Solvables of a kind not supporting the specified attribute will
213      * <b>not</b> be returned.
214      * \todo check the above
215      *
216      * \param attr Attribute identfier. Use sat::Solvattr::* constants
217      * \param value What to search for.
218      *
219      * \see sat::SolvAttr
220      */
221     void addAttribute( const sat::SolvAttr & attr, const std::string & value = "" );
222
223     /** \name Filter by dependencies matching a broken down capability <tt>name [op edition]</tt> and/or architecture.
224      *
225      * The capabilities \c name part may be defined as query string
226      * like with \ref addAttribute. Globing and regex are supported.
227      * Global query strings defined by \ref addString are considered.
228      *
229      * So without any <tt>op edition arch</tt> addDependency behaves the
230      * same as \ref addAttribute. If an edition range is given, matches
231      * are restricted accordingly. There are various overloads, so pick
232      * the one you like best.
233      *
234      * An optional \c arch argument will additionally require the matching
235      * solvable to be of this arch.
236      *
237      * \code
238      * {
239      *   setMatchGlob();
240      *   setCaseSensitive( false );
241      *   addDependency( sat::SolvAttr::provides, "kde*", Rel::EQ, Edition("2.0") );
242      *   addDependency( sat::SolvAttr::provides, "kde*", Edition("2.0") ); // same as above
243      * }
244      * {
245      *   setMatchGlob();
246      *   setCaseSensitive( false );
247      *   addString( "kde*" );
248      *   addDependency( sat::SolvAttr::provides, Rel::EQ, Edition("2.0") );// same as above
249      *   addDependency( sat::SolvAttr::provides, Edition("2.0") );         // same as above
250      * }
251      * \endcode
252      *
253      * \note Thre's also a version of \ref addDependency provided, that takes a
254      * complete \ref Capability as argument. This always requires an exact match
255      * of the name part (as the resolver would do it).
256      *
257      * This is the list of valid dependency attributes:
258      * \code
259      *   SolvAttr::provides
260      *   SolvAttr::obsoletes
261      *   SolvAttr::conflicts
262      *   SolvAttr::requires
263      *   SolvAttr::recommends
264      *   SolvAttr::suggests
265      *   SolvAttr::supplements
266      *   SolvAttr::enhances
267      * \endcode
268      *
269      * \note <b>What happens if a non dependency attribute is passed?<\b>
270      * If an edition range is given, it is matched against the matching
271      * solvables edition instead. Without edition range it behaves the
272      * same as \ref addAttribute.
273      *
274      * \code
275      *   // Find all packages providing "kernel > 2.0"
276      *   addDependency( sat::SolvAttr::provides, "kernel", Rel::GT, Edition("2.0") );
277      *
278      *   // // Find all packages named "kernel" and with edition "> 2.0"
279      *   addDependency( sat::SolvAttr::name, "kernel", Rel::GT, Edition("2.0") );
280      * \endcode
281      */
282     //@{
283     /** Query <tt>"name|global op edition"</tt>. */
284     void addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition );
285     /**  \overload also restricting architecture */
286     void addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition, const Arch & arch );
287     /**  \overload also use an individual Match::Mode for the \a name */
288     void addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition, const Arch & arch, Match::Mode mode );
289
290     /** \overload Query <tt>"name|global == edition"</tt>. */
291     void addDependency( const sat::SolvAttr & attr, const std::string & name, const Edition & edition )
292     { addDependency( attr, name, Rel::EQ, edition ); }
293     /**  \overload also restricting architecture */
294     void addDependency( const sat::SolvAttr & attr, const std::string & name, const Edition & edition, const Arch & arch )
295     { addDependency( attr, name, Rel::EQ, edition, arch ); }
296
297     /** \overload Query <tt>"name|global"</tt>. */
298     void addDependency( const sat::SolvAttr & attr, const std::string & name )
299     { addDependency( attr, name, Rel::ANY, Edition() ); }
300     /**  \overload also restricting architecture */
301     void addDependency( const sat::SolvAttr & attr, const std::string & name, const Arch & arch )
302     { addDependency( attr, name, Rel::ANY, Edition(), arch ); }
303
304     /** \overload Query <tt>"global op edition"</tt>.*/
305     void addDependency( const sat::SolvAttr & attr, const Rel & op, const Edition & edition )
306     { addDependency( attr, std::string(), op, edition ); }
307     /**  \overload also restricting architecture */
308     void addDependency( const sat::SolvAttr & attr, const Rel & op, const Edition & edition, const Arch & arch )
309     { addDependency( attr, std::string(), op, edition, arch ); }
310
311     /** \overload Query <tt>"global == edition"</tt>. */
312     void addDependency( const sat::SolvAttr & attr, const Edition & edition )
313     { addDependency( attr, std::string(), Rel::EQ, edition ); }
314     /**  \overload also restricting architecture */
315     void addDependency( const sat::SolvAttr & attr, const Edition & edition, const Arch & arch )
316     { addDependency( attr, std::string(), Rel::EQ, edition, arch ); }
317
318     /** \overload Query <tt>"global"</tt>. */
319     void addDependency( const sat::SolvAttr & attr )
320     { addDependency( attr, std::string(), Rel::ANY, Edition() ); }
321     /**  \overload also restricting architecture */
322     void addDependency( const sat::SolvAttr & attr, const Arch & arch )
323     { addDependency( attr, std::string(), Rel::ANY, Edition(), arch ); }
324
325     /** \overload Query taking a \ref Capability (always exact name match).
326      * \note If a non dependency attribute is passed, the \ref Capability
327      * will always be matched against the Solvables \c name and \c edition.
328     */
329     void addDependency( const sat::SolvAttr & attr, Capability cap_r );
330     //@}
331
332     /**
333      * Set version condition. This will filter out solvables not matching
334      * <tt>solvableEdition \a op \a edition</tt>.
335      *
336      * \param edition Edition to look for.
337      * \param op      Found-wanted relation operator.
338      */
339     void setEdition(const Edition & edition, const Rel & op = Rel::EQ);
340
341     /** \name Text Matching Options
342      * \note The implementation treats an empty search string as
343      * <it>"match always"</it>. So if you want to actually match
344      * an empty value, try <tt>( "^$", setMatchRegex )</tt>.
345      */
346     //@{
347     /**
348      * Turn case sentitivity on or off (unsets or sets \ref SEARCH_NOCASE flag).
349      * PoolQuery defaults to case insensitive search unless this method
350      * is used.
351      *
352      * \param value Whether to turn the case sensitivity on (default) or off.
353      */
354     void setCaseSensitive( bool value = true );
355
356     /**
357      * If set (default), look at the full path when searching in filelists.
358      * Otherwise just match the the basenames.
359      * \see \ref Match::FILES
360      */
361     void setFilesMatchFullPath( bool value = true );
362     /** \overload */
363     void setFilesMatchBasename( bool value = true )
364     { setFilesMatchFullPath( !value ); }
365
366     /** Set to match exact string instead of substring.*/
367     void setMatchExact();
368     /** Set to substring (the default). */
369     void setMatchSubstring();
370     /** Set to match globs. */
371     void setMatchGlob();
372     /** Set to use the query strings as regexes */
373     void setMatchRegex();
374     /** Set substring to match words */
375     void setMatchWord();
376     //void setLocale(const Locale & locale);
377     //@}
378
379     /** \name getters */
380     //@{
381
382     /** Search strings added via addString() */
383     const StrContainer & strings() const;
384     /**
385      * Map (map<SolvAttr, StrContainer>) of attribute values added via
386      * addAttribute(), addDep in string form */
387     const AttrRawStrMap & attributes() const;
388
389     const StrContainer & attribute(const sat::SolvAttr & attr) const;
390
391     const Kinds & kinds() const;
392
393     const StrContainer & repos() const;
394
395     const Edition edition() const;
396     const Rel editionRel() const;
397
398     /**
399      * returns true if search is case sensitive
400      */
401     bool caseSensitive() const;
402
403     /** Whether searching in filelists looks at the full path or just at the basenames. */
404     bool filesMatchFullPath() const;
405     /** \overload */
406     bool filesMatchBasename() const
407     { return !filesMatchFullPath(); }
408
409     bool matchExact() const;
410     bool matchSubstring() const;
411     bool matchGlob() const;
412     bool matchRegex() const;
413     bool matchWord() const;
414
415     /** Returns string matching mode as enum.
416      * \see \ref Match::Mode
417      */
418     Match::Mode matchMode() const
419     { return flags().mode(); }
420
421     StatusFilter statusFilterFlags() const;
422     //@}
423
424     /**
425      * Reads from stream query. Attributes is sepated by delim. Query is
426      * separated by two delim.
427      *
428      * \param str input stream which contains query
429      * \param delim delimeter for attributes
430      * \return true if non-empty query is recovered
431      *
432      * \see readPoolQueriesFromFile
433      */
434     bool recover( std::istream &str, char delim = '\n' );
435
436     /**
437      * Writes a machine-readable string representation of the query to stream.
438      * Use \a delim as attribute delimiter.
439      *
440      * \param str output stream to write to
441      * \param delim delimiter for attributes
442      *
443      * \see writePoolQueriesToFile
444      */
445     void serialize( std::ostream &str, char delim = '\n' ) const;
446
447     /** Return a human-readable description of the query */
448     std::string asString() const;
449
450     bool operator<(const PoolQuery& b) const;
451     bool operator==(const PoolQuery& b) const;
452     bool operator!=(const PoolQuery& b) const { return !(*this == b ); }
453
454     // low level API
455
456     /**
457      * Free function to get libsolv repo search
458      * flags.
459      *
460      * \see \ref Match
461      */
462     Match flags() const;
463
464     /**
465      * Free function to set libsolv repo search
466      * flags.
467      *
468      * \see \ref Match
469      */
470     void setFlags( const Match & flags );
471
472   public:
473     /** \deprecated Attribute was defined but never implemented/used. Will be removed in future versions. */
474     void setRequireAll( bool require_all = true ) ZYPP_DEPRECATED;
475     /** \deprecated Attribute was defined but never implemented/used. Will be removed in future versions. */
476     bool requireAll() const ZYPP_DEPRECATED;
477
478   public:
479     class Impl;
480   private:
481     /** Pointer to implementation */
482     RW_pointer<Impl> _pimpl;
483   };
484   ///////////////////////////////////////////////////////////////////
485
486   /** \relates PoolQuery Stream output. */
487   std::ostream & operator<<( std::ostream & str, const PoolQuery & obj );
488
489   /** \relates PoolQuery Detailed stream output. */
490   std::ostream & dumpOn( std::ostream & str, const PoolQuery & obj );
491
492   ///////////////////////////////////////////////////////////////////
493   namespace detail
494   { /////////////////////////////////////////////////////////////////
495
496   class PoolQueryMatcher;
497
498   ///////////////////////////////////////////////////////////////////
499   //
500   //  CLASS NAME : PoolQuery::PoolQueryIterator
501   //
502   /** \ref PoolQuery iterator as returned by \ref PoolQuery::begin.
503    *
504    * The \ref PoolQueryIterator visits sat::Solavables that do contain matches.
505    *
506    * But it also provides an iterator by itself, to allow a detailed inspection of
507    * the individual attribute matches within the current Solvable.
508    */
509   class PoolQueryIterator : public boost::iterator_adaptor<
510     PoolQueryIterator                  // Derived
511     , sat::LookupAttr::iterator        // Base
512     , const sat::Solvable              // Value
513     , boost::forward_traversal_tag     // CategoryOrTraversal
514     , const sat::Solvable              // Reference
515   >
516   {
517       typedef std::vector<sat::LookupAttr::iterator> Matches;
518     public:
519       typedef Matches::size_type size_type;
520       typedef Matches::const_iterator matches_iterator;
521     public:
522       /** Default ctor is also \c end.*/
523       PoolQueryIterator()
524       {}
525
526       /** \Ref PoolQuery ctor. */
527       PoolQueryIterator( const shared_ptr<PoolQueryMatcher> & matcher_r )
528       : _matcher( matcher_r )
529       { increment(); }
530
531       /** \name Detailed inspection of attribute matches within the current Solvable.
532        *
533        * The \ref matches_iterator visits all attribute matches within the current Solvable,
534        * providing a \ref sat::LookupAttr::iterator pointing to attribute. While a
535        * \ref matches_iterator itself becomes invalid if the PoolQueryIterator is advanced,
536        * the \ref sat::LookupAttr::iterator it pointed to stays valid, even after the query
537        * ended.
538        *
539        * \code
540        * // Setup query for "libzypp"  in name or requires:
541        * PoolQuery q;
542        * q.addString( "libzypp" );
543        * q.setMatchSubstring();
544        * q.setCaseSensitive( false );
545        * q.addAttribute( sat::SolvAttr::name );
546        * q.addDependency( sat::SolvAttr::requires );
547        *
548        * // Iterate the result:
549        * for_( solvIter, q.begin(), q.end() )
550        * {
551        *   sat::Solvable solvable( *solvIter );
552        *   cout << "Found matches in " << solvable << endl;
553        *   if ( verbose )
554        *     for_( attrIter, solvIter.matchesBegin(), solvIter.matchesEnd() )
555        *     {
556        *       sat::LookupAttr::iterator attr( *attrIter );
557        *       cout << "    " << attr.inSolvAttr() << "\t\"" << attr.asString() << "\"" << endl;
558        *     }
559        * }
560        *
561        *
562        * Found matches in PackageKit-0.3.11-1.12.i586(@System)
563        *    solvable:requires        "libzypp.so.523"
564        * Found matches in libqdialogsolver1-1.2.6-1.1.2.i586(@System)
565        *    solvable:requires        "libzypp.so.523"
566        *    solvable:requires        "libzypp >= 5.25.3-0.1.2"
567        * Found matches in libzypp-5.30.3-0.1.1.i586(@System)
568        *    solvable:name            "libzypp"
569        * Found matches in libzypp-testsuite-tools-4.2.6-8.1.i586(@System)
570        *    solvable:name            "libzypp-testsuite-tools"
571        *    solvable:requires        "libzypp.so.523"
572        * ...
573        * \endcode
574        */
575       //@{
576       /** \c False unless this is the \c end iterator. */
577       bool matchesEmpty() const                 { return ! _matcher; }
578       /** Number of attribute matches. */
579       size_type matchesSize() const             { return matches().size(); }
580       /** Begin of matches. */
581       matches_iterator matchesBegin() const     { return matches().begin(); }
582       /** End of matches. */
583       matches_iterator matchesEnd() const       { return matches().end(); }
584       //@}
585
586     private:
587       friend class boost::iterator_core_access;
588
589       sat::Solvable dereference() const
590       { return base_reference().inSolvable(); }
591
592       void increment();
593
594     private:
595       const Matches & matches() const;
596
597     private:
598       shared_ptr<PoolQueryMatcher> _matcher;
599       mutable shared_ptr<Matches>  _matches;
600   };
601   ///////////////////////////////////////////////////////////////////
602
603   /** \relates PoolQueryIterator Stream output. */
604   inline std::ostream & operator<<( std::ostream & str, const PoolQueryIterator & obj )
605   { return str << obj.base(); }
606
607   /** \relates PoolQueryIterator Detailed stream output. */
608   std::ostream & dumpOn( std::ostream & str, const PoolQueryIterator & obj );
609
610   ///////////////////////////////////////////////////////////////////
611   } //namespace detail
612   ///////////////////////////////////////////////////////////////////
613
614   inline detail::PoolQueryIterator PoolQuery::end() const
615   { return detail::PoolQueryIterator(); }
616
617   /////////////////////////////////////////////////////////////////
618 } // namespace zypp
619 ///////////////////////////////////////////////////////////////////
620
621 #endif // ZYPP_POOLQUERY_H