|
/*
|
|
WORM - a DAL/ORM code generation framework
|
|
Copyright (C) 2011 Erik Winn <sidewalksoftware@gmail.com>
|
|
|
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
//class_definition.tpl is currently the shortest ..
|
|
#define MIN_TPL_FILENAME_SIZE 20
|
|
|
|
#include <dirent.h>
|
|
#include <errno.h>
|
|
#include <fstream>
|
|
#include <stdio.h>
|
|
#include <ctemplate/template.h>
|
|
|
|
#include "wormclassgenerator.h"
|
|
|
|
using namespace ctemplate;
|
|
|
|
namespace WSql
|
|
{
|
|
/** @{ */
|
|
/**
|
|
* These are hashed string constants for refering to the marker tags used in the templates
|
|
* Note that you may also simply use const char strings - this just helps avoid typos ..
|
|
*/
|
|
static const StaticTemplateString kcd_BELONGS_TO_separator = STS_INIT_WITH_HASH(kcd_BELONGS_TO_separator, "BELONGS_TO_separator", 8409796541203472165LLU);
|
|
static const StaticTemplateString kcd_BELONGS_TO = STS_INIT_WITH_HASH(kcd_BELONGS_TO, "BELONGS_TO", 15166195752158467517LLU);
|
|
static const StaticTemplateString kcd_CLASS_NAME = STS_INIT_WITH_HASH(kcd_CLASS_NAME, "CLASS_NAME", 13981977283673860485LLU);
|
|
static const StaticTemplateString kcd_COLUMN_NAME = STS_INIT_WITH_HASH(kcd_COLUMN_NAME, "COLUMN_NAME", 16524890828269290931LLU);
|
|
static const StaticTemplateString kcd_COLUMNS_separator = STS_INIT_WITH_HASH(kcd_COLUMNS_separator, "COLUMNS_separator", 3248360594376546073LLU);
|
|
static const StaticTemplateString kcd_COLUMNS = STS_INIT_WITH_HASH(kcd_COLUMNS, "COLUMNS", 15302874640052016969LLU);
|
|
static const StaticTemplateString kcd_DATATYPE = STS_INIT_WITH_HASH(kcd_DATATYPE, "DATATYPE", 6518949878326190781LLU);
|
|
static const StaticTemplateString kcd_FOREIGNKEY_CLASSNAME = STS_INIT_WITH_HASH(kcd_FOREIGNKEY_CLASSNAME, "FOREIGNKEY_CLASSNAME", 14113744978891695861LLU);
|
|
static const StaticTemplateString kcd_FOREIGNKEY_CLASS_PLURAL = STS_INIT_WITH_HASH(kcd_FOREIGNKEY_CLASS_PLURAL, "FOREIGNKEY_CLASS_PLURAL", 13464148753922874173LLU);
|
|
static const StaticTemplateString kcd_FORWARD_DECLARATIONS = STS_INIT_WITH_HASH(kcd_FORWARD_DECLARATIONS, "FORWARD_DECLARATIONS", 15273852411010322531LLU);
|
|
static const StaticTemplateString kcd_HAS_MANY = STS_INIT_WITH_HASH(kcd_HAS_MANY, "HAS_MANY", 12417993436827992317LLU);
|
|
static const StaticTemplateString kcd_HEADER_GUARD = STS_INIT_WITH_HASH(kcd_HEADER_GUARD, "HEADER_GUARD", 17470440760084290191LLU);
|
|
static const StaticTemplateString kcd_INCLUDES = STS_INIT_WITH_HASH(kcd_INCLUDES, "INCLUDES", 7699670683738647257LLU);
|
|
static const StaticTemplateString kcd_INCLUDE = STS_INIT_WITH_HASH(kcd_INCLUDE, "INCLUDE", 434435386609578605LLU);
|
|
static const StaticTemplateString kcd_PK_COLUMN_NAME = STS_INIT_WITH_HASH(kcd_PK_COLUMN_NAME, "PK_COLUMN_NAME", 10026323698513705213LLU);
|
|
static const StaticTemplateString kcd_PK_SECTION = STS_INIT_WITH_HASH(kcd_PK_SECTION, "PK_SECTION", 2633593037312264637LLU);
|
|
static const StaticTemplateString kcd_REFERENCED_CLASSNAME = STS_INIT_WITH_HASH(kcd_REFERENCED_CLASSNAME, "REFERENCED_CLASSNAME", 5376938313052943395LLU);
|
|
static const StaticTemplateString kcd_REFERENCED_TABLENAME = STS_INIT_WITH_HASH(kcd_REFERENCED_TABLENAME, "REFERENCED_TABLENAME", 14486319327059551333LLU);
|
|
static const StaticTemplateString kcd_REFERENCED_VARIABLE_NAME = STS_INIT_WITH_HASH(kcd_REFERENCED_VARIABLE_NAME, "REFERENCED_VARIABLE_NAME", 9463122012384535247LLU);
|
|
static const StaticTemplateString kcd_REFERING_COLUMN_NAME = STS_INIT_WITH_HASH(kcd_REFERING_COLUMN_NAME, "REFERING_COLUMN_NAME", 9271015767481962353LLU);
|
|
static const StaticTemplateString kcd_REFERENCED_COLUMN_NAME = STS_INIT_WITH_HASH(kcd_REFERENCED_COLUMN_NAME, "REFERENCED_COLUMN_NAME", 15872324185705232533LLU);
|
|
static const StaticTemplateString kcd_REFERING_VARIABLE_NAME = STS_INIT_WITH_HASH(kcd_REFERING_VARIABLE_NAME, "REFERING_VARIABLE_NAME", 4303955651462047995LLU);
|
|
static const StaticTemplateString kcd_TABLE_NAME = STS_INIT_WITH_HASH(kcd_TABLE_NAME, "TABLE_NAME", 3760310134096538793LLU);
|
|
static const StaticTemplateString kcd_UNSIGNED = STS_INIT_WITH_HASH(kcd_UNSIGNED, "UNSIGNED", 10867561526856517727LLU);
|
|
static const StaticTemplateString kcd_UNSUPPORTED = STS_INIT_WITH_HASH(kcd_UNSUPPORTED, "UNSUPPORTED", 8112833089436120679LLU);
|
|
static const StaticTemplateString kcd_VARIABLE_GETTOR = STS_INIT_WITH_HASH(kcd_VARIABLE_GETTOR, "VARIABLE_GETTOR", 4376112485907229951LLU);
|
|
static const StaticTemplateString kcd_VARIABLE_NAME = STS_INIT_WITH_HASH(kcd_VARIABLE_NAME, "VARIABLE_NAME", 5051229879184672055LLU);
|
|
static const StaticTemplateString kcd_VARIABLE_SETTOR = STS_INIT_WITH_HASH(kcd_VARIABLE_SETTOR, "VARIABLE_SETTOR", 18309610407346123363LLU);
|
|
|
|
/** @} */
|
|
|
|
/*! \class WormClassGenerator An ORM generator class
|
|
* \brief The main class in the ORM generator
|
|
*
|
|
* This class is the central class in the ORM generator. It requires a valid WSqlDatabase object
|
|
* and is used in this manner:
|
|
* \code
|
|
*
|
|
* WSql::WSqlDatabase db( drivertype );
|
|
* db.setDatabaseName( dbname );
|
|
* db.setUserName( username );
|
|
* db.setHostName( hostname );
|
|
* db.setPassword( password );
|
|
*
|
|
* if ( !db.open() ) {
|
|
* some_error_func();
|
|
* }
|
|
*
|
|
* WSql::WormClassGenerator gen(db);
|
|
* gen.setTemplateDirectory(templatesdir);
|
|
* gen.setOutputDirectory(outputdir);
|
|
* if(!gen.init())
|
|
* some_error_func();
|
|
* else
|
|
* gen.run();
|
|
*
|
|
* \endcode
|
|
*
|
|
* \ingroup WSql
|
|
*/
|
|
|
|
/*! \brief Constructs a generator with the database \a db
|
|
*/
|
|
WormClassGenerator::WormClassGenerator ( WSqlDatabase &db ) : _db ( db )
|
|
{
|
|
usesBaseClass = false;
|
|
}
|
|
/*! \brief Initialize templates and metadata
|
|
*
|
|
* This method initializes the database metadata and loads the available
|
|
* templates. It must be called (and optionally checked for success) \em before
|
|
* run().
|
|
* Note also that the templates are expected to end in ".tpl", worm will attempt to
|
|
* identify the type of template according to the filename.
|
|
*
|
|
* On failure this sets a message in the database object and returns false.
|
|
*
|
|
* \retval bool - true if templates and metadata successfully initialized.
|
|
*/
|
|
bool WormClassGenerator::init()
|
|
{
|
|
//load available templates
|
|
DIR *dir;
|
|
struct dirent *ent;
|
|
|
|
dir = opendir ( _templateDirectory.c_str() );
|
|
|
|
if ( dir != NULL )
|
|
{
|
|
WormCodeTemplate tpl;
|
|
|
|
while ( ( ent = readdir ( dir ) ) != NULL )
|
|
{
|
|
if ( ent->d_type != DT_REG )
|
|
continue;
|
|
|
|
std::string entry = ent->d_name;
|
|
size_t sz = entry.size();
|
|
|
|
if ( sz < MIN_TPL_FILENAME_SIZE )
|
|
continue;
|
|
|
|
//only accept .tpl files
|
|
std::string ext = entry.substr ( sz - 4 );
|
|
|
|
if ( ext.compare ( ".tpl" ) )
|
|
continue;
|
|
|
|
tpl.setUri ( entry );
|
|
_templates.push_back ( tpl );
|
|
if( WormCodeTemplate::ClassDeclarationBase == tpl.type() )
|
|
usesBaseClass = true;
|
|
|
|
/* maybe use, pass a string to ctemplate: std::string tmp;
|
|
fs.open(entry.c_str());
|
|
while(fs)
|
|
std::getline(fs,tmp);
|
|
tpl.setContent(tmp);
|
|
*/
|
|
}
|
|
|
|
closedir ( dir );
|
|
}
|
|
else
|
|
{
|
|
std::string msg = "Cannot open directory: " + _templateDirectory;
|
|
|
|
if ( errno == EACCES )
|
|
msg.append ( " - Access denied." );
|
|
|
|
_db.addError ( WSqlError ( msg, errno, WSql::WSqlError::SYSTEM, WSql::WSqlError::FATAL ) );
|
|
return false;
|
|
}
|
|
|
|
_db.initMetaData();
|
|
return true;
|
|
}
|
|
/*! \brief Run the generator
|
|
*
|
|
* This method iterates through the available templates for each configured
|
|
* table, calls expand() and writes the results to a class file. It is the principle
|
|
* control function for WormClassGenerator.
|
|
*
|
|
* If no tables have been added it assumes that all tables in the database are
|
|
* to be generated.
|
|
*
|
|
* \sa addTable() setTemplateDirectory() setOutputDirectory()
|
|
*/
|
|
void WormClassGenerator::run()
|
|
{
|
|
if ( _tablesToGenerate.empty() )
|
|
{
|
|
std::cerr << "No tables specified - assuming all tables .." << std::endl;
|
|
_tablesToGenerate = _db.tableNames();
|
|
}
|
|
|
|
std::string outbuffer;
|
|
std::string outfilename;
|
|
std::vector<WormCodeTemplate>::iterator tpl_it;
|
|
std::vector<std::string>::const_iterator tbl_it = _tablesToGenerate.begin();
|
|
|
|
//each table translates to a class object ..
|
|
for ( ; tbl_it != _tablesToGenerate.end(); ++tbl_it )
|
|
{
|
|
WSqlTable table = _db.tableMetaData ( *tbl_it );
|
|
|
|
//foreach template, expand for this table
|
|
for ( tpl_it = _templates.begin(); tpl_it != _templates.end(); ++ tpl_it )
|
|
{
|
|
const std::string tplfilename = _templateDirectory + tpl_it->uri();
|
|
outbuffer = expand ( tplfilename, table, tpl_it->type() );
|
|
outfilename = createOutFileName ( tpl_it->type(), table );
|
|
|
|
if ( !writeFile ( outbuffer, outfilename ) )
|
|
std::cerr << "Warning: failed to write File " << outfilename << std::endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*! \brief Expands the template in \a filename for \a table
|
|
*
|
|
* This initializes a dictionary with the values for each column in table mapped to the
|
|
* marker tags used in the template \a filename (Note: see top of file for supported tags)
|
|
* It then expands the template replacing the tag markers and returns a string suitable for
|
|
* writing to a file.
|
|
*
|
|
* \todo Break this up into smaller functions, its getting long .. and formating the variable strings
|
|
* (eg. variable_gettor/variable_settor) should at least be broken out into a funcion and ideally
|
|
* be moved to the template .. but, we need a smarter templating system for that.
|
|
*
|
|
* \param std::string filename - the file containing the template
|
|
* \param WSqlTable table - the table being generated
|
|
* \retval std::string an expanded template
|
|
*/
|
|
std::string WormClassGenerator::expand ( const std::string &filename, const WSqlTable &table, WormCodeTemplate::Type template_type )
|
|
{
|
|
std::string strToReturn;
|
|
bool has_string = false;
|
|
bool has_vector = false;
|
|
std::string type_declaration;
|
|
std::string column_name;
|
|
std::string variable_name;
|
|
std::string variable_settor;
|
|
std::string variable_gettor;
|
|
std::vector<std::string> forward_declarations;
|
|
|
|
TemplateDictionary *topdict = new TemplateDictionary ( filename );
|
|
TemplateDictionary *forwarddecls_dict = 0;
|
|
TemplateDictionary *belongsto_dict = 0;
|
|
TemplateDictionary *hasmany_dict = 0;
|
|
TemplateDictionary *includes_dict = 0;
|
|
TemplateDictionary *columns_dict = 0;
|
|
TemplateDictionary *primary_key_dict = 0;
|
|
|
|
topdict->SetValue ( kcd_CLASS_NAME, table.className() );
|
|
topdict->SetValue ( kcd_TABLE_NAME, table.name() );
|
|
std::string header_guard = table.className() + "_H";
|
|
WSqlDataType::toUpper(header_guard);
|
|
topdict->SetValue("HEADER_GUARD", header_guard);
|
|
std::string includes_string;
|
|
|
|
//TODO: move this stuff to a method ..
|
|
if( WormCodeTemplate::ClassDefinition == template_type )
|
|
{
|
|
includes_string = "#include \"" + table.className() + ".h\"";
|
|
WSqlDataType::toLower(includes_string);
|
|
includes_dict = topdict->AddSectionDictionary(kcd_INCLUDES);
|
|
includes_dict->SetValue(kcd_INCLUDE, includes_string);
|
|
}
|
|
if( WormCodeTemplate::ClassDefinitionBase == template_type )
|
|
{
|
|
includes_string = "#include \"" + table.className() + "base.h\"";
|
|
WSqlDataType::toLower(includes_string);
|
|
includes_dict = topdict->AddSectionDictionary(kcd_INCLUDES);
|
|
includes_dict->SetValue(kcd_INCLUDE, includes_string);
|
|
}
|
|
if( usesBaseClass && WormCodeTemplate::ClassDeclaration == template_type )
|
|
{
|
|
includes_string = "#include \"" + table.className() + "base.h\"";
|
|
WSqlDataType::toLower(includes_string);
|
|
includes_dict = topdict->AddSectionDictionary(kcd_INCLUDES);
|
|
includes_dict->SetValue(kcd_INCLUDE, includes_string);
|
|
}
|
|
|
|
const std::vector<WSqlColumn>& columns = table.columns();
|
|
std::vector<WSqlColumn>::const_iterator col_it = columns.begin();
|
|
|
|
if ( table.hasForeignKeys() )
|
|
{
|
|
std::vector< WSqlForeignKey >fks = table.foreignKeys();
|
|
std::vector< WSqlForeignKey >::const_iterator fks_it = fks.begin();
|
|
|
|
for ( ; fks_it != fks.end(); ++fks_it )
|
|
{
|
|
//fks_it->dump();
|
|
std::vector<std::string>::const_iterator it = std::find ( forward_declarations.begin(), forward_declarations.end(), fks_it->referencedClassName() );
|
|
|
|
if ( it == forward_declarations.end() ) //avoid repetition ..
|
|
{
|
|
forwarddecls_dict = topdict->AddSectionDictionary ( kcd_FORWARD_DECLARATIONS );
|
|
forwarddecls_dict->SetValue ( kcd_REFERENCED_CLASSNAME, fks_it->referencedClassName() );
|
|
forward_declarations.push_back ( fks_it->referencedClassName() );
|
|
if ( ( ! usesBaseClass && WormCodeTemplate::ClassDefinition == template_type)
|
|
|| WormCodeTemplate::ClassDefinitionBase == template_type )
|
|
{
|
|
includes_string = "#include \"" + fks_it->referencedClassName() + ".h\"";
|
|
WSqlDataType::toLower(includes_string);
|
|
includes_dict = topdict->AddSectionDictionary(kcd_INCLUDES);
|
|
includes_dict->SetValue(kcd_INCLUDE, includes_string);
|
|
}
|
|
}
|
|
belongsto_dict = topdict->AddSectionDictionary ( kcd_BELONGS_TO );
|
|
belongsto_dict->SetValue ( kcd_REFERENCED_CLASSNAME, fks_it->referencedClassName() );
|
|
belongsto_dict->SetValue ( kcd_REFERENCED_TABLENAME, fks_it->referencedTableName() );
|
|
belongsto_dict->SetValue(kcd_REFERENCED_COLUMN_NAME, fks_it->referencedColumnName());
|
|
belongsto_dict->SetValue(kcd_REFERING_COLUMN_NAME, fks_it->columnName());
|
|
belongsto_dict->SetValue(kcd_REFERENCED_VARIABLE_NAME, fks_it->referencedVariableName());
|
|
belongsto_dict->SetValue(kcd_REFERING_VARIABLE_NAME, fks_it->referingVariableName());
|
|
}
|
|
}
|
|
|
|
if ( table.hasReferencedKeys() )
|
|
{
|
|
has_vector = true;
|
|
std::vector< WSqlReferencedKey >rks = table.referencedKeys();
|
|
std::vector< WSqlReferencedKey >::const_iterator rks_it = rks.begin();
|
|
|
|
for ( ; rks_it != rks.end(); ++rks_it )
|
|
{
|
|
//rks_it->dump();
|
|
std::vector<std::string>::const_iterator it = std::find ( forward_declarations.begin(), forward_declarations.end(), rks_it->referingClassName() );
|
|
|
|
if ( it == forward_declarations.end() )
|
|
{
|
|
forwarddecls_dict = topdict->AddSectionDictionary ( kcd_FORWARD_DECLARATIONS );
|
|
forwarddecls_dict->SetValue ( kcd_REFERENCED_CLASSNAME, rks_it->referingClassName() );
|
|
forward_declarations.push_back ( rks_it->referingClassName() );
|
|
if ( ( ! usesBaseClass && WormCodeTemplate::ClassDefinition == template_type)
|
|
|| WormCodeTemplate::ClassDefinitionBase == template_type )
|
|
{
|
|
includes_string = "#include \"" + rks_it->referingClassName() + ".h\"";
|
|
WSqlDataType::toLower(includes_string);
|
|
includes_dict = topdict->AddSectionDictionary(kcd_INCLUDES);
|
|
includes_dict->SetValue(kcd_INCLUDE, includes_string);
|
|
}
|
|
}
|
|
hasmany_dict = topdict->AddSectionDictionary ( kcd_HAS_MANY );
|
|
hasmany_dict->SetValue ( kcd_FOREIGNKEY_CLASSNAME, rks_it->referingClassName() );
|
|
hasmany_dict->SetValue ( kcd_FOREIGNKEY_CLASS_PLURAL, rks_it->referingClassNamePlural() );
|
|
}
|
|
}
|
|
|
|
int i;
|
|
char buff[8];
|
|
|
|
for (i=0; col_it != columns.end(); ++col_it, i++ )
|
|
{
|
|
columns_dict = topdict->AddSectionDictionary ( kcd_COLUMNS );
|
|
type_declaration = col_it->typeDeclaration();
|
|
variable_name = col_it->variableName();
|
|
column_name = col_it->columnName();
|
|
std::string tmp = variable_name;
|
|
tmp[0] = toupper ( tmp[0] );
|
|
variable_settor = "set" + tmp;
|
|
variable_gettor = "get" + tmp;
|
|
|
|
if ( type_declaration.compare ( "std::string" ) == 0 )
|
|
has_string = true;
|
|
|
|
if ( ! col_it->typeIsSupported() )
|
|
columns_dict->ShowSection ( kcd_UNSUPPORTED );
|
|
|
|
if( col_it->isPrimaryKey() )
|
|
{
|
|
primary_key_dict = topdict->AddSectionDictionary ( "PK_SECTION" );
|
|
primary_key_dict->SetValue("PK_VARIABLE_NAME", variable_name);
|
|
primary_key_dict->SetValue("PK_COLUMN_NAME", column_name);
|
|
}
|
|
|
|
columns_dict->SetValue ( kcd_COLUMN_NAME, column_name );
|
|
columns_dict->SetValue ( kcd_DATATYPE, type_declaration );
|
|
if(! type_declaration.empty())
|
|
{
|
|
type_declaration[0] = ::toupper(type_declaration[0]);
|
|
//NOTE: transform std::string to StdString .. for Qt - should be some how moved or made more flexible. Or, depend on a config option.
|
|
//ie. if(qt_support) .. which we might determine from the template file ? in any case, commandline and/or settings (which we don't have ..).
|
|
size_t pos = type_declaration.find_last_of(':');
|
|
if(std::string::npos != pos)
|
|
{
|
|
type_declaration[pos+1] = ::toupper(type_declaration[pos+1]);
|
|
type_declaration.erase (std::remove(type_declaration.begin(), type_declaration.end(), ':'), type_declaration.end());
|
|
}
|
|
//Also for Qt: longlong to LongLong
|
|
pos = type_declaration.find("Long long");
|
|
if(std::string::npos != pos)
|
|
{
|
|
type_declaration[pos] = ::toupper(type_declaration[pos]);
|
|
pos = type_declaration.find(' ');
|
|
type_declaration.erase(pos,1);
|
|
pos = type_declaration.find_last_of('l');
|
|
type_declaration[pos] = ::toupper(type_declaration[pos]);
|
|
}
|
|
}
|
|
columns_dict->SetValue ( "TO_DATATYPE", type_declaration );
|
|
columns_dict->SetValue ( kcd_VARIABLE_NAME, variable_name );
|
|
columns_dict->SetValue ( kcd_VARIABLE_SETTOR, variable_settor );
|
|
columns_dict->SetValue ( kcd_VARIABLE_GETTOR, variable_gettor );
|
|
snprintf(buff, 8, "%d", i);
|
|
columns_dict->SetValue("CURRENT_COLUMN_NUMBER", buff);
|
|
snprintf(buff, 8, "%d", i+1);
|
|
columns_dict->SetValue("COLUMN_COUNT", buff);
|
|
|
|
//FIXME always unsigned .. deep strangeness ..
|
|
/* if(col_it->isUnsigned())
|
|
{
|
|
coldict->ShowSection(kcd_UNSIGNED);
|
|
std::cerr << "in table " << tbl.className() << " " << col_it->columnName() << "is unsigned .." << std::endl
|
|
<< " type: " << WSqlDataType::toString(col_it->type()) << std::endl;
|
|
}
|
|
*/
|
|
}
|
|
//used for a final "QString.arg()" in cases of WHERE queries ..
|
|
snprintf(buff, 8, "%d", i+1);
|
|
topdict->SetValue("COLUMN_COUNT", buff);
|
|
|
|
if(has_string)
|
|
{
|
|
if ( ( ! usesBaseClass && WormCodeTemplate::ClassDeclaration == template_type)
|
|
|| WormCodeTemplate::ClassDeclarationBase == template_type )
|
|
{
|
|
includes_dict = topdict->AddSectionDictionary(kcd_INCLUDES);
|
|
includes_dict->SetValue(kcd_INCLUDE, "#include <string>");
|
|
}
|
|
}
|
|
if(has_vector)
|
|
{
|
|
if ( ( ! usesBaseClass && WormCodeTemplate::ClassDeclaration == template_type)
|
|
|| WormCodeTemplate::ClassDeclarationBase == template_type )
|
|
{
|
|
includes_dict = topdict->AddSectionDictionary(kcd_INCLUDES);
|
|
includes_dict->SetValue(kcd_INCLUDE, "#include <vector>");
|
|
}
|
|
}
|
|
|
|
ExpandTemplate ( filename, DO_NOT_STRIP, topdict, &strToReturn );
|
|
delete topdict;
|
|
return strToReturn;
|
|
}
|
|
|
|
/*! \brief Return a filename for the template type \a type for table \a table
|
|
*
|
|
* This creates an output file name for a table by template type. For example, if the template
|
|
* file was class_declaration.tpl, this will be interpreted as a template of type ClassDeclaration
|
|
* and the file to write will be named using the class for the table: MyClass.h
|
|
*
|
|
* \param WormCodeTemplate::Type type - the type of template
|
|
* \param WSqlTable table - the table for which the class is generated.
|
|
* \retval std::string - a suitable file name
|
|
*/
|
|
std::string WormClassGenerator::createOutFileName ( const WormCodeTemplate::Type type, const WSqlTable &table )
|
|
{
|
|
std::string strToReturn;
|
|
|
|
switch ( type )
|
|
{
|
|
case WormCodeTemplate::ClassDeclarationBase:
|
|
strToReturn = table.className() + "Base.h";
|
|
break;
|
|
case WormCodeTemplate::ClassDefinitionBase:
|
|
strToReturn = table.className() + "Base.cpp";
|
|
break;
|
|
case WormCodeTemplate::ClassDeclaration:
|
|
strToReturn = table.className() + ".h";
|
|
break;
|
|
case WormCodeTemplate::ClassDefinition:
|
|
strToReturn = table.className() + ".cpp";
|
|
break;
|
|
default:
|
|
std::cerr << "WormClassGenerator: WARNING: template type unsupported!";
|
|
}
|
|
|
|
//TODO: make this optional
|
|
WSqlDataType::toLower(strToReturn);
|
|
return strToReturn;
|
|
}
|
|
|
|
/*! \brief Convenience function to create and write a file
|
|
*
|
|
* \retval bool true if successful
|
|
*/
|
|
bool WormClassGenerator::writeFile ( const std::string content, const std::string filename )
|
|
{
|
|
std::ofstream fs;
|
|
std::string target = _outputDirectory + "/" + filename; //!\todo; not portable FIXME
|
|
fs.open ( target.c_str() );
|
|
|
|
if ( !fs ) //!\todo capture error ..
|
|
return false;
|
|
|
|
fs << content;
|
|
fs.close();
|
|
return true;
|
|
}
|
|
|
|
/*!
|
|
* Sets the output directory to \a dir - also appends directory separator if necessary.
|
|
* \todo make portable.
|
|
* \param std::string dir - write generated files to this directory
|
|
*/
|
|
void WormClassGenerator::setOutputDirectory ( const std::string dir )
|
|
{
|
|
_outputDirectory = dir;
|
|
|
|
if ( '/' != _outputDirectory[ _outputDirectory.size() - 1] )
|
|
_outputDirectory.append ( "/" );
|
|
}
|
|
/*!
|
|
* Sets the templates directory to \a dir - also appends directory separator if necessary.
|
|
* \todo make portable.
|
|
* \param std::string dir - look for templates in this directory
|
|
*/
|
|
void WormClassGenerator::setTemplateDirectory ( const std::string dir )
|
|
{
|
|
_templateDirectory = dir;
|
|
|
|
if ( '/' != _templateDirectory[ _templateDirectory.size() - 1] )
|
|
_templateDirectory.append ( "/" );
|
|
}
|
|
|
|
|
|
} //namespace WSql
|