summaryrefslogtreecommitdiff
path: root/TAO/orbsvcs/orbsvcs/Trader/Constraint_Visitors.h
blob: fd204d641534147cea521dc66841cd8929f87128 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
/* -*- C++ -*- */

//=============================================================================
/**
 *  @file Constraint_Visitors.h
 *
 *  $Id$
 *
 *  @author Seth Widoff <sbw1@cs.wustl.edu>
 */
//=============================================================================


#ifndef TAO_CONSTRAINT_VISITOR_H
#define TAO_CONSTRAINT_VISITOR_H
#include /**/ "ace/pre.h"

#include "orbsvcs/Trader/Interpreter_Utils.h"
#include "orbsvcs/Trader/trading_serv_export.h"
#include "ace/Containers.h"

class TAO_DynSequence_i;

class TAO_Constraint;
class TAO_Unary_Constraint;
class TAO_Binary_Constraint;
class TAO_Literal_Constraint;
class TAO_Property_Constraint;
class TAO_Noop_Constraint;

/**
 * @class TAO_Constraint_Visitor
 *
 * @brief This is the base class for all visitors who wish to preform
 * some operation from the state of the expression tree. Using
 * double dispatching, subclasses of Constraint expression call
 * back to the InterpreterVisitor subclass from the accept
 * method.
 *
 * Traversal of the expression tree uses the "Visitor"
 * pattern. To "visit" a node, a client invokes the "accept"
 * method on a subclass of ConstraintExpression, which, in turn,
 * invokes the appropriate method on the visitor passed to it,
 * based on its own type. So, the Constraint_Visitor has a
 * method to deal with each possible type of node in an
 * expression tree; one for each operator in the grammar.
 */
class TAO_Trading_Serv_Export TAO_Constraint_Visitor
{
public:

  virtual ~TAO_Constraint_Visitor (void) {}

  virtual int visit_constraint (TAO_Unary_Constraint* constraint) = 0;

  virtual int visit_with (TAO_Unary_Constraint* unary_with) = 0;
  virtual int visit_min (TAO_Unary_Constraint* unary_min) = 0;
  virtual int visit_max (TAO_Unary_Constraint* unary_max) = 0;
  virtual int visit_first (TAO_Noop_Constraint* noop_first) = 0;
  virtual int visit_random (TAO_Noop_Constraint* noop_random) = 0;

  virtual int visit_and (TAO_Binary_Constraint* boolean_and) = 0;
  virtual int visit_or (TAO_Binary_Constraint* boolean_or) = 0;
  virtual int visit_not (TAO_Unary_Constraint* unary_not) = 0;

  virtual int visit_exist (TAO_Unary_Constraint* unary_exist) = 0;
  virtual int visit_unary_minus (TAO_Unary_Constraint* unary_minus) = 0;

  virtual int visit_add (TAO_Binary_Constraint* boolean_add) = 0;
  virtual int visit_sub (TAO_Binary_Constraint* boolean_sub) = 0;
  virtual int visit_mult (TAO_Binary_Constraint* boolean_mult) = 0;
  virtual int visit_div (TAO_Binary_Constraint* boolean_div) = 0;

  virtual int visit_twiddle (TAO_Binary_Constraint* binary_twiddle) = 0;
  virtual int visit_in (TAO_Binary_Constraint* binary_in) = 0;

  virtual int visit_less_than (TAO_Binary_Constraint* boolean_lt) = 0;
  virtual int visit_less_than_equal (TAO_Binary_Constraint* boolean_lte) = 0;
  virtual int visit_greater_than (TAO_Binary_Constraint* boolean_gt) = 0;
  virtual int visit_greater_than_equal (TAO_Binary_Constraint* boolean_gte) = 0;
  virtual int visit_equal (TAO_Binary_Constraint* boolean_eq) = 0;
  virtual int visit_not_equal (TAO_Binary_Constraint* boolean_neq) = 0;

  virtual int visit_literal (TAO_Literal_Constraint* literal) = 0;
  virtual int visit_property (TAO_Property_Constraint* literal) = 0;
};

#include "orbsvcs/Trader/Constraint_Nodes.h"

