Imported Upstream version 15.21.0
[platform/upstream/libzypp.git] / zypp / SysContent.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/SysContent.cc
10  *
11 */
12 #include <iostream>
13 #include "zypp/base/Logger.h"
14
15 #include "zypp/SysContent.h"
16 #include "zypp/parser/xml/Reader.h"
17 #include "zypp/parser/xml/ParseDef.h"
18 #include "zypp/parser/xml/ParseDefConsume.h"
19
20 using std::endl;
21
22 ///////////////////////////////////////////////////////////////////
23 namespace zypp
24 { /////////////////////////////////////////////////////////////////
25   ///////////////////////////////////////////////////////////////////
26   namespace syscontent
27   { /////////////////////////////////////////////////////////////////
28
29     ///////////////////////////////////////////////////////////////////
30     namespace // Writer helpers
31     { /////////////////////////////////////////////////////////////////
32
33       /** writeXml helper.
34        * \return <tt>tag="value"</tt> if value not empty, else
35        * an empty string.
36       */
37       inline std::string attrIf( const std::string & tag_r,
38                                  const std::string & value_r )
39       {
40         std::string ret;
41         if ( ! value_r.empty() )
42           {
43             ret += " ";
44             ret += tag_r;
45             ret += "=\"";
46             ret += value_r;
47             ret += "\"";
48           }
49         return ret;
50       }
51
52       /////////////////////////////////////////////////////////////////
53     } // namespace
54     ///////////////////////////////////////////////////////////////////
55
56     ///////////////////////////////////////////////////////////////////
57     //
58     //  CLASS NAME : Writer::Impl
59     //
60     /** \see Writer */
61     class Writer::Impl
62     {
63     public:
64       std::ostream & writeXml( std::ostream & str ) const;
65
66     public:
67       std::string _name;
68       Edition     _edition;
69       std::string _description;
70       StorageT    _onsys;
71
72     public:
73       /** Offer default Impl. */
74       static shared_ptr<Impl> nullimpl()
75       {
76         static shared_ptr<Impl> _nullimpl( new Impl );
77         return _nullimpl;
78       }
79
80     private:
81       friend Impl * rwcowClone<Impl>( const Impl * rhs );
82       /** clone for RWCOW_pointer */
83       Impl * clone() const
84       { return new Impl( *this ); }
85     };
86     ///////////////////////////////////////////////////////////////////
87
88     ///////////////////////////////////////////////////////////////////
89     //
90     //  METHOD NAME : Writer::Impl::writeXml
91     //  METHOD TYPE : std::ostream &
92     //
93     std::ostream & Writer::Impl::writeXml( std::ostream & str ) const
94     {
95       // intro
96       str << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
97       str << "<syscontent>\n";
98       // ident data
99       str << "  <ident>\n";
100       str << "    <name>" << _name << "</name>\n";
101       str << "    <version"
102           << attrIf( "epoch", str::numstring(_edition.epoch()) )
103           << attrIf( "ver",   _edition.version() )
104           << attrIf( "rel",   _edition.release() )
105           << "/>\n";
106       str << "    <description>" << _description << "</description>\n";
107       str << "    <created>" << Date::now().asSeconds() << "</created>\n";
108       str << "  </ident>\n";
109       // ResObjects
110       str << "  <onsys>\n";
111       for ( iterator it = _onsys.begin(); it != _onsys.end(); ++it )
112         {
113           str << "    <entry"
114               << attrIf( "kind",  (*it)->kind().asString() )
115               << attrIf( "name",  (*it)->name() )
116               << attrIf( "epoch", str::numstring((*it)->edition().epoch()) )
117               << attrIf( "ver",   (*it)->edition().version() )
118               << attrIf( "rel",   (*it)->edition().release() )
119               << attrIf( "arch",  (*it)->arch().asString() )
120               << "/>\n";
121         }
122       str << "  </onsys>\n";
123       // extro
124       str << "</syscontent>" << endl;
125       return str;
126     };
127
128     ///////////////////////////////////////////////////////////////////
129     //
130     //  CLASS NAME : Writer
131     //
132     ///////////////////////////////////////////////////////////////////
133
134     Writer::Writer()
135     : _pimpl( Impl::nullimpl() )
136     {}
137
138     const std::string & Writer::name() const
139     { return _pimpl->_name; }
140
141     Writer & Writer::name( const std::string & val_r )
142     { _pimpl->_name = val_r; return *this; }
143
144     const Edition & Writer::edition() const
145     { return _pimpl->_edition; }
146
147     Writer & Writer::edition( const Edition & val_r )
148     { _pimpl->_edition = val_r; return *this; }
149
150     const std::string & Writer::description() const
151     { return _pimpl->_description; }
152
153     Writer & Writer::description( const std::string & val_r )
154     { _pimpl->_description = val_r; return *this; }
155
156     void Writer::addInstalled( const PoolItem & obj_r )
157     {
158       if ( obj_r.status().isInstalled() )
159         {
160           _pimpl->_onsys.insert( obj_r.resolvable() );
161         }
162     }
163
164     void Writer::addIf( const PoolItem & obj_r )
165     {
166       if ( obj_r.status().isInstalled() != obj_r.status().transacts()
167            && ! ( obj_r.status().transacts() && obj_r.status().isBySolver() ) )
168         {
169           _pimpl->_onsys.insert( obj_r.resolvable() );
170         }
171     }
172
173     void Writer::add( const ResObject::constPtr & obj_r )
174     { _pimpl->_onsys.insert( obj_r ); }
175
176     bool Writer::empty() const
177     { return _pimpl->_onsys.empty(); }
178
179     Writer::size_type Writer::size() const
180     { return _pimpl->_onsys.size(); }
181
182     Writer::const_iterator Writer::begin() const
183     { return _pimpl->_onsys.begin(); }
184
185     Writer::const_iterator Writer::end() const
186     { return _pimpl->_onsys.end(); }
187
188     std::ostream & Writer::writeXml( std::ostream & str ) const
189     { return _pimpl->writeXml( str ); }
190
191     ///////////////////////////////////////////////////////////////////
192     //
193     //  CLASS NAME : Reader::Entry::Impl
194     //
195     class Reader::Entry::Impl
196     {
197     public:
198       std::string _kind;
199       std::string _name;
200       Edition     _edition;
201       Arch        _arch;
202     };
203     ///////////////////////////////////////////////////////////////////
204
205     ///////////////////////////////////////////////////////////////////
206     //
207     //  CLASS NAME : Reader::Entry
208     //
209     ///////////////////////////////////////////////////////////////////
210
211     Reader::Entry::Entry()
212     : _pimpl( new Impl )
213     {}
214
215     Reader::Entry::Entry( const shared_ptr<Impl> & pimpl_r )
216     : _pimpl( pimpl_r )
217     {}
218
219     const std::string & Reader::Entry::kind() const
220     { return _pimpl->_kind; }
221
222     const std::string & Reader::Entry::name() const
223     { return _pimpl->_name; }
224
225     const Edition & Reader::Entry::edition() const
226     { return _pimpl->_edition; }
227
228     const Arch & Reader::Entry::arch() const
229     { return _pimpl->_arch; }
230
231     ///////////////////////////////////////////////////////////////////
232     //
233     //  CLASS NAME : Reader::Impl
234     //
235     /** \see Reader */
236     class Reader::Impl
237     {
238     public:
239       Impl()
240       {}
241
242       Impl( std::istream & input_r );
243
244     public:
245       std::string _name;
246       Edition     _edition;
247       std::string _description;
248       Date        _created;
249
250       std::list<Entry> _content;
251
252     public:
253       /** Offer default Impl. */
254       static shared_ptr<Impl> nullimpl()
255       {
256         static shared_ptr<Impl> _nullimpl( new Impl );
257         return _nullimpl;
258       }
259
260     private:
261       friend Impl * rwcowClone<Impl>( const Impl * rhs );
262       /** clone for RWCOW_pointer */
263       Impl * clone() const
264       { return new Impl( *this ); }
265     };
266     ///////////////////////////////////////////////////////////////////
267
268     ///////////////////////////////////////////////////////////////////
269     namespace // Reader helpers
270     { /////////////////////////////////////////////////////////////////
271
272       using namespace xml;
273
274       /** Sycontent xml node structure. */
275       struct SycontentNode : public ParseDef
276       {
277         SycontentNode( Mode mode_r )
278         : ParseDef( "syscontent", mode_r )
279         {
280           (*this)("ident",       OPTIONAL)
281                  ("onsys",       OPTIONAL)
282                  ;
283
284           (*this)["ident"]
285                  ("name",        OPTIONAL)
286                  ("version",     OPTIONAL)
287                  ("description", OPTIONAL)
288                  ("created",     OPTIONAL)
289                  ;
290
291           (*this)["onsys"]
292                  ("entry",       MULTIPLE_OPTIONAL)
293                  ;
294         }
295       };
296
297       /** Parse Edition from ver/rel/eopch attributes. */
298       struct ConsumeEdition : public ParseDefConsume
299       {
300         ConsumeEdition( Edition & value_r )
301         : _value( & value_r )
302         {}
303
304         virtual void start( const Node & node_r )
305         {
306           *_value = Edition( node_r.getAttribute("ver").asString(),
307                              node_r.getAttribute("rel").asString(),
308                              node_r.getAttribute("epoch").asString() );
309         }
310
311         Edition *_value;
312       };
313
314       /** Parse std::string from node value. */
315       struct ConsumeString : public ParseDefConsume
316       {
317         ConsumeString( std::string & value_r )
318         : _value( & value_r )
319         {}
320
321         virtual void text( const Node & node_r )
322         {
323           *_value = node_r.value().asString();
324         }
325
326         std::string *_value;
327       };
328
329       /** Parse Date from node value. */
330       struct ConsumeDate : public ParseDefConsume
331       {
332         ConsumeDate( Date & value_r )
333         : _value( & value_r )
334         {}
335
336         virtual void text( const Node & node_r )
337         {
338           *_value = Date(node_r.value().asString());
339         }
340
341         Date *_value;
342       };
343
344       /** Parse entry list. */
345       struct ConsumeEntries : public ParseDefConsume
346       {
347         ConsumeEntries( std::list<Reader::Entry> & value_r )
348         : _value( & value_r )
349         {}
350
351         virtual void start( const Node & node_r )
352         {
353           shared_ptr<Reader::Entry::Impl> centry( new Reader::Entry::Impl );
354
355           centry->_kind = node_r.getAttribute("kind").asString();
356           centry->_name = node_r.getAttribute("name").asString();
357           centry->_edition = Edition( node_r.getAttribute("ver").asString(),
358                                       node_r.getAttribute("rel").asString(),
359                                       node_r.getAttribute("epoch").asString() );
360           centry->_arch = Arch( node_r.getAttribute("arch").asString() );
361
362           _value->push_back( Reader::Entry( centry ) );
363         }
364
365         std::list<Reader::Entry> *_value;
366       };
367
368       /////////////////////////////////////////////////////////////////
369     } // namespace
370     ///////////////////////////////////////////////////////////////////
371
372     ///////////////////////////////////////////////////////////////////
373     //
374     //  METHOD NAME : Reader::Impl::Impl
375     //  METHOD TYPE : Constructor
376     //
377     Reader::Impl::Impl( std::istream & input_r )
378     {
379       xml::Reader reader( input_r );
380       SycontentNode rootNode( xml::ParseDef::MANDTAORY );
381
382       rootNode["ident"]["name"].setConsumer
383       ( new ConsumeString( _name ) );
384
385       rootNode["ident"]["version"].setConsumer
386       ( new ConsumeEdition( _edition ) );
387
388       rootNode["ident"]["description"].setConsumer
389       ( new ConsumeString( _description ) );
390
391       rootNode["ident"]["created"].setConsumer
392       ( new ConsumeDate( _created ) );
393
394       rootNode["onsys"]["entry"].setConsumer
395       ( new ConsumeEntries( _content ) );
396
397       // parse
398       rootNode.take( reader );
399     }
400
401     ///////////////////////////////////////////////////////////////////
402     //
403     //  CLASS NAME : Reader
404     //
405     ///////////////////////////////////////////////////////////////////
406
407     Reader::Reader()
408     : _pimpl( Impl::nullimpl() )
409     {}
410
411     Reader::Reader( std::istream & input_r )
412     : _pimpl( new Impl( input_r ) )
413     {}
414
415     const std::string & Reader::name() const
416     { return _pimpl->_name; }
417
418     const Edition & Reader::edition() const
419     { return _pimpl->_edition; }
420
421     const std::string & Reader::description() const
422     { return _pimpl->_description; }
423
424     const Date & Reader::ctime() const
425     { return _pimpl->_created; }
426
427     bool Reader::empty() const
428     { return _pimpl->_content.empty(); }
429
430     Reader::size_type Reader::size() const
431     { return _pimpl->_content.size(); }
432
433     Reader::const_iterator Reader::begin() const
434     { return _pimpl->_content.begin(); }
435
436     Reader::const_iterator Reader::end() const
437     { return _pimpl->_content.end(); }
438
439     /******************************************************************
440      **
441      ** FUNCTION NAME : operator<<
442      ** FUNCTION TYPE : inline std::ostream &
443     */
444     std::ostream & operator<<( std::ostream & str, const Reader & obj )
445     {
446       return str << "syscontent(" << obj.name() << "-" << obj.edition()
447                  << ", " << obj.size() << " entries"
448                  << ",  created " << obj.ctime()
449                  << ")";
450     }
451
452     /////////////////////////////////////////////////////////////////
453   } // namespace syscontent
454   ///////////////////////////////////////////////////////////////////
455   /////////////////////////////////////////////////////////////////
456 } // namespace zypp
457 ///////////////////////////////////////////////////////////////////