Subversion Repositories DevTools

Rev

Rev 2222 | Rev 2226 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2218 sbetterm 1
//## begin module%1.7%.codegen_version preserve=yes
2
//   Read the documentation to learn more about C++ code generator
3
//   versioning.
4
//## end module%1.7%.codegen_version
5
 
6
//## begin module%420AC16002C1.cm preserve=no
7
//## end module%420AC16002C1.cm
8
 
9
//## begin module%420AC16002C1.cp preserve=no
10
//	C O P Y R I G H T   N O T I C E
11
//	This material is confidential to ERG and may not be disclosed in whole
12
//	or in part to any third party nor used in any manner whatsoever other
13
//	than for the purposes expressly consented to by ERG in writing.
14
//
15
//	This material is also copyright and may not be reproduced, stored in a
16
//	retrieval system or transmitted in any form or by any means in whole or
17
//	in part without the express written consent of ERG.
18
//## end module%420AC16002C1.cp
19
 
20
//## Module: FieldExpression%420AC16002C1; Pseudo Package body
21
//## Subsystem: MASS::Dev::Tools::TxnTestManager::src%41F5A79001E4
22
//## Source file: Z:\MASS_Dev\Tools\TxnTestManager\src\FieldExpression.cpp
23
 
24
//## begin module%420AC16002C1.additionalIncludes preserve=no
25
//## end module%420AC16002C1.additionalIncludes
26
 
27
//## begin module%420AC16002C1.includes preserve=yes
28
#pragma warn -com
29
#include <LoggingMacros.h>
30
#pragma warn +com
31
 
32
#include <vcl.h>
33
#pragma hdrstop
34
//## end module%420AC16002C1.includes
35
 
2222 sbetterm 36
// ICryptographicServerProxy
37
#include "ICryptographicServerProxy.h"
38
// IMessageDigest
39
#include "IMessageDigest.h"
40
// IXmlSchemaWrapperElement
41
#include "IXmlSchemaWrapperElement.h"
2218 sbetterm 42
// TransactionSpecification
43
#include "TransactionSpecification.h"
44
// EvaluationContext
45
#include "EvaluationContext.h"
46
// SequenceCollection
47
#include "SequenceCollection.h"
48
// Sequence
49
#include "Sequence.h"
50
// FieldExpression
51
#include "FieldExpression.h"
52
// DefinedVariable
53
#include "DefinedVariable.h"
54
// DefinedVariableTable
55
#include "DefinedVariableTable.h"
56
//## begin module%420AC16002C1.additionalDeclarations preserve=yes
57
#include <locale>
58
#include <sstream>
59
 
60
enum TokenId
61
{
62
	TOKENID_INVALID = 0,
63
	TOKENID_FUNCTION,
64
	TOKENID_VARIABLE,
65
	TOKENID_CONSTANT
66
};
67
enum FunctionId
68
{
69
	EXPRESSIONID_INVALID = 0,
70
	EXPRESSIONID_FORMATVERSION,
71
	EXPRESSIONID_NOW,
72
	EXPRESSIONID_UTCNOW,
73
	EXPRESSIONID_TODAY,
74
	EXPRESSIONID_YESTERDAY,
75
	EXPRESSIONID_TOMORROW,
76
	EXPRESSIONID_RAND,
77
	EXPRESSIONID_UDTYPE,
78
	EXPRESSIONID_UDSUBTYPE,
79
	EXPRESSIONID_ACCOUNTTYPE,
80
	EXPRESSIONID_SEQ,
81
	EXPRESSIONID_KEYVERSION,
82
	EXPRESSIONID_KEYNUMBER,
2222 sbetterm 83
	EXPRESSIONID_MAC,
84
	EXPRESSIONID_SAMID,
85
	EXPRESSIONID_SCENARIO_INDEX
2218 sbetterm 86
};
87
struct PredefinedFunction
88
{
89
	const char *	functor;
90
	FunctionId		functionId;
91
};
92
 
