Rev 2226 | Blame | Compare with Previous | Last modification | View Log | RSS feed
//## begin module%1.7%.codegen_version preserve=yes// Read the documentation to learn more about C++ code generator// versioning.//## end module%1.7%.codegen_version//## begin module%420AC16002C1.cm preserve=no//## end module%420AC16002C1.cm//## begin module%420AC16002C1.cp preserve=no// C O P Y R I G H T N O T I C E// This material is confidential to ERG and may not be disclosed in whole// or in part to any third party nor used in any manner whatsoever other// than for the purposes expressly consented to by ERG in writing.//// This material is also copyright and may not be reproduced, stored in a// retrieval system or transmitted in any form or by any means in whole or// in part without the express written consent of ERG.//## end module%420AC16002C1.cp//## Module: FieldExpression%420AC16002C1; Pseudo Package body//## Subsystem: MASS::Dev::Tools::TxnTestManager::src%41F5A79001E4//## Source file: Z:\MASS_Dev\Tools\TxnTestManager\src\FieldExpression.cpp//## begin module%420AC16002C1.additionalIncludes preserve=no//## end module%420AC16002C1.additionalIncludes//## begin module%420AC16002C1.includes preserve=yes#pragma warn -com#include <LoggingMacros.h>#pragma warn +com#include <vcl.h>#pragma hdrstop//## end module%420AC16002C1.includes// ICryptographicServerProxy#include "ICryptographicServerProxy.h"// IMessageDigest#include "IMessageDigest.h"// IXmlSchemaWrapperElement#include "IXmlSchemaWrapperElement.h"// TransactionSpecification#include "TransactionSpecification.h"// EvaluationContext#include "EvaluationContext.h"// SequenceCollection#include "SequenceCollection.h"// Sequence#include "Sequence.h"// FieldExpression#include "FieldExpression.h"// DefinedVariable#include "DefinedVariable.h"// DefinedVariableTable#include "DefinedVariableTable.h"//## begin module%420AC16002C1.additionalDeclarations preserve=yes#include <time>#include <locale>#include <sstream>enum TokenId{TOKENID_INVALID = 0,TOKENID_FUNCTION,TOKENID_VARIABLE,TOKENID_CONSTANT};enum FunctionId{EXPRESSIONID_INVALID = 0,EXPRESSIONID_FORMATVERSION,EXPRESSIONID_NOW,EXPRESSIONID_UTCNOW,EXPRESSIONID_TODAY,EXPRESSIONID_YESTERDAY,EXPRESSIONID_TOMORROW,EXPRESSIONID_RAND,EXPRESSIONID_UDTYPE,EXPRESSIONID_UDSUBTYPE,EXPRESSIONID_ACCOUNTTYPE,EXPRESSIONID_SEQ,EXPRESSIONID_KEYVERSION,EXPRESSIONID_KEYNUMBER,EXPRESSIONID_MAC,EXPRESSIONID_SAMID,EXPRESSIONID_SCENARIO_INDEX,EXPRESSIONID_HOSTNAME,EXPRESSIONID_USERNAME};struct PredefinedFunction{const char * functor;FunctionId functionId;};static const PredefinedFunction functions[] ={{ "FORMATVERSION", EXPRESSIONID_FORMATVERSION },{ "NOW", EXPRESSIONID_NOW },{ "UTCNOW", EXPRESSIONID_UTCNOW },{ "TODAY", EXPRESSIONID_TODAY },{ "YESTERDAY", EXPRESSIONID_YESTERDAY },{ "TOMORROW", EXPRESSIONID_TOMORROW },{ "RAND", EXPRESSIONID_RAND },{ "UDTYPE", EXPRESSIONID_UDTYPE },{ "UDSUBTYPE", EXPRESSIONID_UDSUBTYPE },{ "ACCOUNTTYPE", EXPRESSIONID_ACCOUNTTYPE },{ "SEQ", EXPRESSIONID_SEQ },{ "KEYVERSION", EXPRESSIONID_KEYVERSION },{ "KEYNUMBER", EXPRESSIONID_KEYNUMBER },{ "MAC", EXPRESSIONID_MAC },{ "SAMID", EXPRESSIONID_SAMID },{ "SCENARIOINDEX", EXPRESSIONID_SCENARIO_INDEX },{ "HOSTNAME", EXPRESSIONID_HOSTNAME },{ "USERNAME", EXPRESSIONID_USERNAME },{ 0, EXPRESSIONID_INVALID }};static const std::locale myLocale;const FunctionId & getFunctionId( const std::string & string ){PredefinedFunction const * where = 0;for ( where = functions; where->functor; ++where ){if ( string == where->functor ){break;}}return ( where->functionId );}const bool readExpression( std::istream & stream, std::string & symbol, TokenId & token, EvaluationContext& evaluationContext ){symbol.erase();char character = 0;while ( stream.get( character ).good() ){if ( std::isalnum( character ) || character == '_' ){symbol += character;}else{stream.putback( character ); // Always put this back.if ( character == '(' ){token = TOKENID_FUNCTION;return ( true );}break; // We have read in a lexeme, now tokenise it.}}// Only do this when we didn't fail reading from the stream.if ( stream.good() || stream.eof() ){token = ( evaluationContext.getSymbolTable().isVariable( symbol, evaluationContext )? TOKENID_VARIABLE: TOKENID_CONSTANT );return ( true );}return ( false );}//## end module%420AC16002C1.additionalDeclarations// Class FieldExpressionFieldExpression::FieldExpression()//## begin FieldExpression::FieldExpression%420AC16002C1_const.initialization preserve=yes//## end FieldExpression::FieldExpression%420AC16002C1_const.initialization{//## begin FieldExpression::FieldExpression%420AC16002C1_const.body preserve=yes//## end FieldExpression::FieldExpression%420AC16002C1_const.body}//## Operation: FieldExpression%42105AAC0084FieldExpression::FieldExpression (const std::string &expression)//## begin FieldExpression::FieldExpression%42105AAC0084.hasinit preserve=no//## end FieldExpression::FieldExpression%42105AAC0084.hasinit//## begin FieldExpression::FieldExpression%42105AAC0084.initialization preserve=yes: m_expression( expression )//## end FieldExpression::FieldExpression%42105AAC0084.initialization{//## begin FieldExpression::FieldExpression%42105AAC0084.body preserve=yes//## end FieldExpression::FieldExpression%42105AAC0084.body}FieldExpression::~FieldExpression(){//## begin FieldExpression::~FieldExpression%420AC16002C1_dest.body preserve=yes//## end FieldExpression::~FieldExpression%420AC16002C1_dest.body}//## Other Operations (implementation)//## Operation: evaluate%420456630303const bool FieldExpression::evaluate (std::string &value, const bool &sideEffect, EvaluationContext& evaluationContext, std::vector< DefinedVariable * > &path, bool &postponed){//## begin FieldExpression::evaluate%420456630303.body preserve=yesif ( m_cachedValue.length() ){value = m_cachedValue;return ( true );}/*** TODO: Eventually replace the use of streams with a char buffer, but* right now I just need to get it working.*/if ( ( m_expression[ 0 ] == '\"' ) &&( m_expression[ m_expression.length() - 1 ] == '\"' ) ){value = m_cachedValue = m_expression.substr( 1, m_expression.length() - 2 );return ( true );}std::istringstream is( m_expression );skipCharacter( is, '=' ); // Skip the '=' if its there./*** TODO: evaluate this field using the defined collection of variables* and sequence generators, making sure we respect the sideEffect flag.*//**For now, we assume a very simple syntax:expression ::= function | variable | constantfunction ::= =functor ( [ argument list ] )variable ::= =variableconstant ::= alphanumericargument list ::= argument[, argument list ]argument ::= expression*/std::string symbol;TokenId token = TOKENID_INVALID;while ( readExpression( is, symbol, token, evaluationContext ) ){switch ( token ){case TOKENID_FUNCTION:return ( evaluateFunction( is, value, symbol, sideEffect, evaluationContext, path, postponed ) );case TOKENID_VARIABLE:return ( evaluateVariable( is, value, symbol, sideEffect, evaluationContext, path, postponed ) );case TOKENID_CONSTANT:// Its not a defined variable or function, so just evaluate to// it.m_cachedValue = value = m_expression;return ( true );}}return ( true );//## end FieldExpression::evaluate%420456630303.body}//## Operation: evaluateFunction%4208AE9D0216const bool FieldExpression::evaluateFunction (std::istream &is, std::string &value, std::string &symbol, const bool &sideEffect, EvaluationContext& evaluationContext, std::vector< DefinedVariable * > &path, bool &postponed){//## begin FieldExpression::evaluateFunction%4208AE9D0216.body preserve=yes/*** Check parameter lists on all functions calls, and report an error* when a function is called with superfluous arguments.*/postponed = false;switch ( getFunctionId( symbol ) ){case EXPRESSIONID_UDTYPE:{AnsiString os;os.sprintf( "%hu", evaluationContext.getTransaction().getUdType() );m_cachedValue = value = os.c_str();}return ( true );case EXPRESSIONID_UDSUBTYPE:{AnsiString os;os.sprintf( "%hu", evaluationContext.getTransaction().getUdSubtype() );m_cachedValue = value = os.c_str();}return ( true );case EXPRESSIONID_TODAY:m_cachedValue = value = TDateTime::CurrentDateTime().FormatString( "dd-mm-yyyy" ).c_str();return ( true );case EXPRESSIONID_FORMATVERSION:{AnsiString os;os.sprintf( "%d", evaluationContext.getTransaction().getFormatVersion() );m_cachedValue = value = os.c_str();}return ( true );case EXPRESSIONID_NOW:m_cachedValue = value = TDateTime::CurrentDateTime().FormatString( "dd-mm-yyyy hh:nn:ss" ).c_str();return ( true );case EXPRESSIONID_UTCNOW:{const TDateTime time = TDateTime::CurrentDateTime() + ( ( _timezone / 3600.0 ) / 24.0 );m_cachedValue = value = time.FormatString( "dd-mm-yyyy hh:nn:ss" ).c_str();}return ( true );case EXPRESSIONID_YESTERDAY:{const TDateTime time = TDateTime::CurrentDateTime() - 1;m_cachedValue = value = time.FormatString( "dd-mm-yyyy" ).c_str();}return ( true );case EXPRESSIONID_TOMORROW:{const TDateTime time = TDateTime::CurrentDateTime() + 1;m_cachedValue = value = time.FormatString( "dd-mm-yyyy" ).c_str();}return ( true );case EXPRESSIONID_ACCOUNTTYPE:switch( evaluationContext.getTransaction().getUdType() ){case 1: // Cardvalue = "2";break;case 2: // Applicationvalue = "1";break;case 3: // Productvalue = "3";break;case 4: // Othervalue = "4";break;case 5: // Auditvalue = "4";break;case 6: // Eventvalue = "4";break;case 7: // Projectvalue = "4";break;default:value.erase();break;}m_cachedValue = value;return ( true );case EXPRESSIONID_RAND:{std::string lowerBound;std::string upperBound;if ( skipCharacter( is, '(' ) &&readTerm( is, lowerBound ) &&skipCharacter( is, ',' ) &&readTerm( is, upperBound ) &&skipCharacter( is, ')' ) ){const int first = std::min< int >(atoi( lowerBound.c_str() ),atoi( upperBound.c_str() ) );const int last = std::max< int >(atoi( lowerBound.c_str() ),atoi( upperBound.c_str() ) );AnsiString os;os.sprintf( "%d",int( ( rand() / double( RAND_MAX ) ) *( last - first + 1 ) + first ) );value = os.c_str();return ( true );}else{MERROR( "Cannot parse argument list." );}}break;case EXPRESSIONID_SEQ:{bool persisted = false;std::string name;std::string first;std::string increment;std::string last;std::string discriminant;std::string fullName;/*** SEQ( name, first, increment, last[, discriminant] )* name ::= transient name | # persisted name*/if ( skipCharacter( is, '(' ) ){persisted = skipCharacter( is, '#' );if ( readIdentifier( is, name ) &&skipCharacter( is, ',' ) &&readTerm( is, first ) &&skipCharacter( is, ',' ) &&readTerm( is, last ) &&skipCharacter( is, ',' ) &&readTerm( is, increment ) &&( ( skipCharacter( is, ',' ) &&readIdentifier( is, discriminant ) ) ||skipCharacter( is, ')' ) ) ){if ( discriminant.length() ){/*** We have a discriminant, so we evaluate it to form* our name,*/FieldExpression subexpression( discriminant );std::string discriminantValue;if ( subexpression.evaluate( discriminantValue, true, evaluationContext, path, postponed ) ){AnsiString full;full.sprintf( "%s[%s]", name.c_str(), discriminantValue.c_str() );fullName = full.c_str();}}else{fullName = name;}Sequence & sequence = evaluationContext.getSequenceCollection().getSequence(fullName,persisted,atoi( first.c_str() ) );AnsiString os;os.sprintf( "%d", sequence.getValue() );value = os.c_str();sequence.incrementValue(atoi( first.c_str() ),atoi( last.c_str() ),atoi( increment.c_str() ) );return ( true );}}MERROR( "Cannot parse argument list." );}break;case EXPRESSIONID_KEYVERSION:if ( evaluationContext.haveMessageDigest() ){AnsiString os;os.sprintf( "%hu", evaluationContext.getMessageDigest().getKeyVersion() );value = os.c_str();return ( true );}break;case EXPRESSIONID_KEYNUMBER:if ( evaluationContext.haveMessageDigest() ){AnsiString os;os.sprintf( "%hu", evaluationContext.getMessageDigest().getKeyNumber() );value = os.c_str();return ( true );}break;case EXPRESSIONID_MAC:/*** We add the schema element to the collection of schema elements to* which we must assign the MAC. Because we can compute the MAC only* when all fields have been evaluated, this must be postponed, and* until then we must report success.*/if ( evaluationContext.haveSchemaElement() ){evaluationContext.getTransaction().addMacField(evaluationContext.getSchemaElement().clone() );postponed = true;return ( true );}break;case EXPRESSIONID_SAMID:if ( evaluationContext.haveCryptographicServer() ){/*** We don't know which module will be used to compute the* MAC (security doesn't tell us), so until they do we* assume its the first module.*/if ( evaluationContext.getCryptographicServer().getModuleCount() ){AnsiString os;os.sprintf( "%hu", evaluationContext.getCryptographicServer().getSamId( 0 ) );value = os.c_str();return ( true );}}break;case EXPRESSIONID_SCENARIO_INDEX:{AnsiString os;os.sprintf( "%u", evaluationContext.getScenarioIndex() );value = os.c_str();}return ( true );case EXPRESSIONID_HOSTNAME:{char name[ 1024 ];unsigned long size = sizeof( name );if ( GetComputerName( name, &size ) ){value = name;return ( true );}}case EXPRESSIONID_USERNAME:{char name[ 1024 ];unsigned long size = sizeof( name );if ( GetUserName( name, &size ) ){value = name;return ( true );}}default:MERROR( "Function \"" << symbol << "\" is not implemented." );break;}return ( false );//## end FieldExpression::evaluateFunction%4208AE9D0216.body}//## Operation: evaluateVariable%420AE22101D7const bool FieldExpression::evaluateVariable (std::istream &is, std::string &value, std::string &symbol, const bool &sideEffect, EvaluationContext& evaluationContext, std::vector< DefinedVariable * > &path, bool &postponed){//## begin FieldExpression::evaluateVariable%420AE22101D7.body preserve=yesreturn ( evaluationContext.getSymbolTable().getVariable( symbol, evaluationContext ).evaluate( value, sideEffect, evaluationContext, path, postponed ) );//## end FieldExpression::evaluateVariable%420AE22101D7.body}//## Operation: getExpression%420AC68F02E4const std::string & FieldExpression::getExpression () const{//## begin FieldExpression::getExpression%420AC68F02E4.body preserve=yesreturn ( m_expression );//## end FieldExpression::getExpression%420AC68F02E4.body}//## Operation: isFunctor%4209B773036Fconst bool FieldExpression::isFunctor (const std::string &string){//## begin FieldExpression::isFunctor%4209B773036F.body preserve=yesPredefinedFunction const * where = 0;for ( where = functions; where->functor; ++where ){if ( string == where->functor ){return ( true );}}return ( false );//## end FieldExpression::isFunctor%4209B773036F.body}//## Operation: readIdentifier%42102FB70219const bool FieldExpression::readIdentifier (std::istream &is, std::string &identifier){//## begin FieldExpression::readIdentifier%42102FB70219.body preserve=yeschar character = 0;identifier.clear();is >> std::ws;if ( is.get( character ).good() ){if ( std::isalpha( character ) ){do{identifier += character;}while ( is.get( character ).good() &&( std::isalnum( character ) || ( character == '_' ) ) );}if ( is.good() ){is.putback( character );}}return ( identifier.length() > 0 );//## end FieldExpression::readIdentifier%42102FB70219.body}//## Operation: readTerm%420B0EB603D2const bool FieldExpression::readTerm (std::istream &is, std::string &term){//## begin FieldExpression::readTerm%420B0EB603D2.body preserve=yeschar character = 0;term.clear();is >> std::ws;if ( is.get( character ).good() ){const bool quoted = ( character == '\"' );if ( std::isalnum( character ) || ( character == '-' ) || quoted ){do{term += character;}while ( is.get( character ).good() && std::isalnum( character ) );}if ( is.good() && ( !quoted || character != '\"' ) ){is.putback( character );}}return ( term.length() > 0 );//## end FieldExpression::readTerm%420B0EB603D2.body}//## Operation: setExpression%420AC68F02F3const std::string & FieldExpression::setExpression (const std::string &value){//## begin FieldExpression::setExpression%420AC68F02F3.body preserve=yesreturn ( m_expression = value );//## end FieldExpression::setExpression%420AC68F02F3.body}//## Operation: skipCharacter%420B100701E7const bool FieldExpression::skipCharacter (std::istream &is, const char &character){//## begin FieldExpression::skipCharacter%420B100701E7.body preserve=yeschar c = 0;is >> std::ws >> c;if ( is.good() ){if ( c == character ){return ( true );}is.putback( c );}return ( false );//## end FieldExpression::skipCharacter%420B100701E7.body}// Additional Declarations//## begin FieldExpression%420AC16002C1.declarations preserve=yes//## end FieldExpression%420AC16002C1.declarations//## begin module%420AC16002C1.epilog preserve=yes//## end module%420AC16002C1.epilog