2008-02-10 17:23:16 +01:00
/*
2010-02-28 07:17:12 +01:00
STRUCT - FACTORY - IMPL . hpp - crating structural assets ( impl details )
2008-02-10 17:23:16 +01:00
2008-03-10 08:38:59 +01:00
Copyright ( C ) Lumiera . org
2010-02-28 07:17:12 +01:00
2008 - 2010 , Hermann Vosseler < Ichthyostega @ web . de >
2008-02-10 17:23:16 +01:00
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation ; either version 2 of the
License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
2010-02-28 07:17:12 +01:00
/** @file struct-factory-impl.hpp
2008-02-10 17:23:16 +01:00
* * Private implementation details of creating various structural assets .
2010-02-28 07:17:12 +01:00
* * Details how to fabricate specific kinds of structural assets , based
* * on capability informations encoded into a query ( goal ) .
2008-02-10 17:23:16 +01:00
* * @ internal to be used by struct . cpp
* *
* * @ see ConfigQuery
* *
*/
2010-02-28 07:17:12 +01:00
# ifndef ASSET_STRUCT_FACTORY_IMPL_H
# define ASSET_STRUCT_FACTORY_IMPL_H
2008-02-10 17:23:16 +01:00
2008-02-18 04:16:53 +01:00
# include "proc/mobject/session.hpp"
2008-12-18 08:54:33 +01:00
# include "common/configrules.hpp"
2010-03-06 04:30:12 +01:00
# include "lib/symbol.hpp"
2008-12-27 00:53:35 +01:00
# include "lib/error.hpp"
2008-12-17 17:53:32 +01:00
# include "lib/util.hpp"
2008-02-10 17:23:16 +01:00
# include <boost/format.hpp>
using boost : : format ;
2008-02-18 04:16:53 +01:00
using mobject : : Session ;
2010-03-06 04:30:12 +01:00
using lib : : Symbol ;
2008-02-18 04:16:53 +01:00
using util : : isnil ;
using util : : contains ;
2008-02-10 17:23:16 +01:00
using asset : : Query ;
2008-03-10 08:38:59 +01:00
using lumiera : : query : : LUMIERA_ERROR_CAPABILITY_QUERY ;
using lumiera : : query : : extractID ;
2008-02-10 17:23:16 +01:00
2010-02-28 07:17:12 +01:00
namespace asset {
2008-02-10 17:23:16 +01:00
2010-03-06 04:30:12 +01:00
namespace { // structural asset ID scheme ///////////////////////////////////////////////////////////TICKET #565
template < class STRU >
struct Traits
{
static Symbol namePrefix ;
static Symbol catFolder ;
static Symbol idSymbol ;
} ;
template < > Symbol Traits < Track > : : namePrefix = " track " ;
template < > Symbol Traits < Track > : : catFolder = " tracks " ;
template < > Symbol Traits < Track > : : idSymbol = " track " ;
template < > Symbol Traits < Pipe > : : namePrefix = " pipe " ;
template < > Symbol Traits < Pipe > : : catFolder = " pipes " ;
template < > Symbol Traits < Pipe > : : idSymbol = " pipe " ;
template < > Symbol Traits < const ProcPatt > : : namePrefix = " patt " ;
template < > Symbol Traits < const ProcPatt > : : catFolder = " build-templates " ;
template < > Symbol Traits < const ProcPatt > : : idSymbol = " procPatt " ;
Symbol genericIdSymbol ( " id " ) ;
}
2008-02-10 17:23:16 +01:00
/**
2009-01-05 16:17:17 +01:00
* Implementation details , especially concerning how configuration
2008-02-10 17:23:16 +01:00
* queries are resolved and when to create new objects automatically .
* @ todo better use a general struct traits class , esp . for creating the Ident
*/
class StructFactoryImpl
{
2010-02-28 07:17:12 +01:00
2008-02-10 17:23:16 +01:00
/** @internal derive a sensible asset ident tuple when creating
* structural asset instances based on a capability query
*/
template < class STRU >
const Asset : : Ident
createIdent ( const Query < STRU > & query )
{
2010-03-06 04:30:12 +01:00
string name ( query ) ;
// does the query somehow specify the desired name-ID?
string nameID = extractID ( genericIdSymbol , query ) ;
if ( isnil ( nameID ) )
nameID = extractID ( Traits < STRU > : : idSymbol , query ) ;
2008-02-18 04:16:53 +01:00
if ( isnil ( nameID ) )
{
// no name-ID contained in the query...
// so we'll create a new one
static int i = 0 ;
static format namePattern ( " %s.%d " ) ;
static format predPattern ( " %s(%s) , " ) ;
nameID = str ( namePattern % Traits < STRU > : : namePrefix % ( + + i ) ) ;
name . insert ( 0 ,
str ( predPattern % Traits < STRU > : : idSymbol % nameID ) ) ;
}
ENSURE ( ! isnil ( name ) ) ;
ENSURE ( ! isnil ( nameID ) ) ;
ENSURE ( contains ( name , nameID ) ) ;
2008-02-10 17:23:16 +01:00
Category cat ( STRUCT , Traits < STRU > : : catFolder ) ;
2010-03-07 06:30:26 +01:00
return Asset : : Ident ( name , cat ) ; ///////////////////////TICKET #565 the ID field should be just the ID, the query should go into a dedicated "capabilities" field.
2008-02-10 17:23:16 +01:00
}
2010-02-28 07:17:12 +01:00
2008-02-10 17:23:16 +01:00
/** used for issuing recursive create calls to top level */
StructFactory & recursive_create_ ;
public :
StructFactoryImpl ( StructFactory & interface )
: recursive_create_ ( interface )
{ }
/** make a new structural asset instance.
2010-02-28 07:17:12 +01:00
* @ warning default / fallback implementation just throws .
* @ todo a real implementation using a resolution engine .
2008-02-10 17:23:16 +01:00
*/
template < class STRU >
STRU * fabricate ( const Query < STRU > & caps )
{
2008-03-10 08:38:59 +01:00
throw lumiera : : error : : Config ( str ( format ( " The following Query could not be resolved: %s. " ) % caps . asKey ( ) )
, LUMIERA_ERROR_CAPABILITY_QUERY ) ;
2008-02-10 17:23:16 +01:00
}
} ;
/* ============= specialisations =========================== */
2010-02-28 07:17:12 +01:00
2008-02-10 17:23:16 +01:00
template < >
Track *
StructFactoryImpl : : fabricate ( const Query < Track > & caps )
{
TODO ( " actually extract properties/capabilities from the query... " ) ;
2010-02-28 07:17:12 +01:00
TODO ( " make sure AssetManager detects duplicates (currently 4/08 it doesn't) " ) ; /////////////TICKET #102
2008-02-10 17:23:16 +01:00
return new Track ( createIdent ( caps ) ) ;
}
template < >
2008-02-13 04:41:58 +01:00
const ProcPatt *
StructFactoryImpl : : fabricate ( const Query < const ProcPatt > & caps )
2008-02-10 17:23:16 +01:00
{
TODO ( " actually extract properties/capabilities from the query... " ) ;
return new ProcPatt ( createIdent ( caps ) ) ;
}
template < >
2008-02-14 04:12:30 +01:00
Pipe *
StructFactoryImpl : : fabricate ( const Query < Pipe > & caps )
2008-02-10 17:23:16 +01:00
{
2008-02-18 04:16:53 +01:00
const Asset : : Ident idi ( createIdent ( caps ) ) ;
string pipeID = extractID ( " pipe " , idi . name ) ;
string streamID = extractID ( " stream " , caps ) ;
if ( isnil ( streamID ) ) streamID = " default " ;
PProcPatt processingPattern = Session : : current - > defaults ( Query < const ProcPatt > ( " stream( " + streamID + " ) " ) ) ;
return new Pipe ( idi
, processingPattern
, pipeID
) ;
2008-02-10 17:23:16 +01:00
}
} // namespace asset
# endif