importing my current diff
[platform/upstream/libzypp.git] / zypp / capability / CapabilityImpl.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/capability/CapabilityImpl.cc
10  *
11 */
12 #include <iostream>
13 #include <vector>
14
15 #include "zypp/base/Logger.h"
16 #include "zypp/base/Exception.h"
17 #include "zypp/capability/CapabilityImpl.h"
18 #include "zypp/capability/Capabilities.h"
19
20 using namespace std;
21
22 ///////////////////////////////////////////////////////////////////
23 namespace zypp
24 { /////////////////////////////////////////////////////////////////
25   ///////////////////////////////////////////////////////////////////
26   namespace capability
27   { /////////////////////////////////////////////////////////////////
28     IMPL_PTR_TYPE(CapabilityImpl)
29
30     ///////////////////////////////////////////////////////////////////
31     //
32     //  METHOD NAME : CapabilityImpl::CapabilityImpl
33     //  METHOD TYPE : Ctor
34     //
35     CapabilityImpl::CapabilityImpl( const Resolvable::Kind & refers_r )
36     : _refers( refers_r )
37     {}
38
39     ///////////////////////////////////////////////////////////////////
40     //
41     //  METHOD NAME : CapabilityImpl::capImplOrderLess
42     //  METHOD TYPE : bool
43     //
44     bool CapabilityImpl::capImplOrderLess( const constPtr & rhs ) const
45     {
46       return encode() < rhs->encode();
47     }
48
49     ///////////////////////////////////////////////////////////////////
50     //
51     //  METHOD NAME : CapabilityImpl::capImplOrderLess
52     //  METHOD TYPE : bool
53     //
54     std::ostream & CapabilityImpl::dumpOn( std::ostream & str ) const
55     {
56       return str << '[' << refers() << "] "
57                  << '(' << kind() << ") "
58                  << asString();
59     }
60
61     /** Assert a valid Resolvable::Kind. */
62     static void assertResKind( const Resolvable::Kind & refers_r )
63     {
64       if ( refers_r == Resolvable::Kind() )
65         ZYPP_THROW( Exception("Missing or empty  Resolvable::Kind in Capability") );
66     }
67
68     bool isEditionSpec( Rel op_r, const Edition & edition_r )
69     {
70       switch ( op_r.inSwitch() )
71         {
72         case Rel::ANY_e:
73           if ( edition_r != Edition::noedition )
74             WAR << "Operator " << op_r << " causes Edition "
75             << edition_r << " to be ignored." << endl;
76           return false;
77           break;
78
79         case Rel::NONE_e:
80           ZYPP_THROW( Exception("Operator NONE is not allowed in Capability") );
81           break;
82
83         case Rel::EQ_e:
84         case Rel::NE_e:
85         case Rel::LT_e:
86         case Rel::LE_e:
87         case Rel::GT_e:
88         case Rel::GE_e:
89           return true;
90           break;
91         }
92       // SHOULD NOT GET HERE
93       ZYPP_THROW( Exception("Unknown Operator NONE is not allowed in Capability") );
94       return false; // not reached
95     }
96
97     bool isFileSpec( const std::string & name_r )
98     {
99       return *name_r.c_str() == '/';
100     }
101
102     bool isSplitSpec( const std::string & name_r )
103     {
104       return name_r.find( ":/" ) != std::string::npos;
105     }
106
107     bool isHalSpec( const std::string & name_r )
108     {
109       return name_r.substr(0,4) == "hal(";
110     }
111
112     bool isModaliasSpec( const std::string & name_r )
113     {
114       return name_r.substr(0,9) == "modalias(";
115     }
116
117     bool isFilesystemSpec( const std::string & name_r )
118     {
119       return name_r.substr(0,11) == "filesystem(";
120     }
121
122     CapabilityImpl::Ptr buildFile( const Resolvable::Kind & refers_r,
123                                           const std::string & name_r )
124     {
125       // NullCap check first:
126       if ( name_r.empty() )
127         {
128           // Singleton, so no need to put it into _uset !?
129           return capability::NullCap::instance();
130         }
131
132       assertResKind( refers_r );
133
134       return new capability::FileCap( refers_r, name_r );
135     }
136
137     CapabilityImpl::Ptr buildNamed( const Resolvable::Kind & refers_r,
138                                            const std::string & name_r )
139     {
140       // NullCap check first:
141       if ( name_r.empty() )
142       {
143         // Singleton, so no need to put it into _uset !?
144         return capability::NullCap::instance();
145       }
146
147       assertResKind( refers_r );
148
149       // file:    /absolute/path
150       if ( isFileSpec( name_r ) )
151       {
152         return new capability::FileCap( refers_r, name_r );
153       }
154       if ( isFilesystemSpec( name_r ) )
155       {
156         return buildFilesystem( refers_r, name_r );
157       }
158
159       //split:   name:/absolute/path
160       std::vector<std::string> what;
161       if (str::split( name_r, std::back_inserter(what), ":") >= 2)
162       {
163         return new capability::SplitCap( refers_r, what[0], what[1] );
164       }
165
166       //name:    name
167       return new capability::NamedCap( refers_r, name_r );
168     }
169
170     CapabilityImpl::Ptr buildVersioned( const Resolvable::Kind & refers_r,
171                                                const std::string & name_r,
172                                                Rel op_r,
173                                                const Edition & edition_r )
174     {
175       if ( isEditionSpec( op_r, edition_r ) )
176         {
177           assertResKind( refers_r );
178
179           // build a VersionedCap
180           return new capability::VersionedCap( refers_r, name_r, op_r, edition_r );
181         }
182       //else
183       // build a NamedCap
184
185       return buildNamed( refers_r, name_r );
186     }
187
188     CapabilityImpl::Ptr buildHal( const Resolvable::Kind & refers_r,
189                                          const std::string & name_r,
190                                          Rel op_r,
191                                          const std::string & value_r )
192     {
193       if ( op_r != Rel::ANY )
194         {
195           ZYPP_THROW( Exception("Unsupported kind of Hal Capability '" + op_r.asString() + "'") );
196         }
197
198       //split:   hal(name) [op string]
199       std::vector<std::string> what;
200       if (str::split( name_r, std::back_inserter(what), ")"))
201         {
202           // Hal always refers to 'System' kind of Resolvable.
203           return new capability::HalCap( ResTraits<SystemResObject>::kind,
204                                     what[0].substr(strlen("hal(")) );
205         }
206       // otherwise
207       ZYPP_THROW( Exception("Unsupported kind of Hal Capability '" + name_r + "'") );
208       return NULL; // make gcc happy
209     }
210
211     CapabilityImpl::Ptr buildModalias( const Resolvable::Kind & refers_r,
212                                               const std::string & name_r,
213                                               Rel op_r,
214                                               const std::string & value_r )
215     {
216       if ( op_r != Rel::ANY )
217         {
218           ZYPP_THROW( Exception("Unsupported kind of Modalias Capability  '" + op_r.asString() + "'") );
219         }
220
221       //split:   modalias(name) [op string]
222       std::vector<std::string> what;
223       if (str::split( name_r, std::back_inserter(what), ")"))
224         {
225           // Modalias always refers to 'System' kind of Resolvable
226           return new capability::ModaliasCap( ResTraits<SystemResObject>::kind,
227                                          what[0].substr(strlen("modalias(")));
228         }
229       // otherwise
230       ZYPP_THROW( Exception("Unsupported kind of Modalias Capability'" + name_r + "'") );
231       return NULL; // make gcc happy
232     }
233
234     /******************************************************************
235     **
236     **  FUNCTION NAME : buildFilesystem
237     **  FUNCTION TYPE : CapabilityImpl::Ptr
238     */
239     CapabilityImpl::Ptr buildFilesystem( const Resolvable::Kind & refers_r,
240                                        const std::string & name_r )
241     {
242       //split:   filesystem(name) [op string]
243       std::vector<std::string> what;
244       if (str::split( name_r, std::back_inserter(what), ")"))
245       {
246         // Filesystem always refers to 'System' kind of Resolvable
247         return new capability::FilesystemCap( ResTraits<SystemResObject>::kind,
248                                               what[0].substr(strlen("filesystem(")) );
249       }
250       // otherwise
251       ZYPP_THROW( Exception("Unsupported kind of Filesystem Capability'" + name_r + "'") );
252       return NULL; // make gcc happy
253     }
254
255
256     CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r,
257                                const std::string & strval_r )
258   try
259     {
260       if ( isHalSpec( strval_r ) )
261         {
262           return buildHal( refers_r, strval_r );
263         }
264       if ( isModaliasSpec( strval_r ) )
265         {
266           return buildModalias( refers_r, strval_r );
267         }
268       if ( isFilesystemSpec( strval_r ) )
269         {
270           return buildFilesystem( refers_r, strval_r );
271         }
272       if ( isFileSpec( strval_r ) )
273         {
274           return buildFile( refers_r, strval_r );
275         }
276
277       // strval_r has at least two words which could make 'op edition'?
278       std::vector<std::string> what;
279       if (str::split( strval_r, std::back_inserter(what)) >= 2)
280         {
281           Rel op;
282           Edition edition;
283           try
284             {
285               op = Rel(what[1]);
286               edition = Edition(what[2]);
287             }
288           catch ( Exception & excpt )
289             {
290               // So they don't make valid 'op edition'
291               ZYPP_CAUGHT( excpt );
292               DBG << "Trying named cap for: " << strval_r << endl;
293               // See whether it makes a named cap.
294               return buildNamed( refers_r, strval_r );
295             }
296
297           // Valid 'op edition'
298           return buildVersioned( refers_r,
299                                  what[0], op, edition );
300         }
301       //else
302       // not a VersionedCap
303       return buildNamed( refers_r, strval_r );
304     }
305   catch ( Exception & excpt )
306     {
307       ZYPP_RETHROW( excpt );
308       return NULL; // not reached
309     }
310
311
312   CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r,
313                                 const std::string & name_r,
314                                 const std::string & op_r,
315                                 const std::string & edition_r )
316     try
317     {
318       if ( isHalSpec( name_r ) )
319       {
320         return buildHal( refers_r, name_r, Rel(op_r), edition_r );
321       }
322       if ( isModaliasSpec( name_r ) )
323         {
324           return buildModalias( refers_r, name_r, Rel(op_r), edition_r );
325         }
326       // Try creating Rel and Edition, then parse
327       return parse( refers_r, name_r, Rel(op_r), Edition(edition_r) );
328     }
329     catch ( Exception & excpt )
330     {
331       ZYPP_RETHROW( excpt );
332       return NULL; // not reached
333     }
334
335   ///////////////////////////////////////////////////////////////////
336   //
337   //    METHOD NAME : CapFactory::parse
338   //    METHOD TYPE : Capability
339   //
340   CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r,
341                              const std::string & name_r,
342                              Rel op_r,
343                              const Edition & edition_r )
344   try
345   {
346       if ( isHalSpec( name_r ) )
347       {
348         return buildHal( refers_r, name_r, op_r, edition_r.asString() );
349       }
350       if ( isModaliasSpec( name_r ) )
351       {
352         return buildModalias( refers_r, name_r, op_r, edition_r.asString() );
353       }
354       return buildVersioned( refers_r, name_r, op_r, edition_r );
355   }
356   catch ( Exception & excpt )
357   {
358       ZYPP_RETHROW( excpt );
359       return NULL; // not reached
360   }
361
362   ///////////////////////////////////////////////////////////////////
363
364     /////////////////////////////////////////////////////////////////
365   } // namespace capability
366   ///////////////////////////////////////////////////////////////////
367   /////////////////////////////////////////////////////////////////
368 } // namespace zypp
369 ///////////////////////////////////////////////////////////////////