Subversion Repositories DevTools

Rev

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