/**
 * @class TAO_Constraint_Validator
 *
 * @brief TAO_Constraint_Validator ensures that in an expression tree
 * passed to it, the operands of each operation match the
 * correct types.
 *
 * TAO_Constraint_Validator uses the visitor pattern to
 * traverse all the nodes in an expression tree, checking that
 * for each operator node the operands are of the proper data
 * type it they're literals, or that they exist in the service
 * type definition _and_ have the proper type, if they're
 * property names. The algorithm for type
 * checking is as follows: ensure that operand expression(s)
 * return the correct types using expr_returns* methods. If they
 * (or it) return the correct types, call accept
 * on each operand until all return true or one returns false,
 * at which point we can back out of the traversal and indicate
 * failure.
 */
class TAO_Trading_Serv_Export TAO_Constraint_Validator : public TAO_Constraint_Visitor
{
public:
  /// Constructor.
  TAO_Constraint_Validator (void);

  /// Destructor.
  virtual ~TAO_Constraint_Validator (void);

  /**
   * Validate returns 1 if the expression tree whose root is <root>
   * makes semantic sense, in that the operands for each operation
   * comply with each other and the types accepted by the operator.
   */
  int validate (TAO_Constraint* root);

  // = Visitor Methods

  virtual int visit_constraint (TAO_Unary_Constraint* constraint);

  virtual int visit_with (TAO_Unary_Constraint* unary_with);
  virtual int visit_min (TAO_Unary_Constraint* unary_min);
  virtual int visit_max (TAO_Unary_Constraint* unary_max);
  virtual int visit_first (TAO_Noop_Constraint* noop_first);
  virtual int visit_random (TAO_Noop_Constraint* noop_random);

  /// The two operands must return a boolean value.
  virtual int visit_and (TAO_Binary_Constraint* boolean_and);
  virtual int visit_or (TAO_Binary_Constraint* boolean_or);

  /// The operand must return a boolean value.
  virtual int visit_not (TAO_Unary_Constraint* unary_not);

  /// The operand must return a valid  (i.e., present in the service
  /// type description) property name.
  virtual int visit_exist (TAO_Unary_Constraint* unary_exist);

  /// The operand must return a number to be negated.
  virtual int visit_unary_minus (TAO_Unary_Constraint* unary_minus);

  /// Both operands must return numeric results.
  virtual int visit_add (TAO_Binary_Constraint* boolean_add);
  virtual int visit_sub (TAO_Binary_Constraint* boolean_sub);
  virtual int visit_mult (TAO_Binary_Constraint* boolean_mult);
  virtual int visit_div (TAO_Binary_Constraint* boolean_div);

  /// Both operands must return strings.
  virtual int visit_twiddle (TAO_Binary_Constraint* binary_twiddle);

  /// The right operand must be a sequence of the same simple type as
  /// the left operand.
  virtual int visit_in (TAO_Binary_Constraint* binary_in);

  /// The left and right operands must both be of the same simple type.
  virtual int visit_less_than (TAO_Binary_Constraint* boolean_lt);
  virtual int visit_less_than_equal (TAO_Binary_Constraint* boolean_lte);
  virtual int visit_greater_than (TAO_Binary_Constraint* boolean_gt);
  virtual int visit_greater_than_equal (TAO_Binary_Constraint* boolean_gte);
  virtual int visit_equal (TAO_Binary_Constraint* boolean_eq);
  virtual int visit_not_equal (TAO_Binary_Constraint* boolean_neq);

  /// The property must be defined in the service type description.
  virtual int visit_literal (TAO_Literal_Constraint* literal);
  virtual int visit_property (TAO_Property_Constraint* literal);

protected:

  /// A map gleaned from the ServiceTypeStruct, which correlates
  /// property names with their types.
  TAO_Typecode_Table type_map_;

private:

  CORBA::TypeCode* extract_type (TAO_Constraint* expr_type,
                                 TAO_Expression_Type& type);

  /// expr_returns_boolean returns 1 if <expr_type>, when evaluated, will
  /// return a boolean.
  int expr_returns_boolean (TAO_Expression_Type expr_type);

  /// expr_returns_boolean returns 1 if <expr_type>, when evaluated, will
  /// return a number.
  int expr_returns_number (TAO_Expression_Type expr_type);

  /// expr_returns_boolean returns 1 if <expr_type>, when evaluated, will
  /// return a string.
  int expr_returns_string (TAO_Expression_Type expr_type);

  TAO_Constraint_Validator (const TAO_Constraint_Validator&);
  TAO_Constraint_Validator& operator= (const TAO_Constraint_Validator&);
};

/**
 * @class TAO_Constraint_Evaluator
 *
 * @brief TAO_Constraint_Evaluator traverse a constraint expression
 * tree, and determines whether an offer fits the constraints
 * represented by the tree
 *
 * Using the Visitor pattern, the TAO_Constraint_Evaluator has
 * each node of the expression tree call back to it with the
 * method designated for its type. In that method, the visitor
 * will evaluate its operands and perform the operation
 * designated by that node's type, and return the result. Note:
 * the TAO_Constraint_Evaluator assumes the tree is semantically
 * correct, that is, the validate method on
 * TAO_Constraint_Validator return true. The only possible
 * evaluation time errors are a divide by a property whose value
 * is zero and undefined properties.
 */
class TAO_Trading_Serv_Export TAO_Constraint_Evaluator : public TAO_Constraint_Visitor
{
public:

  /// Constructor.
  TAO_Constraint_Evaluator (void);

  /**
   * Evaluate returns 1 if the offer satisfies the constraints
   * represented by the the expression tree rooted at <root>, 0 if it
   * doesn't. If an error occurs during process, the constraint
   * automatically fails.
   */
  CORBA::Boolean evaluate_constraint (TAO_Constraint* root);

  /// The result of the preference evaluation is stored in result. The
  /// method returns 0 upon success, -1 upon failure.
  int evaluate_preference (TAO_Constraint* root,
                           TAO_Literal_Constraint& result);

  // = Visitor Methods

  virtual int visit_constraint (TAO_Unary_Constraint* constraint);

  virtual int visit_with (TAO_Unary_Constraint* unary_with);
  virtual int visit_min (TAO_Unary_Constraint* unary_min);
  virtual int visit_max (TAO_Unary_Constraint* unary_max);
  virtual int visit_first (TAO_Noop_Constraint* noop_first);
  virtual int visit_random (TAO_Noop_Constraint* noop_random);

  /**
   * Takes the logical and of the results of both operands. Note that
   * in the case where the left operand returns zero, the result is
   * immediately known.
   */
  virtual int visit_and (TAO_Binary_Constraint* boolean_and);

  /**
   * Takes the logical or of the results of both operands. Note that
   * in the case where the left operand returns one, the result is
   * immediately known.
   */
  virtual int visit_or (TAO_Binary_Constraint* boolean_or);

  /// Logically negates the value of the operand.
  virtual int visit_not (TAO_Unary_Constraint* unary_not);

  /// The property exists if its name is bound to a value in the
  /// <props_> map.
  virtual int visit_exist (TAO_Unary_Constraint* unary_exist);

  /// Mathematically negates the return value the operand.
  virtual int visit_unary_minus (TAO_Unary_Constraint* unary_minus);

  /// Add the results of evaluating the left and right operands.
  virtual int visit_add (TAO_Binary_Constraint* boolean_add);

  /// Subtract the results of evaluating the left and right operands.
  virtual int visit_sub (TAO_Binary_Constraint* boolean_sub);

  /// Multiply the results of evaluating the left and right operands.
  virtual int visit_mult (TAO_Binary_Constraint* boolean_mult);

  /// Divide the results of evaluating the left and right operands.
  virtual int visit_div (TAO_Binary_Constraint* boolean_div);

  /// Determines if the right operand is a substring of the left.
  virtual int visit_twiddle (TAO_Binary_Constraint* binary_twiddle);

  /// Determines if the sequence represented by the right operand
  /// contains the left operand.
  virtual int visit_in (TAO_Binary_Constraint* binary_in);

  // = Compare the results of evaluating left and right operands.
  virtual int visit_less_than (TAO_Binary_Constraint* boolean_lt);
  virtual int visit_less_than_equal (TAO_Binary_Constraint* boolean_lte);
  virtual int visit_greater_than (TAO_Binary_Constraint* boolean_gt);
  virtual int visit_greater_than_equal (TAO_Binary_Constraint* boolean_gte);
  virtual int visit_equal (TAO_Binary_Constraint* boolean_eq);
  virtual int visit_not_equal (TAO_Binary_Constraint* boolean_neq);

  /// Copy the value of the literal into the result container.
  virtual int visit_literal (TAO_Literal_Constraint* literal);

  /// Copy the value of the property into the result container.
  virtual int visit_property (TAO_Property_Constraint* literal);

private:

