1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/CapFactory.cc
16 #include "zypp/base/Logger.h"
17 #include "zypp/base/Exception.h"
18 #include "zypp/base/String.h"
20 #include "zypp/CapFactory.h"
21 #include "zypp/capability/Capabilities.h"
25 ///////////////////////////////////////////////////////////////////
27 { /////////////////////////////////////////////////////////////////
29 using ::zypp::capability::CapabilityImpl;
32 * \todo check set ordering to assert no dups
34 struct USetOrder : public std::binary_function<CapabilityImpl::Ptr, CapabilityImpl::Ptr, bool>
37 bool operator()( const CapabilityImpl::Ptr & lhs,
38 const CapabilityImpl::Ptr & rhs ) const
39 { return lhs->asString() < rhs->asString(); }
43 typedef std::set<CapabilityImpl::Ptr,USetOrder> USet;
45 /** Set to unify created capabilities. */
48 /** Immediately wrap \a allocated_r and unify by inserting
50 * \return CapabilityImpl_Ptr referencing \a allocated_r (or an
51 * eqal representation, allocated is deleted then).
53 CapabilityImpl::Ptr usetInsert( CapabilityImpl * allocated_r )
55 return *(_uset.insert( CapabilityImpl::Ptr(allocated_r) ).first);
58 /////////////////////////////////////////////////////////////////
60 ///////////////////////////////////////////////////////////////////
62 ///////////////////////////////////////////////////////////////////
64 { /////////////////////////////////////////////////////////////////
66 ///////////////////////////////////////////////////////////////////
68 // CLASS NAME : CapFactoryImpl
70 /** CapFactory implementation.
72 * Provides various functions doing checks and log and \c throw.
73 * CapFactory::parse usually combines them, and if nothing fails,
74 * finaly builds the Capability.
76 * \li \c file: /absolute/path
77 * \li \c split: name:/absolute/path
79 * \li \c vers: name op edition
81 struct CapFactory::Impl
83 /** Assert a valid Resolvable::Kind. */
84 static void assertResKind( const Resolvable::Kind & refers_r )
86 if ( refers_r == Resolvable::Kind() )
87 ZYPP_THROW( "Missing or empty Resolvable::Kind in Capability." );
90 /** Check whether \a op_r and \a edition_r make a valid edition spec.
92 * Rel::NONE is not usefull thus forbidden. Rel::ANY can be ignored,
93 * so no VersionedCap is needed for this. Everything else requires
96 * \return Whether to build a VersionedCap (i.e. \a op_r
99 static bool isEditionSpec( Rel op_r, const Edition & edition_r )
101 switch ( op_r.inSwitch() )
104 if ( edition_r != Edition::noedition )
105 WAR << "Operator " << op_r << " causes Edition "
106 << edition_r << " to be ignored." << endl;
111 ZYPP_THROW( "Operator NONE is not allowed in Capability " );
123 // SHOULD NOT GET HERE
124 ZYPP_THROW( "Unknow Operator NONE is not allowed in Capability " );
125 return false; // not reached
128 /** Test for a FileCap. \a name_r starts with \c "/". */
129 static bool isFileSpec( const std::string & name_r )
131 return *name_r.c_str() == '/';
134 /** Test for a SplitCap. \a name_r constains \c ":/". */
135 static bool isSplitSpec( const std::string & name_r )
137 return name_r.find( ":/" ) != std::string::npos;
140 /** Try to build a non versioned cap from \a name_r .
142 * The CapabilityImpl is built here and inserted into _uset.
143 * The final Capability must be created by CapFactory, as it
144 * is a friend of Capability. Here we can't access the ctor.
146 static CapabilityImpl::Ptr buildNamed( const Resolvable::Kind & refers_r,
147 const std::string & name_r )
149 assertResKind( refers_r );
151 // file: /absolute/path
152 if ( isFileSpec( name_r ) )
154 ( new capability::FileCap( refers_r, name_r ) );
156 //split: name:/absolute/path
157 str::regex rx( "([^/]*):(/.*)" );
159 if( str::regex_match( name_r.begin(), name_r.end(), what, rx ) )
162 ( new capability::SplitCap( refers_r, what[1].str(), what[2].str() ) );
167 ( new capability::NamedCap( refers_r, name_r ) );
170 /** Try to build a versioned cap from \a name_r .
172 * The CapabilityImpl is built here and inserted into _uset.
173 * The final Capability must be created by CapFactory, as it
174 * is a friend of Capability. Here we can't access the ctor.
176 * \todo Quick check for name not being filename or split.
178 static CapabilityImpl::Ptr buildVersioned( const Resolvable::Kind & refers_r,
179 const std::string & name_r,
181 const Edition & edition_r )
183 if ( Impl::isEditionSpec( op_r, edition_r ) )
185 assertResKind( refers_r );
187 // build a VersionedCap
189 ( new capability::VersionedCap( refers_r, name_r, op_r, edition_r ) );
194 return buildNamed( refers_r, name_r );
197 ///////////////////////////////////////////////////////////////////
199 ///////////////////////////////////////////////////////////////////
201 ///////////////////////////////////////////////////////////////////
203 // CLASS NAME : CapFactory
205 ///////////////////////////////////////////////////////////////////
207 ///////////////////////////////////////////////////////////////////
209 // METHOD NAME : CapFactory::CapFactory
210 // METHOD TYPE : Ctor
212 CapFactory::CapFactory()
215 ///////////////////////////////////////////////////////////////////
217 // METHOD NAME : CapFactory::~CapFactory
218 // METHOD TYPE : Dtor
220 CapFactory::~CapFactory()
224 ///////////////////////////////////////////////////////////////////
226 // METHOD NAME : CapFactory::parse
227 // METHOD TYPE : Capability
229 Capability CapFactory::parse( const std::string & strval_r ) const
231 return parse( strval_r, Resolvable::Kind() );
235 ///////////////////////////////////////////////////////////////////
237 // METHOD NAME : CapFactory::parse
238 // METHOD TYPE : Capability
240 Capability CapFactory::parse( const Resolvable::Kind & refers_r,
241 const std::string & strval_r ) const
245 // strval_r has at least two words which could make 'op edition'?
246 str::regex rx( "(.*[^ \t])([ \t]+)([^ \t]+)([ \t]+)([^ \t]+)" );
248 if( str::regex_match( strval_r.begin(), strval_r.end(),what, rx ) )
254 op = Rel(what[3].str());
255 edition = Edition(what[5].str());
257 catch ( Exception & excpt )
259 // So they don't make valid 'op edition'
260 ZYPP_CAUGHT( excpt );
261 // See whether it makes a named cap.
262 return Capability( Impl::buildNamed( refers_r, strval_r ) );
265 // Valid 'op edition'
266 return Capability ( Impl::buildVersioned( refers_r,
267 what[1].str(), op, edition ) );
270 // not a VersionedCap
272 return Capability( Impl::buildNamed( refers_r, strval_r ) );
274 catch ( Exception & excpt )
276 ZYPP_RETHROW( excpt );
277 return Capability(); // not reached
281 ///////////////////////////////////////////////////////////////////
283 // METHOD NAME : CapFactory::parse
284 // METHOD TYPE : Capability
286 Capability CapFactory::parse( const Resolvable::Kind & refers_r,
287 const std::string & name_r,
288 const std::string & op_r,
289 const std::string & edition_r ) const
292 // Try creating Rel and Edition, then parse
293 return parse( refers_r, name_r, Rel(op_r), Edition(edition_r) );
295 catch ( Exception & excpt )
297 ZYPP_RETHROW( excpt );
298 return Capability(); // not reached
301 ///////////////////////////////////////////////////////////////////
303 // METHOD NAME : CapFactory::parse
304 // METHOD TYPE : Capability
306 Capability CapFactory::parse( const Resolvable::Kind & refers_r,
307 const std::string & name_r,
309 const Edition & edition_r ) const
313 ( Impl::buildVersioned( refers_r, name_r, op_r, edition_r ) );
315 catch ( Exception & excpt )
317 ZYPP_RETHROW( excpt );
318 return Capability(); // not reached
321 /******************************************************************
323 ** FUNCTION NAME : operator<<
324 ** FUNCTION TYPE : std::ostream &
326 std::ostream & operator<<( std::ostream & str, const CapFactory & obj )
328 return str << "No CapFactory stats implemented";
331 /////////////////////////////////////////////////////////////////
333 ///////////////////////////////////////////////////////////////////