Use gcc-c++ >= 4.5
[platform/upstream/libzypp.git] / zypp / parser / ProductFileReader.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/parser/ProductFileReader.cc
10  *
11 */
12 #include <iostream>
13 #include "zypp/base/Logger.h"
14 #include "zypp/base/Exception.h"
15 #include "zypp/base/Functional.h"
16
17 #include "zypp/PathInfo.h"
18
19 #include "zypp/parser/ProductFileReader.h"
20 #include "zypp/parser/xml/ParseDef.h"
21 #include "zypp/parser/xml/ParseDefConsume.h"
22 #include "zypp/parser/xml/Reader.h"
23
24 using std::endl;
25
26 ///////////////////////////////////////////////////////////////////
27 namespace zypp
28 { /////////////////////////////////////////////////////////////////
29   ///////////////////////////////////////////////////////////////////
30   namespace parser
31   { /////////////////////////////////////////////////////////////////
32
33     /////////////////////////////////////////////////////////////////
34     //
35     // class ProductFileData::Upgrade
36     //
37     /////////////////////////////////////////////////////////////////
38
39     struct ProductFileData::Upgrade::Impl
40     {
41       std::string                 _name;
42       std::string                 _summary;
43       std::string                 _repository;
44       std::string                 _product;
45       DefaultIntegral<bool,false> _notify;
46       std::string                 _status;
47     };
48
49     ProductFileData::Upgrade::Upgrade( Impl * allocated_r )
50       : _pimpl( allocated_r ? allocated_r : new Impl )
51     {}
52
53     std::string ProductFileData::Upgrade::name()       const { return _pimpl->_name; }
54     std::string ProductFileData::Upgrade::summary()    const { return _pimpl->_summary; }
55     std::string ProductFileData::Upgrade::repository() const { return _pimpl->_repository; }
56     std::string ProductFileData::Upgrade::product()    const { return _pimpl->_product; }
57     bool        ProductFileData::Upgrade::notify()     const { return _pimpl->_notify; }
58     std::string ProductFileData::Upgrade::status()     const { return _pimpl->_status; }
59
60     /////////////////////////////////////////////////////////////////
61     //
62     // class ProductFileData
63     //
64     /////////////////////////////////////////////////////////////////
65
66     struct ProductFileData::Impl
67     {
68       IdString    _vendor;
69       IdString    _name;
70       Edition     _edition;
71       Arch        _arch;
72
73       std::string _shortName;
74       std::string _summary;
75
76       std::string _productline;
77       std::string _registerTarget;
78       std::string _registerRelease;
79
80       std::string _updaterepokey;
81
82       Upgrades    _upgrades;
83     };
84
85     ProductFileData::ProductFileData( Impl * allocated_r )
86       : _pimpl( allocated_r ? allocated_r : new Impl )
87     {}
88
89     IdString    ProductFileData::vendor()  const { return _pimpl->_vendor; }
90     IdString    ProductFileData::name()    const { return _pimpl->_name; }
91     Edition     ProductFileData::edition() const { return _pimpl->_edition; }
92     Arch        ProductFileData::arch()    const { return _pimpl->_arch; }
93
94     std::string ProductFileData::shortName()    const { return _pimpl->_shortName; }
95     std::string ProductFileData::summary()      const { return _pimpl->_summary; }
96
97     std::string ProductFileData::productline()     const { return _pimpl->_productline; }
98     std::string ProductFileData::registerTarget()  const { return _pimpl->_registerTarget; }
99     std::string ProductFileData::registerRelease() const { return _pimpl->_registerRelease; }
100
101     std::string ProductFileData::updaterepokey() const { return _pimpl->_updaterepokey; }
102
103     const ProductFileData::Upgrades & ProductFileData::upgrades() const { return _pimpl->_upgrades; }
104
105     std::ostream & operator<<( std::ostream & str, const ProductFileData & obj )
106     {
107       str << str::form( "|product|%s|%s|%s|%s|",
108                         obj.name().c_str(),
109                         obj.edition().c_str(),
110                         obj.arch().c_str(),
111                         obj.vendor().c_str() );
112       if ( ! obj.upgrades().empty() )
113       {
114         for_( it, obj.upgrades().begin(), obj.upgrades().end() )
115           str << endl << "    " << *it;
116       }
117       return str;
118     }
119
120     std::ostream & operator<<( std::ostream & str, const ProductFileData::Upgrade & obj )
121     {
122       str << str::form( "|upgrade|%s|%s|%s|%s|%s|",
123                         obj.name().c_str(),
124                         obj.repository().c_str(),
125                         obj.product().c_str(),
126                         obj.status().c_str(),
127                         (obj.notify() ? "notify" : "noNotify") );
128       return str;
129     }
130     /////////////////////////////////////////////////////////////////
131     //
132     // class ProductFileReader
133     //
134     /////////////////////////////////////////////////////////////////
135
136     struct ProductNode : public xml::ParseDef
137     {
138       ProductNode( ProductFileData::Impl & pdata_r )
139         : ParseDef( "product", MANDTAORY )
140         , _pdata( pdata_r )
141       {
142         (*this)
143             ("vendor",        OPTIONAL,   xml::parseDefAssign( _pdata._vendor ) )
144             ("name",          MANDTAORY,  xml::parseDefAssign( _pdata._name ) )
145             ("version",       MANDTAORY,  xml::parseDefAssign( _version ) )
146             ("release",       MANDTAORY,  xml::parseDefAssign( _release ) )
147             ("arch",          MANDTAORY,  xml::parseDefAssign( _pdata._arch ) )
148             ("shortsummary",  OPTIONAL,   xml::parseDefAssign( _pdata._shortName ) )
149             ("summary",       MULTIPLE_OPTIONAL, xml::parseDefAssign( _ttext )( "lang", _tlocale )
150                                           >>bind( &ProductNode::doneLocalizedDefault, this, _1, boost::ref(_pdata._summary) ))
151             ("productline",   OPTIONAL,   xml::parseDefAssign( _pdata._productline ) )
152             ("register",      OPTIONAL)
153             ("updaterepokey", OPTIONAL,   xml::parseDefAssign( _pdata._updaterepokey ) )
154             ("upgrades",      OPTIONAL)
155             ;
156
157         (*this)["register"]
158             ("target",        OPTIONAL,   xml::parseDefAssign( _pdata._registerTarget ) )
159             ("release",       OPTIONAL,   xml::parseDefAssign( _pdata._registerRelease ) )
160             ;
161
162         (*this)["upgrades"]
163             ("upgrade",       MULTIPLE_OPTIONAL, xml::parseDefAssign()
164                                                  >> bind( &ProductNode::doneUpgrade, this, _1 ))
165             ;
166
167         (*this)["upgrades"]["upgrade"]
168             ("name",          OPTIONAL,   xml::parseDefAssign( _upgrade._name ) )
169             ("summary",       OPTIONAL,   xml::parseDefAssign( _upgrade._summary ) )
170             ("repository",    OPTIONAL,   xml::parseDefAssign( _upgrade._repository ) )
171             ("product",       OPTIONAL,   xml::parseDefAssign( _upgrade._product ) )
172             ("notify",        OPTIONAL,   xml::parseDefAssign( _upgrade._notify ) )
173             ("status",        OPTIONAL,   xml::parseDefAssign( _upgrade._status ) )
174             ;
175
176         // </product> callback to build edition.
177         setConsumer( xml::parseDefAssign() >> bind( &ProductNode::done, this, _1 ) );
178         // xml::ParseDef::_debug = true;
179       }
180
181       /** collect _upgrade */
182       void doneUpgrade( const xml::Node & _node )
183       {
184         ProductFileData::Upgrade cdata( new ProductFileData::Upgrade::Impl( _upgrade ) );
185         _pdata._upgrades.push_back( cdata );
186         _upgrade = ProductFileData::Upgrade::Impl();
187       }
188       /** collect localized data */
189       void doneLocalizedDefault( const xml::Node & _node, std::string & store_r )
190       {
191         // take 1st or default
192         if ( store_r.empty() || _tlocale.empty() )
193           store_r = _ttext;
194       }
195
196       /** finaly */
197       void done( const xml::Node & _node )
198       {
199         _pdata._edition = Edition( _version, _release );
200       }
201
202       private:
203         ProductFileData::Impl & _pdata;
204
205         std::string             _version;
206         std::string             _release;
207
208         std::string             _ttext;
209         std::string             _tlocale;
210
211         ProductFileData::Upgrade::Impl _upgrade;
212     };
213
214     bool ProductFileReader::parse( const InputStream & input_r ) const
215     {
216       MIL << "+++" << input_r << endl;
217       bool ret = true;
218
219       ProductFileData::Impl * pdataImpl = 0;
220       ProductFileData pdata( (pdataImpl = new ProductFileData::Impl) );
221
222       try
223       {
224         xml::Reader reader( input_r );
225         ProductNode rootNode( *pdataImpl );
226         rootNode.take( reader );
227
228       }
229       catch ( const Exception & err )
230       {
231         // parse error
232         ERR << err << endl;
233         ERR << "---" << ret << " - " << input_r << endl;
234         return ret;
235       }
236
237       if ( _consumer )
238       {
239         ret = _consumer( pdata );
240       }
241
242       MIL << "---" << ret << " - " << input_r << endl;
243       return ret;
244     }
245
246     /////////////////////////////////////////////////////////////////
247
248     bool ProductFileReader::scanDir( const Consumer & consumer_r, const Pathname & dir_r )
249     {
250       std::list<Pathname> retlist;
251       int res = filesystem::readdir( retlist, dir_r, /*dots*/false );
252       if ( res != 0 )
253       {
254         WAR << "scanDir " << dir_r << " failed (" << res << ")" << endl;
255         return true;
256       }
257
258       ProductFileReader reader( consumer_r );
259       for_( it, retlist.begin(), retlist.end() )
260       {
261         if ( PathInfo( *it, PathInfo::LSTAT ).isFile() && ! reader.parse( *it ) )
262         {
263           return false; // consumer_r request to stop parsing.
264         }
265       }
266       return true;
267     }
268
269     ProductFileData ProductFileReader::scanFile( const Pathname & file_r )
270     {
271       if ( ! PathInfo( file_r ).isFile() )
272       {
273         WAR << "scanFile " << PathInfo( file_r ) << " is not a file." << endl;
274         return ProductFileData();
275       }
276
277       ProductFileData ret;
278       ProductFileReader reader( functor::getFirst( ret ), file_r );
279       return ret;
280    }
281
282     /////////////////////////////////////////////////////////////////
283   } // namespace parser
284   ///////////////////////////////////////////////////////////////////
285   /////////////////////////////////////////////////////////////////
286 } // namespace zypp
287 ///////////////////////////////////////////////////////////////////