  class TAO_Trading_Serv_Export Operand_Queue :
    public ACE_Unbounded_Queue <TAO_Literal_Constraint>
  // = TITLE
  // A queue adapter with methods to setting and getting operands
  // from the expression evaluation results.
  {
  public:

    Operand_Queue  (void);

    /// In a binary operation, obtain the left operand.
    TAO_Literal_Constraint& get_left_operand (void);

    /// In a binary operation, obtain the right operand.
    TAO_Literal_Constraint& get_right_operand (void);

    /// In a unary operation, obtain the only operand.
    TAO_Literal_Constraint& get_operand (void);

    /// Remove an operand from the queue.
    void dequeue_operand (void);
  };

  /// Method for performing a arithmetic or comparison operation.
  void do_the_op (int operation);

  /// Method for evaluating a binary operation.
  int visit_bin_op (TAO_Binary_Constraint* op, int operation);

  /// Determine if sequence contains <element>, a literal of the same
  /// simple type as <sequence_type>. Return 1 in this eventuality.
  CORBA::Boolean sequence_does_contain (CORBA::Any* sequence,
                                        TAO_Literal_Constraint& element);

  /// Disallow copying.
  TAO_Constraint_Evaluator (const TAO_Constraint_Evaluator&);
  TAO_Constraint_Evaluator& operator= (const TAO_Constraint_Evaluator&);

protected:

  /// The map of property names to their values for a property.
  TAO_Lookup_Table props_;

  /// The result of a non_boolean operation.
  Operand_Queue queue_;
};

// Forward declaration
template <class ELEMENT_TYPE> class TAO_Element_Equal;

ACE_TEMPLATE_SPECIALIZATION
class TAO_Element_Equal<CORBA::Short>
{
public:
  /// Calls the correct method on dyn_seq to extract the element type,
  /// then uses the appropriate form of equals comparison.
  int operator () (TAO_DynSequence_i& dyn_any,
                   CORBA::Short element) const;
};

ACE_TEMPLATE_SPECIALIZATION
class TAO_Element_Equal<CORBA::UShort>
{
public:
  /// Calls the correct method on dyn_seq to extract the element type,
  /// then uses the appropriate form of equals comparison.
  int operator () (TAO_DynSequence_i& dyn_any,
                   CORBA::UShort element) const;
};

ACE_TEMPLATE_SPECIALIZATION
class TAO_Element_Equal<CORBA::Long>
{
public:
  /// Calls the correct method on dyn_seq to extract the element type,
  /// then uses the appropriate form of equals comparison.
  int operator () (TAO_DynSequence_i& dyn_any,
                   CORBA::Long element) const;
};

ACE_TEMPLATE_SPECIALIZATION
class TAO_Element_Equal<CORBA::ULong>
{
public:
  /// Calls the correct method on dyn_seq to extract the element type, then
  /// uses the appropriate form of equals comparison.
  int operator () (TAO_DynSequence_i& dyn_any,
                   CORBA::ULong element) const;

};

ACE_TEMPLATE_SPECIALIZATION
class TAO_Element_Equal<CORBA::Float>
{
public:
  /// Calls the correct method on dyn_seq to extract the element type,
  /// then uses the appropriate form of equals comparison.
  int operator () (TAO_DynSequence_i& dyn_any,
                   CORBA::Float element) const;
};

ACE_TEMPLATE_SPECIALIZATION
class TAO_Element_Equal<CORBA::Double>
{
public:
  /// Calls the correct method on dyn_seq to extract the element type,
  /// then uses the appropriate form of equals comparison.
  int operator () (TAO_DynSequence_i& dyn_any,
                   CORBA::Double element) const;
};

ACE_TEMPLATE_SPECIALIZATION
class TAO_Element_Equal<CORBA::Boolean>
{
public:
  /// Calls the correct method on dyn_seq to extract the element type,
  /// then uses the appropriate form of equals comparison.
  int operator () (TAO_DynSequence_i& dyn_any,
                   CORBA::Boolean element) const;
};

ACE_TEMPLATE_SPECIALIZATION
class TAO_Element_Equal<const char*>
{
public:
  /// Calls the correct method on dyn_seq to extract the element type,
  /// then uses the appropriate form of equals comparison.
  int operator () (TAO_DynSequence_i& dyn_any,
                   const char* element) const;
};

#include /**/ "ace/post.h"
#endif /* CONSTRAINT_VISITORS_H */