Removed obsolete files and classes.
[platform/upstream/libzypp.git] / zypp / target / store / serialize.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/target/store/serialize.cc
10 *
11 */
12 #include <iostream>
13 #include <ctime>
14 #include <fstream>
15 #include <sstream>
16 #include <streambuf>
17
18 #include <boost/logic/tribool.hpp>
19
20 #include "zypp/base/Logger.h"
21 #include "zypp/Url.h"
22
23 #include "zypp/ResObject.h"
24 #include "zypp/repo/ScriptProvider.h"
25
26 #include "serialize.h"
27
28 #include "xml_escape_parser.hpp"
29
30 using namespace std;
31 ///////////////////////////////////////////////////////////////////
32 namespace zypp
33 { /////////////////////////////////////////////////////////////////
34 namespace storage
35 { /////////////////////////////////////////////////////////////////
36
37 static void copyFileToStream( const Pathname & file_r, std::ostream & out_r )
38 {
39   std::ifstream infile( file_r.c_str() );
40   while (infile.good())
41   {
42     char c = (char)infile.get();
43     if (! infile.eof())
44       out_r << c;
45   }
46   infile.close();
47 }
48
49 static string xml_escape( const string &text )
50 {
51   iobind::parser::xml_escape_parser parser;
52   return parser.escape(text);
53 }
54
55 static string xml_tag_enclose( const string &text, const string &tag, bool escape = false )
56 {
57   string result;
58   result += "<" + tag + ">";
59
60   if ( escape)
61    result += xml_escape(text);
62   else
63    result += text;
64
65   result += "</" + tag + ">";
66   return result;
67 }
68
69 static ostream & operator<<( ostream & str, const boost::tribool obj )
70 {
71   if (obj)
72     return str << "true";
73   else if (!obj)
74     return str << "false";
75   else
76     return str << "indeterminate";
77 }
78
79 /**
80  * helper function that builds
81  * <tagname lang="code">text</tagname>
82  *
83  *
84  */
85 static string translatedTextToXML(const TranslatedText &text, const string &tagname)
86 {
87   set<Locale> locales = text.locales();
88   //ERR << "locale contains " << locales.size() << " translations" << endl;
89   stringstream out;
90   for ( set<Locale>::const_iterator it = locales.begin(); it != locales.end(); ++it)
91   {
92     //ERR << "serializing " << (*it).code() << endl;
93     if ( *it == Locale() )
94       out << "<" << tagname << ">" << xml_escape(text.text(*it)) << "</" << tagname << ">" << endl;
95     else
96       out << "<" << tagname << " lang=\"" << (*it).code() << "\">" << xml_escape(text.text(*it)) << "</" << tagname << ">" << endl;
97   }
98   return out.str();
99 }
100
101 template<class T>
102 string toXML( const T &obj ); //undefined
103
104 template<>
105 string toXML( const Edition &edition )
106 {
107   stringstream out;
108   // sad the yum guys did not acll it edition
109   out << "<version ver=\"" << xml_escape(edition.version()) << "\" rel=\"" << xml_escape(edition.release()) << "\" epoch=\"" << edition.epoch() << "\" />";
110   return out.str();
111 }
112
113 template<>
114 string toXML( const Arch &arch )
115 {
116   stringstream out;
117   out << xml_tag_enclose(xml_escape(arch.asString()), "arch");
118   return out.str();
119 }
120
121 template<>
122 string toXML( const Capability &cap )
123 {
124 #warning FIX WRITING AND READING CAPABILITY (incl old format)
125   stringstream out;
126   //CapFactory factory;
127   //out << "<capability kind=\"" << cap.refers() << "\" >" <<  xml_escape(factory.encode(cap)) << "</capability>" << endl;
128   out << "<capability>" <<  cap << "</capability>" << endl; // wrong !
129
130   return out.str();
131 }
132
133 template<>
134 string toXML( const Capabilities &caps )
135 {
136   stringstream out;
137   Capabilities::const_iterator it = caps.begin();
138   for ( ; it != caps.end(); ++it)
139   {
140     out << toXML((*it));
141   }
142   return out.str();
143 }
144
145 template<>
146 string toXML( const Dependencies &dep )
147 {
148   stringstream out;
149   if ( dep[Dep::PROVIDES].size() > 0 )
150     out << "    " << xml_tag_enclose(toXML(dep[Dep::PROVIDES]), "provides") << endl;
151   if ( dep[Dep::PREREQUIRES].size() > 0 )
152     out << "    " << xml_tag_enclose(toXML(dep[Dep::PREREQUIRES]), "prerequires") << endl;
153   if ( dep[Dep::CONFLICTS].size() > 0 )
154     out << "    " << xml_tag_enclose(toXML(dep[Dep::CONFLICTS]), "conflicts") << endl;
155   if ( dep[Dep::OBSOLETES].size() > 0 )
156     out << "    " << xml_tag_enclose(toXML(dep[Dep::OBSOLETES]), "obsoletes") << endl;
157   // why the YUM tag is freshen without s????
158   if ( dep[Dep::FRESHENS].size() > 0 )
159     out << "    " << xml_tag_enclose(toXML(dep[Dep::FRESHENS]), "freshens") << endl;
160   if ( dep[Dep::REQUIRES].size() > 0 )
161     out << "    " << xml_tag_enclose(toXML(dep[Dep::REQUIRES]), "requires") << endl;
162   if ( dep[Dep::RECOMMENDS].size() > 0 )
163     out << "    " << xml_tag_enclose(toXML(dep[Dep::RECOMMENDS]), "recommends") << endl;
164   if ( dep[Dep::ENHANCES].size() > 0 )
165     out << "    " << xml_tag_enclose(toXML(dep[Dep::ENHANCES]), "enhances") << endl;
166   if ( dep[Dep::SUPPLEMENTS].size() > 0 )
167     out << "    " << xml_tag_enclose(toXML(dep[Dep::SUPPLEMENTS]), "supplements") << endl;
168   if ( dep[Dep::SUGGESTS].size() > 0 )
169     out << "    " << xml_tag_enclose(toXML(dep[Dep::SUGGESTS]), "suggests") << endl;
170   return out.str();
171
172 }
173
174 template<>
175 string toXML( const Resolvable::constPtr &obj )
176 {
177   stringstream out;
178
179   out << "  <name>" << xml_escape(obj->name()) << "</name>" << endl;
180   // is this shared? uh
181   out << "  " << toXML(obj->edition()) << endl;
182   out << "  " << toXML(obj->arch()) << endl;
183   out << "  " << toXML(obj->deps()) << endl;
184   return out.str();
185 }
186
187 template<>
188 string toXML( const ResObject::constPtr &obj )
189 {
190   stringstream out;
191 #warning FIX WRITING AND READING TRANSLATED TEXTS
192   // access implementation
193   //detail::ResImplTraits<ResObject::Impl>::constPtr pipp( detail::ImplConnect::resimpl( obj ) );
194   //out << translatedTextToXML(pipp->summary(), "summary");
195   //out << translatedTextToXML(pipp->description(), "description");
196
197   //out << translatedTextToXML(pipp->insnotify(), "install-notify");
198   //out << translatedTextToXML(pipp->delnotify(), "delete-notify");
199   //out << translatedTextToXML(pipp->licenseToConfirm(), "license-to-confirm");
200   out << "  <vendor>" << xml_escape(obj->vendor()) << "</vendor>" << endl;
201   out << "  <size>" << static_cast<ByteCount::SizeType>(obj->size()) << "</size>" << endl;
202   out << "  <archive-size>" << static_cast<ByteCount::SizeType>(obj->downloadSize()) << "</archive-size>" << endl;
203   out << "  <install-only>" << ( obj->installOnly() ? "true" : "false" ) << "</install-only>" << endl;
204   out << "  <build-time>" << obj->buildtime().asSeconds()  << "</build-time>" << endl;
205   // we assume we serialize on storeObject, set install time to NOW
206   out << "  <install-time>" << Date::now().asSeconds() << "</install-time>" << endl;
207
208   return out.str();
209 }
210
211 template<>
212 string toXML( const Package::constPtr &obj )
213 {
214   stringstream out;
215   out << "<package>" << endl;
216   // reuse Resolvable information serialize function
217   out << toXML(static_cast<Resolvable::constPtr>(obj));
218   out << toXML(static_cast<ResObject::constPtr>(obj));
219   out << "</package>" << endl;
220   return out.str();
221 }
222
223 template<>
224 string toXML( const Script::constPtr &obj )
225 {
226   stringstream out;
227   out << "<script>" << endl;
228   // reuse Resolvable information serialize function
229   out << toXML(static_cast<Resolvable::constPtr>(obj));
230   out << toXML(static_cast<ResObject::constPtr>(obj));
231
232   repo::RepoMediaAccess access;
233   repo::ScriptProvider prov( access );
234
235   out << "  <do>" << endl;
236   out << "  <![CDATA[" << endl;
237   copyFileToStream( prov.provideDoScript( obj ), out );
238   out << "  ]]>" << endl;
239   out << "  </do>" << endl;
240
241   if ( obj->undoAvailable() )
242   {
243     out << "  <undo>" << endl;
244     out << "  <![CDATA[" << endl;
245     copyFileToStream( prov.provideUndoScript( obj ), out );
246     out << "  ]]>" << endl;
247     out << "  </undo>" << endl;
248
249   }
250   out << "</script>" << endl;
251   return out.str();
252 }
253
254 template<>
255 string toXML( const Message::constPtr &obj )
256 {
257   stringstream out;
258   out << "<message>" << endl;
259   // reuse Resolvable information serialize function
260   out << toXML(static_cast<Resolvable::constPtr>(obj));
261   out << toXML(static_cast<ResObject::constPtr>(obj));
262   out << "  <text>" << xml_escape(obj->text().text()) << "</text>" << endl;
263   out << "</message>" << endl;
264   return out.str();
265 }
266
267 template<>
268 string toXML( const Language::constPtr &obj )
269 {
270   stringstream out;
271   out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
272   out << "<language version=\"" << SERIALIZER_VERSION << "\" xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << endl;
273   out << toXML(static_cast<Resolvable::constPtr>(obj)) << endl;
274   out << toXML(static_cast<ResObject::constPtr>(obj));
275   out << "</language>" << endl;
276   return out.str();
277 }
278
279
280 template<>
281 string toXML( const Selection::constPtr &obj )
282 {
283   stringstream out;
284   out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
285   out << "<pattern version=\"" << SERIALIZER_VERSION << "\" xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << endl;
286
287   out << toXML(static_cast<Resolvable::constPtr>(obj)) << endl;
288   out << toXML(static_cast<ResObject::constPtr>(obj));
289
290   //out << "  <default>" << (obj->isDefault() ? "true" : "false" ) << "</default>" << endl;
291   out << "  <uservisible>" << (obj->visible() ? "true" : "false" ) << "</uservisible>" << endl;
292   out << "  <category>" << xml_escape(obj->category()) << "</category>" << endl;
293   out << "  <icon></icon>" << endl;
294   out << "</pattern>" << endl;
295   return out.str();
296 }
297
298 template<>
299 string toXML( const Atom::constPtr &obj )
300 {
301   stringstream out;
302   out << "<atom>" << endl;
303   out << toXML(static_cast<Resolvable::constPtr>(obj)) << endl;
304   out << toXML(static_cast<ResObject::constPtr>(obj));
305   out << "</atom>" << endl;
306   return out.str();
307 }
308
309 template<>
310 string toXML( const Pattern::constPtr &obj )
311 {
312   stringstream out;
313   out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
314   out << "<pattern version=\"" << SERIALIZER_VERSION << "\" xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << endl;
315
316   out << toXML(static_cast<Resolvable::constPtr>(obj)) << endl;
317   out << toXML(static_cast<ResObject::constPtr>(obj));
318
319   out << "  <default>" << (obj->isDefault() ? "true" : "false" ) << "</default>" << endl;
320   out << "  <uservisible>" << (obj->userVisible() ? "true" : "false" ) << "</uservisible>" << endl;
321   out << "  <category>" << xml_escape(obj->category()) << "</category>" << endl;
322   out << "  <icon>" << xml_escape(obj->icon().asString()) << "</icon>" << endl;
323   out << "  <script>" << xml_escape(obj->script().asString()) << "</script>" << endl;
324   out << "</pattern>" << endl;
325   return out.str();
326 }
327
328 template<>
329 string toXML( const Product::constPtr &obj )
330 {
331   stringstream out;
332   out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
333   out << "<product version=\"" << SERIALIZER_VERSION << "\" xmlns=\"http://www.novell.com/metadata/zypp/xml-store\" type=\"" << xml_escape(obj->type()) << "\">" << endl;
334   out << toXML(static_cast<Resolvable::constPtr>(obj)) << endl;
335 #warning "FIXME description and displayname of products"
336
337   out << toXML(static_cast<ResObject::constPtr>(obj));
338
339 #warning FIX WRITING AND READING TRANSLATED TEXTS
340   // access implementation
341 //   detail::ResImplTraits<Product::Impl>::constPtr pipp( detail::ImplConnect::resimpl( obj ) );
342 //   out << translatedTextToXML(pipp->shortName(), "shortname");
343
344   out << "  <distribution-name>" << xml_escape(obj->distributionName()) << "</distribution-name>" << endl;
345   out << "  <distribution-edition>" << xml_escape(obj->distributionEdition().asString()) << "</distribution-edition>" << endl;
346   out << "  <source>" << xml_escape(obj->repository().info().alias()) << "</source>" << endl;
347   out << "  <release-notes-url>" << xml_escape(obj->releaseNotesUrl().asString()) << "</release-notes-url>" << endl;
348
349   out << "  <update-urls>" << endl;
350   list<Url> updateUrls = obj->updateUrls();
351   for ( list<Url>::const_iterator it = updateUrls.begin(); it != updateUrls.end(); ++it)
352   {
353     out << "    <update-url>" << xml_escape(it->asString()) << "</update-url>" << endl;
354   }
355   out << "  </update-urls>" << endl;
356
357   out << "  <extra-urls>" << endl;
358   list<Url> extraUrls = obj->extraUrls();
359   for ( list<Url>::const_iterator it = extraUrls.begin(); it != extraUrls.end(); ++it)
360   {
361     out << "    <extra-url>" << xml_escape(it->asString()) << "</extra-url>" << endl;
362   }
363   out << "  </extra-urls>" << endl;
364
365   out << "  <optional-urls>" << endl;
366   list<Url> optionalUrls = obj->optionalUrls();
367   for ( list<Url>::const_iterator it = optionalUrls.begin(); it != optionalUrls.end(); ++it)
368   {
369     out << "    <optional-url>" << xml_escape(it->asString()) << "</optional-url>" << endl;
370   }
371   out << "  </optional-urls>" << endl;
372
373   out << "  <product-flags>" << endl;
374   list<string> flags = obj->flags();
375   for ( list<string>::const_iterator it = flags.begin(); it != flags.end(); ++it)
376   {
377     out << "    <product-flag>" << xml_escape(*it) << "</product-flag>" << endl;
378   }
379   out << "  </product-flags>" << endl;
380
381   out << "</product>" << endl;
382
383   return out.str();
384 }
385
386
387 string castedToXML( const Resolvable::constPtr &resolvable )
388 {
389   stringstream out;
390   if ( isKind<Package>(resolvable) )
391      out << toXML(asKind<const Package>(resolvable)) << endl;
392   if ( isKind<Patch>(resolvable) )
393      out << toXML(asKind<const Patch>(resolvable)) << endl;
394   if ( isKind<Message>(resolvable) )
395      out << toXML(asKind<const Message>(resolvable)) << endl;
396   if ( isKind<Script>(resolvable) )
397      out << toXML(asKind<const Script>(resolvable)) << endl;
398   if ( isKind<Atom>(resolvable) )
399      out << toXML(asKind<const Atom>(resolvable)) << endl;
400   if ( isKind<Product>(resolvable) )
401      out << toXML(asKind<const Product>(resolvable)) << endl;
402   if ( isKind<Pattern>(resolvable) )
403      out << toXML(asKind<const Pattern>(resolvable)) << endl;
404   if ( isKind<Selection>(resolvable) )
405      out << toXML(asKind<const Selection>(resolvable)) << endl;
406   if ( isKind<Language>(resolvable) )
407     out << toXML(asKind<const Language>(resolvable)) << endl;
408   return out.str();
409 }
410
411 string resolvableTypeToString( const Resolvable::constPtr &resolvable, bool plural )
412 {
413   return resolvableKindToString(resolvable->kind(), plural);
414 }
415
416 string resolvableKindToString( const Resolvable::Kind &kind, bool plural)
417 {
418   string k = kind.asString();
419   if (k.substr(k.size() - 2, 2) == "ch")
420     return k + (plural?"es":"");
421   else
422     return k + (plural?"s":"");
423 }
424
425 template<>
426 string toXML( const Patch::constPtr &obj )
427 {
428   stringstream out;
429   out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
430   out << "<patch version=\"" << SERIALIZER_VERSION << "\" xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << endl;
431
432   // reuse Resolvable information serialize function
433   out << toXML(static_cast<Resolvable::constPtr>(obj));
434   out << toXML(static_cast<ResObject::constPtr>(obj));
435
436   out << "<id>" << xml_escape(obj->id()) << "</id>" << endl;
437   out << "<timestamp>" << obj->timestamp().asSeconds() << "</timestamp>" << endl;
438
439   out << "<category>" << obj->category() << "</category>" << endl;
440   out << "<affects-package-manager>" << ( obj->affects_pkg_manager() ? "true" : "false" ) << "</affects-package-manager>" << endl;
441   out << "<reboot-needed>" << ( obj->reboot_needed() ? "true" : "false" ) << "</reboot-needed>" << endl;
442
443   Patch::AtomList at = obj->atoms();
444   out << "  <atoms>" << endl;
445   for (Patch::AtomList::iterator it = at.begin(); it != at.end(); it++)
446   {
447     Resolvable::Ptr one_atom = *it;
448     out << castedToXML(one_atom) << endl;
449   }
450   out << "  </atoms>" << endl;
451   out << "</patch>" << endl;
452   return out.str();
453 }
454
455 /////////////////////////////////////////////////////////////////
456 } // namespace storage
457         ///////////////////////////////////////////////////////////////////
458         /////////////////////////////////////////////////////////////////
459 } // namespace zypp
460 ///////////////////////////////////////////////////////////////////