SelectableImpl.h

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #ifndef ZYPP_UI_SELECTABLEIMPL_H
00013 #define ZYPP_UI_SELECTABLEIMPL_H
00014 
00015 #include <iostream>
00016 #include "zypp/base/LogTools.h"
00017 
00018 #include "zypp/base/PtrTypes.h"
00019 
00020 #include "zypp/ZConfig.h"
00021 #include "zypp/ui/Selectable.h"
00022 #include "zypp/ui/SelectableTraits.h"
00023 
00024 using std::endl;
00025 
00027 namespace zypp
00028 { 
00029 
00030   namespace ui
00031   { 
00032 
00034     //
00035     //  CLASS NAME : Selectable::Impl
00036     //
00041     struct Selectable::Impl
00042     {
00043     public:
00044 
00045       typedef SelectableTraits::AvailableItemSet         AvailableItemSet;
00046       typedef SelectableTraits::available_iterator       available_iterator;
00047       typedef SelectableTraits::available_const_iterator available_const_iterator;
00048       typedef SelectableTraits::available_size_type      available_size_type;
00049 
00050       typedef SelectableTraits::InstalledItemSet         InstalledItemSet;
00051       typedef SelectableTraits::installed_iterator       installed_iterator;
00052       typedef SelectableTraits::installed_const_iterator installed_const_iterator;
00053       typedef SelectableTraits::installed_size_type      installed_size_type;
00054 
00055       typedef SelectableTraits::PickList                PickList;
00056 
00057     public:
00058       template <class _Iterator>
00059       Impl( const ResObject::Kind & kind_r,
00060             const std::string & name_r,
00061             _Iterator begin_r,
00062             _Iterator end_r )
00063       : _ident( sat::Solvable::SplitIdent( kind_r, name_r ).ident() )
00064       , _kind( kind_r )
00065       , _name( name_r )
00066       {
00067         for_( it, begin_r, end_r )
00068         {
00069           if ( it->status().isInstalled() )
00070             _installedItems.insert( *it );
00071           else
00072             _availableItems.insert( *it );
00073         }
00074         _defaultCandidate = defaultCandidate();
00075       }
00076 
00077     public:
00079       IdString ident() const
00080       { return _ident; }
00081 
00083       ResObject::Kind kind() const
00084       { return _kind; }
00085 
00087       const std::string & name() const
00088       { return _name; }
00089 
00091       Status status() const;
00092 
00094       bool setStatus( Status state_r, ResStatus::TransactByValue causer_r );
00095 
00097       PoolItem installedObj() const
00098       {
00099         if ( installedEmpty() )
00100           return PoolItem();
00101         PoolItem ret( transactingInstalled() );
00102         return ret ? ret : *_installedItems.begin();
00103       }
00104 
00109       PoolItem candidateObj() const
00110       {
00111         PoolItem ret( transactingCandidate() );
00112         if ( ret )
00113           return ret;
00114         return _candidate ? _candidate : _defaultCandidate;
00115       }
00116 
00121       PoolItem setCandidate( const PoolItem & newCandidate_r, ResStatus::TransactByValue causer_r );
00122 
00128       PoolItem candidateObjFrom( Repository repo_r ) const
00129       {
00130         for_( it, availableBegin(), availableEnd() )
00131         {
00132           if ( (*it)->repository() == repo_r )
00133             return *it;
00134         }
00135         return PoolItem();
00136       }
00137 
00144       PoolItem updateCandidateObj() const
00145       {
00146         if ( multiversionInstall() || installedEmpty() || ! _defaultCandidate )
00147           return _defaultCandidate;
00148         // Here: installed and _defaultCandidate are non NULL and it's not a
00149         //       multiversion install.
00150 
00151         // update candidate must come from the highest priority repo
00152         if ( _defaultCandidate->repoInfo().priority() != (*availableBegin())->repoInfo().priority() )
00153           return PoolItem();
00154 
00155         PoolItem installed( installedObj() );
00156         // check vendor change
00157         if ( ! ( ZConfig::instance().solver_allowVendorChange()
00158                  || VendorAttr::instance().equivalent( _defaultCandidate->vendor(), installed->vendor() ) ) )
00159           return PoolItem();
00160 
00161         // check arch change (arch noarch changes are allowed)
00162         if ( _defaultCandidate->arch() != installed->arch()
00163            && ! ( _defaultCandidate->arch() == Arch_noarch || installed->arch() == Arch_noarch ) )
00164           return PoolItem();
00165 
00166         // check greater edition
00167         if ( _defaultCandidate->edition() <= installed->edition() )
00168           return PoolItem();
00169 
00170         return _defaultCandidate;
00171       }
00172 
00174       PoolItem highestAvailableVersionObj() const
00175       {
00176         PoolItem ret;
00177         for_( it, availableBegin(), availableEnd() )
00178         {
00179           if ( !ret || (*it).satSolvable().edition() > ret.satSolvable().edition() )
00180             ret = *it;
00181         }
00182         return ret;
00183       }
00184 
00186       bool identicalAvailable( const PoolItem & rhs ) const
00187       {
00188         if ( !availableEmpty() && rhs )
00189         {
00190           for_( it, _availableItems.begin(), _availableItems.end() )
00191           {
00192             if ( identical( *it, rhs ) )
00193               return true;
00194           }
00195         }
00196         return false;
00197       }
00198 
00200       bool identicalInstalled( const PoolItem & rhs ) const
00201       {
00202         if ( !installedEmpty() && rhs )
00203         {
00204           for_( it, _installedItems.begin(), _installedItems.end() )
00205           {
00206             if ( identical( *it, rhs ) )
00207               return true;
00208           }
00209         }
00210         return false;
00211       }
00212 
00214       PoolItem theObj() const
00215       {
00216         PoolItem ret( candidateObj() );
00217         if ( ret )
00218           return ret;
00219         return installedObj();
00220       }
00221 
00223 
00224       bool availableEmpty() const
00225       { return _availableItems.empty(); }
00226 
00227       available_size_type availableSize() const
00228       { return _availableItems.size(); }
00229 
00230       available_const_iterator availableBegin() const
00231       { return _availableItems.begin(); }
00232 
00233       available_const_iterator availableEnd() const
00234       { return _availableItems.end(); }
00235 
00237 
00238       bool installedEmpty() const
00239       { return _installedItems.empty(); }
00240 
00241       installed_size_type installedSize() const
00242       { return _installedItems.size(); }
00243 
00244       installed_iterator installedBegin() const
00245       { return _installedItems.begin(); }
00246 
00247       installed_iterator installedEnd() const
00248       { return _installedItems.end(); }
00249 
00251 
00252       const PickList & picklist() const
00253       {
00254         if ( ! _picklistPtr )
00255         {
00256           _picklistPtr.reset( new PickList );
00257           // installed without identical avaialble first:
00258           for_( it, _installedItems.begin(), _installedItems.end() )
00259           {
00260             if ( ! identicalAvailable( *it ) )
00261               _picklistPtr->push_back( *it );
00262           }
00263           _picklistPtr->insert( _picklistPtr->end(), availableBegin(), availableEnd() );
00264         }
00265         return *_picklistPtr;
00266       }
00267 
00268       bool picklistEmpty() const
00269       { return picklist().empty(); }
00270 
00271       picklist_size_type picklistSize() const
00272       { return picklist().size(); }
00273 
00274       picklist_iterator picklistBegin() const
00275       { return picklist().begin(); }
00276 
00277       picklist_iterator picklistEnd() const
00278       { return picklist().end(); }
00279 
00281 
00282       bool isUnmaintained() const
00283       { return availableEmpty(); }
00284 
00285       bool multiversionInstall() const
00286       { return theObj().satSolvable().multiversionInstall(); }
00287 
00288       bool pickInstall( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r );
00289 
00290       bool pickDelete( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r );
00291 
00292       Status pickStatus( const PoolItem & pi_r ) const;
00293 
00294       bool setPickStatus( const PoolItem & pi_r, Status state_r, ResStatus::TransactByValue causer_r );
00295 
00297 
00298       bool isUndetermined() const
00299       {
00300         PoolItem cand( candidateObj() );
00301         return ! cand || cand.isUndetermined();
00302       }
00303       bool isRelevant() const
00304       {
00305         PoolItem cand( candidateObj() );
00306         return cand && cand.isRelevant();
00307       }
00308       bool isSatisfied() const
00309        {
00310         PoolItem cand( candidateObj() );
00311         return cand && cand.isSatisfied();
00312       }
00313       bool isBroken() const
00314       {
00315         PoolItem cand( candidateObj() );
00316         return cand && cand.isBroken();
00317       }
00318 
00320       ResStatus::TransactByValue modifiedBy() const;
00321 
00323       bool hasLicenceConfirmed() const
00324       { return candidateObj() && candidateObj().status().isLicenceConfirmed(); }
00325 
00327       void setLicenceConfirmed( bool val_r )
00328       { if ( candidateObj() ) candidateObj().status().setLicenceConfirmed( val_r ); }
00329 
00330     private:
00331       PoolItem transactingInstalled() const
00332       {
00333         for_( it, installedBegin(), installedEnd() )
00334           {
00335             if ( (*it).status().transacts() )
00336               return (*it);
00337           }
00338         return PoolItem();
00339       }
00340 
00341       PoolItem transactingCandidate() const
00342       {
00343         for_( it, availableBegin(), availableEnd() )
00344           {
00345             if ( (*it).status().transacts() )
00346               return (*it);
00347           }
00348         return PoolItem();
00349       }
00350 
00351       PoolItem defaultCandidate() const
00352       {
00353         if ( ! ( multiversionInstall() || installedEmpty() ) )
00354         {
00355           // prefer the installed objects arch and vendor
00356           bool solver_allowVendorChange( ZConfig::instance().solver_allowVendorChange() );
00357           for ( installed_const_iterator iit = installedBegin();
00358                 iit != installedEnd(); ++iit )
00359           {
00360             PoolItem sameArch; // in case there's no same vendor at least stay with same arch.
00361             for ( available_const_iterator it = availableBegin();
00362                   it != availableEnd(); ++it )
00363             {
00364               // 'same arch' includes allowed changes to/from noarch.
00365               if ( (*iit)->arch() == (*it)->arch() || (*iit)->arch() == Arch_noarch || (*it)->arch() == Arch_noarch )
00366               {
00367                 if ( ! solver_allowVendorChange )
00368                 {
00369                   if ( VendorAttr::instance().equivalent( (*iit), (*it) ) )
00370                     return *it;
00371                   else if ( ! sameArch ) // remember best same arch in case no same vendor found
00372                      sameArch = *it;
00373                 }
00374                 else // same arch is sufficient
00375                   return *it;
00376               }
00377             }
00378             if ( sameArch )
00379               return sameArch;
00380           }
00381         }
00382         if ( _availableItems.empty() )
00383           return PoolItem();
00384 
00385         return *_availableItems.begin();
00386       }
00387 
00388       bool allCandidatesLocked() const
00389       {
00390         for ( available_const_iterator it = availableBegin();
00391               it != availableEnd(); ++it )
00392           {
00393             if ( ! (*it).status().isLocked() )
00394               return false;
00395           }
00396         return( ! _availableItems.empty() );
00397       }
00398 
00399       bool allInstalledLocked() const
00400       {
00401         for ( installed_const_iterator it = installedBegin();
00402               it != installedEnd(); ++it )
00403           {
00404             if ( ! (*it).status().isLocked() )
00405               return false;
00406           }
00407         return( ! _installedItems.empty() );
00408       }
00409 
00410 
00411     private:
00412       const IdString         _ident;
00413       const ResObject::Kind  _kind;
00414       const std::string      _name;
00415       InstalledItemSet       _installedItems;
00416       AvailableItemSet       _availableItems;
00418       PoolItem               _defaultCandidate;
00420       PoolItem               _candidate;
00422       mutable scoped_ptr<PickList> _picklistPtr;
00423     };
00425 
00427     inline std::ostream & operator<<( std::ostream & str, const Selectable::Impl & obj )
00428     {
00429       return str << '[' << obj.kind() << ']' << obj.name() << ": " << obj.status()
00430                  << " (I " << obj.installedSize() << ")"
00431                  << " (A " << obj.availableSize() << ")"
00432                  << obj.candidateObj();
00433     }
00434 
00436     inline std::ostream & dumpOn( std::ostream & str, const Selectable::Impl & obj )
00437     {
00438       str << '[' << obj.kind() << ']' << obj.name() << ": " << obj.status()
00439           << ( obj.multiversionInstall() ? " (multiversion)" : "") << endl;
00440 
00441       if ( obj.installedEmpty() )
00442         str << "   (I 0) {}" << endl << "   ";
00443       else
00444       {
00445         PoolItem icand( obj.installedObj() );
00446         str << "   (I " << obj.installedSize() << ") {" << endl;
00447         for_( it, obj.installedBegin(), obj.installedEnd() )
00448         {
00449           char t = ' ';
00450           if ( *it == icand )
00451           {
00452             t = 'i';
00453           }
00454           str << " " << t << " " << *it << endl;
00455         }
00456         str << "}  ";
00457       }
00458 
00459       if ( obj.availableEmpty() )
00460       {
00461         str << "(A 0) {}" << endl << "   ";
00462       }
00463       else
00464       {
00465         PoolItem cand( obj.candidateObj() );
00466         PoolItem up( obj.updateCandidateObj() );
00467         str << "(A " << obj.availableSize() << ") {" << endl;
00468         for_( it, obj.availableBegin(), obj.availableEnd() )
00469         {
00470           char t = ' ';
00471           if ( *it == cand )
00472           {
00473             t = *it == up ? 'C' : 'c';
00474           }
00475           else if ( *it == up )
00476           {
00477             t = 'u';
00478           }
00479           str << " " << t << " " << *it << endl;
00480         }
00481         str << "}  ";
00482       }
00483 
00484       if ( obj.picklistEmpty() )
00485       {
00486         str << "(P 0) {}";
00487       }
00488       else
00489       {
00490         PoolItem cand( obj.candidateObj() );
00491         PoolItem up( obj.updateCandidateObj() );
00492         str << "(P " << obj.picklistSize() << ") {" << endl;
00493         for_( it, obj.picklistBegin(), obj.picklistEnd() )
00494         {
00495           char t = ' ';
00496           if ( *it == cand )
00497           {
00498             t = *it == up ? 'C' : 'c';
00499           }
00500           else if ( *it == up )
00501           {
00502             t = 'u';
00503           }
00504           str << " " << t << " " << *it << "\t" << obj.pickStatus( *it ) << endl;
00505         }
00506         str << "}  ";
00507       }
00508 
00509       return str;
00510     }
00512   } // namespace ui
00515 } // namespace zypp
00517 #endif // ZYPP_UI_SELECTABLEIMPL_H

doxygen