93
static const PredefinedFunction functions[] =
94
{
95
	{ "FORMATVERSION",	EXPRESSIONID_FORMATVERSION },
96
	{ "NOW",			EXPRESSIONID_NOW },
97
	{ "UTCNOW",			EXPRESSIONID_UTCNOW },
98
	{ "TODAY",			EXPRESSIONID_TODAY },
99
	{ "YESTERDAY",		EXPRESSIONID_YESTERDAY },
100
	{ "TOMORROW",		EXPRESSIONID_TOMORROW },
101
	{ "RAND",			EXPRESSIONID_RAND },
102
	{ "UDTYPE",			EXPRESSIONID_UDTYPE },
103
	{ "UDSUBTYPE",		EXPRESSIONID_UDSUBTYPE },
104
	{ "ACCOUNTTYPE",	EXPRESSIONID_ACCOUNTTYPE },
105
	{ "SEQ",			EXPRESSIONID_SEQ },
106
	{ "KEYVERSION",		EXPRESSIONID_KEYVERSION },
107
	{ "KEYNUMBER",		EXPRESSIONID_KEYNUMBER },
108
	{ "MAC",			EXPRESSIONID_MAC },
2222 sbetterm 109
	{ "SAMID",			EXPRESSIONID_SAMID },
110
	{ "SCENARIOINDEX",	EXPRESSIONID_SCENARIO_INDEX },
2218 sbetterm 111
	{ 0,				EXPRESSIONID_INVALID }
112
};
113
 
114
static const std::locale myLocale;
115
 
116
const FunctionId & getFunctionId( const std::string & string )
117
{
118
	PredefinedFunction const * where = 0;
119
 
120
	for ( where = functions; where->functor; ++where )
121
	{
122
		if ( string == where->functor )
123
		{
124
			break;
125
		}
126
	}
127
 
128
	return ( where->functionId );
129
}
130
 
2224 sbetterm 131
const bool readExpression( std::istream & stream, std::string & symbol, TokenId & token, EvaluationContext& evaluationContext )
2218 sbetterm 132
{
133
	symbol.erase();
134
 
135
	char character = 0;
136
	while ( stream.get( character ).good() )
137
	{
138
		if ( std::isalnum( character ) || character == '_' )
139
		{
140
			symbol += character;
141
		}
142
		else
143
		{
144
			stream.putback( character );	// Always put this back.
145
 
146
			if ( character == '(' )
147
			{
148
				token = TOKENID_FUNCTION;
149
				return ( true );
150
			}
151
 
152
			break;	// We have read in a lexeme, now tokenise it.
153
		}
154
	}
155
 
156
	// Only do this when we didn't fail reading from the stream.
157
	if ( stream.good() || stream.eof() )
158
	{
2224 sbetterm 159
		token = ( evaluationContext.getSymbolTable().isVariable( symbol, evaluationContext )
2218 sbetterm 160
			? TOKENID_VARIABLE
161
			: TOKENID_CONSTANT );
162
		return ( true );
163
	}
164
 
165
	return ( false );
166
}
167
//## end module%420AC16002C1.additionalDeclarations
168
 
169
 
170
// Class FieldExpression 
171
 
172
FieldExpression::FieldExpression()
173
  //## begin FieldExpression::FieldExpression%420AC16002C1_const.initialization preserve=yes
174
  //## end FieldExpression::FieldExpression%420AC16002C1_const.initialization
175
{
176
  //## begin FieldExpression::FieldExpression%420AC16002C1_const.body preserve=yes
177
  //## end FieldExpression::FieldExpression%420AC16002C1_const.body
178
}
179
 
180
//## Operation: FieldExpression%42105AAC0084
181
FieldExpression::FieldExpression (const std::string &expression)
182
  //## begin FieldExpression::FieldExpression%42105AAC0084.hasinit preserve=no
183
  //## end FieldExpression::FieldExpression%42105AAC0084.hasinit
184
  //## begin FieldExpression::FieldExpression%42105AAC0084.initialization preserve=yes
185
 
186
:	m_expression( expression )
187
 
188
  //## end FieldExpression::FieldExpression%42105AAC0084.initialization
189
{
190
  //## begin FieldExpression::FieldExpression%42105AAC0084.body preserve=yes
191
  //## end FieldExpression::FieldExpression%42105AAC0084.body
192
}
193
 
194
 
195
FieldExpression::~FieldExpression()
196
{
197
  //## begin FieldExpression::~FieldExpression%420AC16002C1_dest.body preserve=yes
198
  //## end FieldExpression::~FieldExpression%420AC16002C1_dest.body
199
}
200
 
