Merge branch 'local_services' of gitorious.org:~duncan/opensuse/duncans-libzypp
[platform/upstream/libzypp.git] / zypp / parser / RepoindexFileReader.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/parser/RepoindexFileReader.cc
10  * Implementation of repoindex.xml file reader.
11  */
12 #include <iostream>
13
14 #include "zypp/base/String.h"
15 #include "zypp/base/Logger.h"
16 #include "zypp/base/Gettext.h"
17 #include "zypp/Pathname.h"
18
19 #include "zypp/parser/xml/Reader.h"
20 #include "zypp/parser/ParseException.h"
21
22 #include "zypp/RepoInfo.h"
23
24 #include "zypp/parser/RepoindexFileReader.h"
25
26
27 #undef ZYPP_BASE_LOGGER_LOGGROUP
28 #define ZYPP_BASE_LOGGER_LOGGROUP "parser"
29
30 using namespace std;
31 using namespace zypp::xml;
32
33 namespace zypp
34 {
35   namespace parser
36   {
37
38
39   ///////////////////////////////////////////////////////////////////////
40   //
41   //  CLASS NAME : RepoindexFileReader::Impl
42   //
43   class RepoindexFileReader::Impl : private base::NonCopyable
44   {
45   public:
46     /**
47      * CTOR
48      *
49      * \see RepoindexFileReader::RepoindexFileReader(Pathname,ProcessResource)
50      */
51     Impl(const Pathname &repoindex_file, const ProcessResource & callback);
52
53     /**
54      * Callback provided to the XML parser.
55      */
56     bool consumeNode( Reader & reader_r );
57
58
59   private:
60     /** Function for processing collected data. Passed-in through constructor. */
61     ProcessResource _callback;
62     string _target_distro;
63   };
64   ///////////////////////////////////////////////////////////////////////
65
66   RepoindexFileReader::Impl::Impl(
67       const Pathname &repoindex_file, const ProcessResource & callback)
68     : _callback(callback)
69   {
70     Reader reader( repoindex_file );
71     MIL << "Reading " << repoindex_file << endl;
72     reader.foreachNode( bind( &RepoindexFileReader::Impl::consumeNode, this, _1 ) );
73   }
74
75   // --------------------------------------------------------------------------
76
77   /*
78    * xpath and multiplicity of processed nodes are included in the code
79    * for convenience:
80    *
81    * // xpath: <xpath> (?|*|+)
82    *
83    * if multiplicity is ommited, then the node has multiplicity 'one'.
84    */
85
86   // --------------------------------------------------------------------------
87
88   bool RepoindexFileReader::Impl::consumeNode( Reader & reader_r )
89   {
90     if ( reader_r->nodeType() == XML_READER_TYPE_ELEMENT )
91     {
92       // xpath: /repoindex
93       if ( reader_r->name() == "repoindex" )
94       {
95         return true;
96       }
97
98       // xpath: /repoindex/data (+)
99       if ( reader_r->name() == "repo" )
100       {
101         XmlString s;
102
103         RepoInfo info;
104
105         // url and/or path
106         string url_s;
107         s = reader_r->getAttribute("url");
108         if (s.get())
109           url_s = s.asString();
110         string path_s;
111         s = reader_r->getAttribute("path");
112         if (s.get())
113           path_s = s.asString();
114
115         if (url_s.empty() && path_s.empty())
116           throw ParseException(str::form(_("One or both of '%s' or '%s' attributes is required."), "url", "path"));
117         //! \todo FIXME this hardcodes the "/repo/" fragment - should not be if we want it to be usable by others!
118         else if (url_s.empty())
119           info.setPath(Pathname(string("/repo/") + path_s));
120         else if (path_s.empty())
121           info.setBaseUrl(Url(url_s));
122         else
123           info.setBaseUrl(Url(url_s + "/repo/" + path_s));
124
125         // required alias
126         s = reader_r->getAttribute("alias");
127         if (!s.get())
128           throw ParseException(str::form(_("Required attribute '%s' is missing."), "alias"));
129         info.setAlias(s.asString());
130
131         // optional type
132         s = reader_r->getAttribute("type");
133         if (s.get())
134           info.setType(repo::RepoType(s.asString()));
135
136         // optional name
137         s = reader_r->getAttribute("name");
138         if (s.get())
139           info.setName(s.asString());
140
141         // optional targetDistro
142         s = reader_r->getAttribute("distro_target");
143         if (s.get())
144           info.setTargetDistribution(s.asString());
145
146         DBG << info << endl;
147         
148         // Set some defaults that are not contained in the repo information
149         info.setAutorefresh( true );
150         // enabled or disabled is controlled by the
151         // reposToEnable/Disable list
152         info.setEnabled(false);        
153         
154         // ignore the rest
155         _callback(info);
156         return true;
157       }
158     }
159
160     return true;
161   }
162
163
164   ///////////////////////////////////////////////////////////////////
165   //
166   //  CLASS NAME : RepoindexFileReader
167   //
168   ///////////////////////////////////////////////////////////////////
169
170   RepoindexFileReader::RepoindexFileReader(
171       const Pathname & repoindex_file, const ProcessResource & callback)
172     :
173       _pimpl(new Impl(repoindex_file, callback))
174   {}
175
176   RepoindexFileReader::~RepoindexFileReader()
177   {}
178
179
180   } // ns parser
181 } // ns zypp
182
183 // vim: set ts=2 sts=2 sw=2 et ai: