1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/ui/SelectableImpl.h
12 #ifndef ZYPP_UI_SELECTABLEIMPL_H
13 #define ZYPP_UI_SELECTABLEIMPL_H
16 #include "zypp/base/LogTools.h"
18 #include "zypp/base/PtrTypes.h"
20 #include "zypp/ResPool.h"
21 #include "zypp/Resolver.h"
22 #include "zypp/ui/Selectable.h"
23 #include "zypp/ui/SelectableTraits.h"
27 ///////////////////////////////////////////////////////////////////
29 { /////////////////////////////////////////////////////////////////
30 ///////////////////////////////////////////////////////////////////
32 { /////////////////////////////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////
36 // CLASS NAME : Selectable::Impl
38 /** Selectable implementation.
39 * \note Implementation is based in PoolItem, just the Selectable
40 * inteface restricts them to ResObject::constPtr.
42 struct Selectable::Impl
46 typedef SelectableTraits::AvailableItemSet AvailableItemSet;
47 typedef SelectableTraits::available_iterator available_iterator;
48 typedef SelectableTraits::available_const_iterator available_const_iterator;
49 typedef SelectableTraits::available_size_type available_size_type;
51 typedef SelectableTraits::InstalledItemSet InstalledItemSet;
52 typedef SelectableTraits::installed_iterator installed_iterator;
53 typedef SelectableTraits::installed_const_iterator installed_const_iterator;
54 typedef SelectableTraits::installed_size_type installed_size_type;
56 typedef SelectableTraits::PickList PickList;
59 template <class _Iterator>
60 Impl( const ResObject::Kind & kind_r,
61 const std::string & name_r,
64 : _ident( sat::Solvable::SplitIdent( kind_r, name_r ).ident() )
68 for_( it, begin_r, end_r )
70 if ( it->status().isInstalled() )
71 _installedItems.insert( *it );
73 _availableItems.insert( *it );
79 IdString ident() const
83 ResObject::Kind kind() const
87 const std::string & name() const
91 Status status() const;
94 bool setStatus( Status state_r, ResStatus::TransactByValue causer_r );
96 /** Installed object (transacting ot highest version). */
97 PoolItem installedObj() const
99 if ( installedEmpty() )
101 PoolItem ret( transactingInstalled() );
102 return ret ? ret : *_installedItems.begin();
105 /** Best among available objects.
106 * The transacting candidate or the one scheduled to receive
109 PoolItem candidateObj() const
111 PoolItem ret( transactingCandidate() );
114 return _candidate ? _candidate : defaultCandidate();
117 /** Set a userCandidate (out of available objects).
118 * \return The new userCandidate or NULL if choice was invalid
119 * (not among availableObjs).
121 PoolItem setCandidate( const PoolItem & newCandidate_r, ResStatus::TransactByValue causer_r );
123 /** The best candidate provided by a specific \ref Repository, if there is one.
124 * In contrary to \ref candidateObj, this may return no item even if
125 * there are available objects. This simply means the \ref Repository
126 * does not provide this object.
128 PoolItem candidateObjFrom( Repository repo_r ) const
130 for_( it, availableBegin(), availableEnd() )
132 if ( (*it)->repository() == repo_r )
138 /** The best candidate for update, if there is one.
139 * In contrary to \ref candidateObj, this may return no item even if
140 * there are available objects. This simply means the best object is
141 * already installed, and all available objects violate at least one
144 PoolItem updateCandidateObj() const
146 PoolItem defaultCand( defaultCandidate() );
148 if ( multiversionInstall() )
149 return identicalInstalled( defaultCand ) ? PoolItem() : defaultCand;
151 if ( installedEmpty() || ! defaultCand )
153 // Here: installed and defaultCand are non NULL and it's not a
154 // multiversion install.
156 // update candidate must come from the highest priority repo
157 if ( defaultCand->repoInfo().priority() != (*availableBegin())->repoInfo().priority() )
160 PoolItem installed( installedObj() );
161 // check vendor change
162 if ( ! ( ResPool::instance().resolver().allowVendorChange()
163 || VendorAttr::instance().equivalent( defaultCand->vendor(), installed->vendor() ) ) )
166 // check arch change (arch noarch changes are allowed)
167 if ( defaultCand->arch() != installed->arch()
168 && ! ( defaultCand->arch() == Arch_noarch || installed->arch() == Arch_noarch ) )
171 // check greater edition
172 if ( defaultCand->edition() <= installed->edition() )
178 /** \copydoc Selectable::highestAvailableVersionObj()const */
179 PoolItem highestAvailableVersionObj() const
182 for_( it, availableBegin(), availableEnd() )
184 if ( !ret || (*it).satSolvable().edition() > ret.satSolvable().edition() )
190 /** \copydoc Selectable::identicalAvailable( const PoolItem & )const */
191 bool identicalAvailable( const PoolItem & rhs ) const
192 { return bool(identicalAvailableObj( rhs )); }
194 /** \copydoc Selectable::identicalInstalled( const PoolItem & )const */
195 bool identicalInstalled( const PoolItem & rhs ) const
196 { return bool(identicalInstalledObj( rhs )); }
198 /** \copydoc Selectable::identicalAvailableObj( const PoolItem & rhs ) const */
199 PoolItem identicalAvailableObj( const PoolItem & rhs ) const
201 if ( !availableEmpty() && rhs )
203 for_( it, _availableItems.begin(), _availableItems.end() )
205 if ( identical( *it, rhs ) )
212 /** \copydoc Selectable::identicalInstalledObj( const PoolItem & rhs ) const */
213 PoolItem identicalInstalledObj( const PoolItem & rhs ) const
215 if ( !installedEmpty() && rhs )
217 for_( it, _installedItems.begin(), _installedItems.end() )
219 if ( identical( *it, rhs ) )
226 /** Best among all objects. */
227 PoolItem theObj() const
229 PoolItem ret( candidateObj() );
232 return installedObj();
235 ////////////////////////////////////////////////////////////////////////
237 bool availableEmpty() const
238 { return _availableItems.empty(); }
240 available_size_type availableSize() const
241 { return _availableItems.size(); }
243 available_const_iterator availableBegin() const
244 { return _availableItems.begin(); }
246 available_const_iterator availableEnd() const
247 { return _availableItems.end(); }
249 ////////////////////////////////////////////////////////////////////////
251 bool installedEmpty() const
252 { return _installedItems.empty(); }
254 installed_size_type installedSize() const
255 { return _installedItems.size(); }
257 installed_iterator installedBegin() const
258 { return _installedItems.begin(); }
260 installed_iterator installedEnd() const
261 { return _installedItems.end(); }
263 ////////////////////////////////////////////////////////////////////////
265 const PickList & picklist() const
267 if ( ! _picklistPtr )
269 _picklistPtr.reset( new PickList );
270 // installed without identical avaialble first:
271 for_( it, _installedItems.begin(), _installedItems.end() )
273 if ( ! identicalAvailable( *it ) )
274 _picklistPtr->push_back( *it );
276 _picklistPtr->insert( _picklistPtr->end(), availableBegin(), availableEnd() );
278 return *_picklistPtr;
281 bool picklistEmpty() const
282 { return picklist().empty(); }
284 picklist_size_type picklistSize() const
285 { return picklist().size(); }
287 picklist_iterator picklistBegin() const
288 { return picklist().begin(); }
290 picklist_iterator picklistEnd() const
291 { return picklist().end(); }
293 ////////////////////////////////////////////////////////////////////////
295 bool isUnmaintained() const
296 { return availableEmpty(); }
298 bool multiversionInstall() const
299 { return sat::Pool::instance().isMultiversion( ident() ); }
301 bool pickInstall( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r );
303 bool pickDelete( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r );
305 Status pickStatus( const PoolItem & pi_r ) const;
307 bool setPickStatus( const PoolItem & pi_r, Status state_r, ResStatus::TransactByValue causer_r );
309 ////////////////////////////////////////////////////////////////////////
311 bool isUndetermined() const
313 PoolItem cand( candidateObj() );
314 return ! cand || cand.isUndetermined();
316 bool isRelevant() const
318 PoolItem cand( candidateObj() );
319 return cand && cand.isRelevant();
321 bool isSatisfied() const
323 PoolItem cand( candidateObj() );
324 return cand && cand.isSatisfied();
326 bool isBroken() const
328 PoolItem cand( candidateObj() );
329 return cand && cand.isBroken();
332 /** Return who caused the modification. */
333 ResStatus::TransactByValue modifiedBy() const;
335 /** Return value of LicenceConfirmed bit. */
336 bool hasLicenceConfirmed() const
337 { return candidateObj() && candidateObj().status().isLicenceConfirmed(); }
339 /** Set LicenceConfirmed bit. */
340 void setLicenceConfirmed( bool val_r )
341 { if ( candidateObj() ) candidateObj().status().setLicenceConfirmed( val_r ); }
344 PoolItem transactingInstalled() const
346 for_( it, installedBegin(), installedEnd() )
348 if ( (*it).status().transacts() )
354 PoolItem transactingCandidate() const
356 for_( it, availableBegin(), availableEnd() )
358 if ( (*it).status().transacts() )
364 PoolItem defaultCandidate() const
366 if ( ! ( multiversionInstall() || installedEmpty() ) )
368 // prefer the installed objects arch and vendor
369 bool solver_allowVendorChange( ResPool::instance().resolver().allowVendorChange() );
370 for ( installed_const_iterator iit = installedBegin();
371 iit != installedEnd(); ++iit )
373 PoolItem sameArch; // in case there's no same vendor at least stay with same arch.
374 for ( available_const_iterator it = availableBegin();
375 it != availableEnd(); ++it )
377 // 'same arch' includes allowed changes to/from noarch.
378 if ( (*iit)->arch() == (*it)->arch() || (*iit)->arch() == Arch_noarch || (*it)->arch() == Arch_noarch )
380 if ( ! solver_allowVendorChange )
382 if ( VendorAttr::instance().equivalent( (*iit), (*it) ) )
384 else if ( ! sameArch ) // remember best same arch in case no same vendor found
387 else // same arch is sufficient
395 if ( _availableItems.empty() )
398 return *_availableItems.begin();
401 bool allCandidatesLocked() const
403 for ( available_const_iterator it = availableBegin();
404 it != availableEnd(); ++it )
406 if ( ! (*it).status().isLocked() )
409 return( ! _availableItems.empty() );
412 bool allInstalledLocked() const
414 for ( installed_const_iterator it = installedBegin();
415 it != installedEnd(); ++it )
417 if ( ! (*it).status().isLocked() )
420 return( ! _installedItems.empty() );
425 const IdString _ident;
426 const ResObject::Kind _kind;
427 const std::string _name;
428 InstalledItemSet _installedItems;
429 AvailableItemSet _availableItems;
430 //! The object selected by setCandidateObj() method.
432 //! lazy initialized picklist
433 mutable scoped_ptr<PickList> _picklistPtr;
435 ///////////////////////////////////////////////////////////////////
437 /** \relates Selectable::Impl Stream output */
438 inline std::ostream & operator<<( std::ostream & str, const Selectable::Impl & obj )
440 return str << '[' << obj.kind() << ']' << obj.name() << ": " << obj.status()
441 << " (I " << obj.installedSize() << ")"
442 << " (A " << obj.availableSize() << ")"
443 << obj.candidateObj();
446 /** \relates Selectable::Impl Stream output */
447 inline std::ostream & dumpOn( std::ostream & str, const Selectable::Impl & obj )
449 str << '[' << obj.kind() << ']' << obj.name() << ": " << obj.status()
450 << ( obj.multiversionInstall() ? " (multiversion)" : "") << endl;
452 if ( obj.installedEmpty() )
453 str << " (I 0) {}" << endl << " ";
456 PoolItem icand( obj.installedObj() );
457 str << " (I " << obj.installedSize() << ") {" << endl;
458 for_( it, obj.installedBegin(), obj.installedEnd() )
465 str << " " << t << " " << *it << endl;
470 if ( obj.availableEmpty() )
472 str << "(A 0) {}" << endl << " ";
476 PoolItem cand( obj.candidateObj() );
477 PoolItem up( obj.updateCandidateObj() );
478 str << "(A " << obj.availableSize() << ") {" << endl;
479 for_( it, obj.availableBegin(), obj.availableEnd() )
484 t = *it == up ? 'C' : 'c';
486 else if ( *it == up )
490 str << " " << t << " " << *it << endl;
495 if ( obj.picklistEmpty() )
501 PoolItem cand( obj.candidateObj() );
502 PoolItem up( obj.updateCandidateObj() );
503 str << "(P " << obj.picklistSize() << ") {" << endl;
504 for_( it, obj.picklistBegin(), obj.picklistEnd() )
509 t = *it == up ? 'C' : 'c';
511 else if ( *it == up )
515 str << " " << t << " " << *it << "\t" << obj.pickStatus( *it ) << endl;
522 /////////////////////////////////////////////////////////////////
524 ///////////////////////////////////////////////////////////////////
525 /////////////////////////////////////////////////////////////////
527 ///////////////////////////////////////////////////////////////////
528 #endif // ZYPP_UI_SELECTABLEIMPL_H