201
 
202
 
203
//## Other Operations (implementation)
204
//## Operation: evaluate%420456630303
205
const bool FieldExpression::evaluate (std::string &value, const bool &sideEffect, EvaluationContext& evaluationContext, std::vector< DefinedVariable * > &path, bool &postponed)
206
{
207
  //## begin FieldExpression::evaluate%420456630303.body preserve=yes
208
 
209
	if ( m_cachedValue.length() )
210
	{
211
		value = m_cachedValue;
212
		return ( true );
213
	}
214
 
215
	/**
216
	 *	TODO: Eventually replace the use of streams with a char buffer, but
217
	 *	right now I just need to get it working.
218
	 */
219
	if ( ( m_expression[ 0 ] == '\"' ) &&
220
		 ( m_expression[ m_expression.length() - 1 ] == '\"' ) )
221
	{
222
		value = m_cachedValue = m_expression.substr( 1, m_expression.length() - 2 );
223
		return ( true );
224
	}
225
 
226
	std::istringstream is( m_expression );
227
	skipCharacter( is, '=' );	// Skip the '=' if its there.
228
 
229
	/**
230
	 *	TODO: evaluate this field using the defined collection of variables
231
	 *	and sequence generators, making sure we respect the sideEffect flag.
232
	 */
233
	/**
234
		For now, we assume a very simple syntax:
235
 
236
			expression		::= function | variable | constant
237
			function		::= =functor ( [ argument list ] )
238
			variable		::= =variable
239
			constant		::= alphanumeric
240
			argument list	::= argument[, argument list ]
241
			argument		::= expression
242
	 */
243
	std::string	symbol;
244
	TokenId		token = TOKENID_INVALID;
2224 sbetterm 245
	while ( readExpression( is, symbol, token, evaluationContext ) )
2218 sbetterm 246
	{
247
		switch ( token )
248
		{
249
		case TOKENID_FUNCTION:
250
			return ( evaluateFunction( is, value, symbol, sideEffect, evaluationContext, path, postponed ) );
251
		case TOKENID_VARIABLE:
252
			return ( evaluateVariable( is, value, symbol, sideEffect, evaluationContext, path, postponed ) );
253
		case TOKENID_CONSTANT:
254
			// Its not a defined variable or function, so just evaluate to
255
			// it.
256
			m_cachedValue = value = m_expression;
257
			return ( true );
258
		}
259
	}
260
 
261
	return ( true );
262
 
263
  //## end FieldExpression::evaluate%420456630303.body
264
}
265
 
266
//## Operation: evaluateFunction%4208AE9D0216
267
const bool FieldExpression::evaluateFunction (std::istream &is, std::string &value, std::string &symbol, const bool &sideEffect, EvaluationContext& evaluationContext, std::vector< DefinedVariable * > &path, bool &postponed)
268
{
269
  //## begin FieldExpression::evaluateFunction%4208AE9D0216.body preserve=yes
270
 
271
	/**
272
	 *	Check parameter lists on all functions calls, and report an error
273
	 *	when a function is called with superfluous arguments.
274
	 */
275
 
276
	postponed = false;
277
	switch ( getFunctionId( symbol ) )
278
	{
279
	case EXPRESSIONID_UDTYPE:
280
		{
281
			AnsiString os;
282
			os.sprintf( "%hu", evaluationContext.getTransaction().getUdType() );
283
			m_cachedValue = value = os.c_str();
284
		}
285
		return ( true );
286
	case EXPRESSIONID_UDSUBTYPE:
287
		{
288
			AnsiString os;
289
			os.sprintf( "%hu", evaluationContext.getTransaction().getUdSubtype() );
290
			m_cachedValue = value = os.c_str();
291
		}
292
		return ( true );
293
	case EXPRESSIONID_TODAY:
294
		m_cachedValue = value = TDateTime::CurrentDateTime().FormatString( "dd-mm-yyyy" ).c_str();
295
		return ( true );
296
	case EXPRESSIONID_FORMATVERSION:
297
		{
298
			AnsiString os;
299
			os.sprintf( "%d", evaluationContext.getTransaction().getFormatVersion() );
300
			m_cachedValue = value = os.c_str();
301
		}
302
		return ( true );
303
	case EXPRESSIONID_NOW:
304
		m_cachedValue = value = TDateTime::CurrentDateTime().FormatString( "dd-mm-yyyy hh:nn:ss" ).c_str();
305
		return ( true );
306
	case EXPRESSIONID_UTCNOW:
307
		{
308
			const TDateTime time = TDateTime::CurrentDateTime() + ( ( _timezone / 3600.0 ) / 24.0 );
309
 
310
			m_cachedValue = value = time.FormatString( "dd-mm-yyyy hh:nn:ss" ).c_str();
311
		}
312
		return ( true );
313
	case EXPRESSIONID_YESTERDAY:
314
		{
315
			const TDateTime time = TDateTime::CurrentDateTime() - 1;
316
 
317
			m_cachedValue = value = time.FormatString( "dd-mm-yyyy" ).c_str();
318
		}
319
		return ( true );
320
	case EXPRESSIONID_TOMORROW:
321
		{
322
			const TDateTime time = TDateTime::CurrentDateTime() + 1;
323
 
324
			m_cachedValue = value = time.FormatString( "dd-mm-yyyy" ).c_str();
325
		}
326
		return ( true );
327
	case EXPRESSIONID_ACCOUNTTYPE:
328
		switch( evaluationContext.getTransaction().getUdType() )
329
		{
330
		case 1:	// Card
331
			value = "2";
332
			break;
333
		case 2:	// Application
334
			value = "1";
335
			break;
336
		case 3:	// Product
337
			value = "3";
338
			break;
339
		case 4:	// Other
340
			value = "4";
341
			break;
342
		case 5:	// Audit
343
			value = "4";
344
			break;
345
		case 6:	// Event
346
			value = "4";
347
			break;
348
		case 7:	// Project
349
			value = "4";
350
			break;
351
		default:
352
			value.erase();
353
			break;
354
		}
355
		m_cachedValue = value;
356
		return ( true );
357
	case EXPRESSIONID_RAND:
358
		{
359
			std::string lowerBound;
360
			std::string upperBound;
361
			if ( skipCharacter( is, '(' ) &&
362
				 readTerm( is, lowerBound ) &&
363
				 skipCharacter( is, ',' ) &&
364
				 readTerm( is, upperBound ) &&
365
				 skipCharacter( is, ')' ) )
366
			{
367
				const int first	= std::min< int >(
368
									atoi( lowerBound.c_str() ),
369
									atoi( upperBound.c_str() ) );
370
				const int last	= std::max< int >(
371
									atoi( lowerBound.c_str() ),
372
									atoi( upperBound.c_str() ) );
373
 
374
				AnsiString os;
375
				os.sprintf( "%d",
376
					int( ( rand() / double( RAND_MAX ) ) *
377
						 ( last - first + 1 ) + first ) );
378
				value = os.c_str();
379
				return ( true );
380
			}
381
			else
382
			{
383
				MERROR( "Cannot parse argument list." );
384
			}
385
		}
386
		break;
387
	case EXPRESSIONID_SEQ:
388
		{
389
			bool persisted = false;
390
			std::string name;
391
			std::string first;
392
			std::string increment;
393
			std::string last;
394
			std::string discriminant;
395
			std::string	fullName;
396
 
397
			/**
398
			 *	SEQ( name, first, increment, last[, discriminant] )
399
			 *	name ::= transient name | # persisted name
400
			 */
401
			if ( skipCharacter( is, '(' ) )
402
			{
403
				persisted = skipCharacter( is, '#' );
404
 
405
				if ( readIdentifier( is, name ) &&
406
					 skipCharacter( is, ',' ) &&
407
					 readTerm( is, first ) &&
408
					 skipCharacter( is, ',' ) &&
409
					 readTerm( is, last ) &&
410
					 skipCharacter( is, ',' ) &&
411
					 readTerm( is, increment ) &&
412
					 ( ( skipCharacter( is, ',' ) &&
413
						 readIdentifier( is, discriminant ) ) ||
414
					   skipCharacter( is, ')' ) ) )
415
				{
416
					if ( discriminant.length() )
417
					{
418
						/**
419
						 *	We have a discriminant, so we evaluate it to form
420
						 *	our name,
421
						 */
422
						FieldExpression subexpression( discriminant );
423
 
424
						std::string discriminantValue;
425
						if ( subexpression.evaluate( discriminantValue, true, evaluationContext, path, postponed ) )
426
						{
427
							AnsiString full;
428
							full.sprintf( "%s[%s]", name.c_str(), discriminantValue.c_str() );
429
							fullName = full.c_str();
430
						}
431
					}
432
					else
433
					{
434
						fullName = name;
435
					}
436
 
437
					Sequence & sequence = evaluationContext.
438
						getSequenceCollection().getSequence(
439
							fullName,
440
							persisted,
441
							atoi( first.c_str() ) );
442
					AnsiString os;
443
					os.sprintf( "%d", sequence.getValue() );
444
					value = os.c_str();
445
 
446
					sequence.incrementValue(
447
						atoi( first.c_str() ),
448
						atoi( last.c_str() ),
449
						atoi( increment.c_str() ) );
450
 
451
					return ( true );
452
				}
453
			}
454
 
455
			MERROR( "Cannot parse argument list." );
456
		}
457
		break;
458
	case EXPRESSIONID_KEYVERSION:
459
		if ( evaluationContext.haveMessageDigest() )
460
		{
461
			AnsiString os;
462
			os.sprintf( "%hu", evaluationContext.getMessageDigest().getKeyVersion() );
463
			value = os.c_str();
464
 
465
			return ( true );
466
		}
467
		break;
468
	case EXPRESSIONID_KEYNUMBER:
469
		if ( evaluationContext.haveMessageDigest() )
470
		{
471
			AnsiString os;
472
			os.sprintf( "%hu", evaluationContext.getMessageDigest().getKeyNumber() );
473
			value = os.c_str();
474
 
475
			return ( true );
476
		}
477
		break;
478
	case EXPRESSIONID_MAC:
479
		/**
480
		 *	We add the schema element to the collection of schema elements to
481
		 *	which we must assign the MAC.  Because we can compute the MAC only
482
		 *	when all fields have been evaluated, this must be postponed, and
483
		 *	until then we must report success.
484
		 */
485
		if ( evaluationContext.haveSchemaElement() )
486
		{
487
			evaluationContext.getTransaction().addMacField(
488
				evaluationContext.getSchemaElement().clone() );
489
			postponed = true;
490
 
491
			return ( true );
492
		}
493
		break;
2222 sbetterm 494
	case EXPRESSIONID_SAMID:
495
		if ( evaluationContext.haveCryptographicServer() )
496
		{
497
			/**
498
			 *	We don't know which module will be used to compute the
499
			 *	MAC (security doesn't tell us), so until they do we
500
			 *	assume its the first module.
501
			 */
502
			if ( evaluationContext.getCryptographicServer().getModuleCount() )
503
			{
504
				AnsiString os;
505
				os.sprintf( "%hu", evaluationContext.getCryptographicServer().getSamId( 0 ) );
506
				value = os.c_str();
507
				return ( true );
508
			}
509
		}
510
		break;
511
	case EXPRESSIONID_SCENARIO_INDEX:
512
		{
513
			AnsiString os;
514
			os.sprintf( "%u", evaluationContext.getScenarioIndex() );
515
			value = os.c_str();
516
		}
517
		return ( true );
2218 sbetterm 518
	default:
2222 sbetterm 519
		MERROR( "Function \"" << symbol << "\" is not implemented." );
2218 sbetterm 520
		break;
521
	}
522
 
523
	return ( false );
524
 
525
  //## end FieldExpression::evaluateFunction%4208AE9D0216.body
526
}
527
 
528
//## Operation: evaluateVariable%420AE22101D7
529
const bool FieldExpression::evaluateVariable (std::istream &is, std::string &value, std::string &symbol, const bool &sideEffect, EvaluationContext& evaluationContext, std::vector< DefinedVariable * > &path, bool &postponed)
530
{
531
  //## begin FieldExpression::evaluateVariable%420AE22101D7.body preserve=yes
532
 
2224 sbetterm 533
	return ( evaluationContext.getSymbolTable().getVariable( symbol, evaluationContext ).
2218 sbetterm 534
				evaluate( value, sideEffect, evaluationContext, path, postponed ) );
535
 
536
  //## end FieldExpression::evaluateVariable%420AE22101D7.body
537
}
538
 
539
//## Operation: getExpression%420AC68F02E4
540
const std::string & FieldExpression::getExpression () const
541
{
542
  //## begin FieldExpression::getExpression%420AC68F02E4.body preserve=yes
543
 
544
	return ( m_expression );
545
 
546
  //## end FieldExpression::getExpression%420AC68F02E4.body
547
}
548
 
549
//## Operation: isFunctor%4209B773036F
550
const bool FieldExpression::isFunctor (const std::string &string)
551
{
552
  //## begin FieldExpression::isFunctor%4209B773036F.body preserve=yes
553
 
554
	PredefinedFunction const * where = 0;
555
 
556
	for ( where = functions; where->functor; ++where )
557
	{
558
		if ( string == where->functor )
559
		{
560
			return ( true );
561
		}
562
	}
563
 
564
	return ( false );
565
 
566
  //## end FieldExpression::isFunctor%4209B773036F.body
567
}
568
 
569
//## Operation: readIdentifier%42102FB70219
570
const bool FieldExpression::readIdentifier (std::istream &is, std::string &identifier)
571
{
572
  //## begin FieldExpression::readIdentifier%42102FB70219.body preserve=yes
573
 
574
	char character = 0;
575
 
576
	identifier.clear();
577
 
578
	is >> std::ws;
579
	if ( is.get( character ).good() )
580
	{
581
		if ( std::isalpha( character ) )
582
		{
583
			do
584
			{
585
				identifier += character;
586
			}
587
			while ( is.get( character ).good() &&
588
					( std::isalnum( character ) || ( character == '_' ) ) );
589
		}
590
 
591
		if ( is.good() )
592
		{
593
			is.putback( character );
594
		}
595
	}
596
 
597
	return ( identifier.length() > 0 );
598
 
599
  //## end FieldExpression::readIdentifier%42102FB70219.body
600
}
601
 
602
//## Operation: readTerm%420B0EB603D2
603
const bool FieldExpression::readTerm (std::istream &is, std::string &term)
604
{
605
  //## begin FieldExpression::readTerm%420B0EB603D2.body preserve=yes
606
 
607
	char character = 0;
608
 
609
	term.clear();
610
 
611
	is >> std::ws;
612
	if ( is.get( character ).good() )
613
	{
614
		const bool quoted = ( character == '\"' );
615
		if ( std::isalnum( character ) || ( character == '-' ) || quoted )
616
		{
617
			do
618
			{
619
				term += character;
620
			}
621
			while ( is.get( character ).good() && std::isalnum( character ) );
622
		}
623
 
624
		if ( is.good() && ( !quoted || character != '\"' ) )
625
		{
626
			is.putback( character );
627
		}
628
	}
629
 
630
	return ( term.length() > 0 );
631
 
632
  //## end FieldExpression::readTerm%420B0EB603D2.body
633
}
634
 
635
//## Operation: setExpression%420AC68F02F3
636
const std::string & FieldExpression::setExpression (const std::string &value)
637
{
638
  //## begin FieldExpression::setExpression%420AC68F02F3.body preserve=yes
639
 
640
	return ( m_expression = value );
641
 
642
  //## end FieldExpression::setExpression%420AC68F02F3.body
643
}
644
 
645
//## Operation: skipCharacter%420B100701E7
646
const bool FieldExpression::skipCharacter (std::istream &is, const char &character)
647
{
648
  //## begin FieldExpression::skipCharacter%420B100701E7.body preserve=yes
649
 
650
	char c = 0;
651
	is >> std::ws >> c;
652
 
653
	if ( is.good() )
654
	{
655
		if ( c == character )
656
		{
657
			return ( true );
658
		}
659
 
660
		is.putback( c );
661
	}
662
 
663
	return ( false );
664
 
665
  //## end FieldExpression::skipCharacter%420B100701E7.body
666
}
667
 
668
// Additional Declarations
669
  //## begin FieldExpression%420AC16002C1.declarations preserve=yes
670
  //## end FieldExpression%420AC16002C1.declarations
671
 
672
//## begin module%420AC16002C1.epilog preserve=yes
673
//## end module%420AC16002C1.epilog