diff options
Diffstat (limited to 'trunk/TAO/orbsvcs/orbsvcs/Log/Log_Constraint_Visitors.cpp')
-rw-r--r-- | trunk/TAO/orbsvcs/orbsvcs/Log/Log_Constraint_Visitors.cpp | 1352 |
1 files changed, 1352 insertions, 0 deletions
diff --git a/trunk/TAO/orbsvcs/orbsvcs/Log/Log_Constraint_Visitors.cpp b/trunk/TAO/orbsvcs/orbsvcs/Log/Log_Constraint_Visitors.cpp new file mode 100644 index 00000000000..6c8b55d4d88 --- /dev/null +++ b/trunk/TAO/orbsvcs/orbsvcs/Log/Log_Constraint_Visitors.cpp @@ -0,0 +1,1352 @@ +#include "orbsvcs/Log/Log_Constraint_Visitors.h" + +#include "orbsvcs/ETCL/ETCL_Constraint.h" +#include "orbsvcs/ETCL/ETCL_y.h" + +#include "tao/DynamicAny/DynArray_i.h" +#include "tao/DynamicAny/DynSequence_i.h" +#include "tao/DynamicAny/DynStruct_i.h" +#include "tao/DynamicAny/DynUnion_i.h" +#include "tao/DynamicAny/DynEnum_i.h" +#include "tao/DynamicAny/DynAnyFactory.h" +#include "tao/DynamicAny/DynAnyUtils_T.h" + +#include "tao/AnyTypeCode/Any_Unknown_IDL_Type.h" +#include "tao/CDR.h" + +ACE_RCSID (Log, + Log_Constraint_Visitors, + "$Id$") + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_Log_Constraint_Visitor::TAO_Log_Constraint_Visitor (const DsLogAdmin::LogRecord &rec) + : property_lookup_ (property_lookup_size_) +{ + CORBA::Any val_id; +#if defined (ACE_LACKS_LONGLONG_T) || defined (ACE_LACKS_UNSIGNEDLONGLONG_T) + val_id <<= ACE_U64_TO_U32 (rec.id); +#else + val_id <<= static_cast<ACE_UINT32> (rec.id); +#endif + this->property_lookup_.bind (ACE_CString("id", 0, 0), val_id); + + + CORBA::Any val_time; +#if defined (ACE_LACKS_LONGLONG_T) || defined (ACE_LACKS_UNSIGNEDLONGLONG_T) + val_time <<= ACE_U64_TO_U32 (rec.time); +#else + val_time <<= static_cast<ACE_UINT32> (rec.time); +#endif + this->property_lookup_.bind (ACE_CString("time", 0, 0), val_time); + + this->property_lookup_.bind (ACE_CString("info", 0, 0), rec.info); + + // Bind an entry for each item in the record's attribute list. + CORBA::Long len = rec.attr_list.length(); + for (CORBA::Long i = 0; i < len; ++i) + { + this->property_lookup_.bind (ACE_CString(rec.attr_list[i].name, + 0, + 0), + rec.attr_list[i].value); + } +} + +CORBA::Boolean +TAO_Log_Constraint_Visitor::evaluate_constraint (TAO_ETCL_Constraint* root) +{ + CORBA::Boolean result = 0; + this->queue_.reset (); + + // Evaluate the constraint in root_; + if (root != 0) + { + if ((root->accept (this) == 0) && + (! this->queue_.is_empty ())) + { + TAO_ETCL_Literal_Constraint top; + this->queue_.dequeue_head (top); + result = (CORBA::Boolean) top; + } + } + + // If a property couldn't be evaluated we must return 0. + return result; +} + +int +TAO_Log_Constraint_Visitor::visit_literal ( + TAO_ETCL_Literal_Constraint *literal + ) +{ + this->queue_.enqueue_head (*literal); + return 0; +} + +int +TAO_Log_Constraint_Visitor::visit_identifier (TAO_ETCL_Identifier *ident) +{ + int return_value = -1; + const char *name = ident->value (); + ACE_CString key (name, 0, 0); + + CORBA::Any any; + + if (this->property_lookup_.find (key, any) == 0) + { + if (any.impl() != 0) + { + this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (&any)); + return_value = 0; + } + } + + return return_value; +} + +int +TAO_Log_Constraint_Visitor::visit_union_value ( + TAO_ETCL_Union_Value *union_value + ) +{ + switch (union_value->sign ()) + { + case 0: + this->queue_.enqueue_head (*union_value->string ()); + break; + case -1: + this->queue_.enqueue_head (-(*union_value->integer ())); + break; + case 1: + this->queue_.enqueue_head (*union_value->integer ()); + break; + default: + return -1; + } + + return 0; +} + +int +TAO_Log_Constraint_Visitor::visit_union_pos ( + TAO_ETCL_Union_Pos *union_pos + ) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + if (union_pos->union_value ()->accept (this) == 0) + { + TAO_ETCL_Literal_Constraint disc_val; + this->queue_.dequeue_head (disc_val); + + TAO_DynUnion_i dyn_union; + dyn_union.init (this->current_member_.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + CORBA::TypeCode_var tc = this->current_member_->type (); + + switch (disc_val.expr_type ()) + { + case TAO_ETCL_INTEGER: + case TAO_ETCL_SIGNED: + case TAO_ETCL_UNSIGNED: + { + CORBA::Any disc_any; + CORBA::TypeCode_var disc_tc = + tc->discriminator_type (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + CORBA::TCKind disc_kind = + TAO_DynAnyFactory::unalias (disc_tc.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + switch (disc_kind) + { + case CORBA::tk_boolean: + disc_any <<= CORBA::Any::from_boolean ((CORBA::Boolean) disc_val); + break; + case CORBA::tk_short: + disc_any <<= (CORBA::Short) ((CORBA::Long) disc_val); + break; + case CORBA::tk_ushort: + disc_any <<= (CORBA::UShort) ((CORBA::ULong) disc_val); + break; + case CORBA::tk_long: + disc_any <<= (CORBA::Long) disc_val; + break; + case CORBA::tk_ulong: + disc_any <<= (CORBA::ULong) disc_val; + break; + case CORBA::tk_enum: + { + TAO_OutputCDR cdr; + cdr.write_ulong ((CORBA::ULong) disc_val); + TAO_InputCDR in_cdr (cdr); + TAO::Unknown_IDL_Type *unk = 0; + ACE_NEW_RETURN (unk, + TAO::Unknown_IDL_Type ( + disc_tc.in (), + in_cdr + ), + -1); + + disc_any.replace (unk); + break; + } + // @@@ (JP) I don't think ETCL handles 64-bit + // integers at this point, and I also think that + // chars and/or wchars will just come out in the + // constraint as (w)strings of length 1. + case CORBA::tk_longlong: + case CORBA::tk_ulonglong: + case CORBA::tk_char: + case CORBA::tk_wchar: + default: + return -1; + } + + DynamicAny::DynAny_var dyn_any = + TAO::MakeDynAnyUtils::make_dyn_any_t<const CORBA::Any &> ( + disc_tc.in (), + disc_any + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + dyn_union.set_discriminator (dyn_any.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + DynamicAny::DynAny_var u_member = + dyn_union.member (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->current_member_ = + u_member->to_any (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + break; + } + case TAO_ETCL_STRING: + { + const char *name = (const char *) disc_val; + CORBA::ULong count = + tc->member_count (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + const char *member_name = 0; + CORBA::ULong i = 0; + + for (i = 0; i < count; ++i) + { + member_name = tc->member_name (i + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (ACE_OS::strcmp (name, member_name) == 0) + { + break; + } + } + + // If there's no match, member_label will throw + // CORBA::TypeCode::Bounds and the catch block will + // return -1; + this->current_member_ = tc->member_label (i + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + break; + } + // The TAO_ETCL_Union_Value that was put on the queue + // shouldn't have any other type. + default: + return -1; + } + + TAO_ETCL_Constraint *nested = union_pos->component (); + + // If there's no nested component, then we just want the + // union member value on the queue. Otherwise, we want + // the member value in current_member_ while we visit + // the nested component. + if (nested == 0) + { + TAO_ETCL_Literal_Constraint lit (this->current_member_.ptr ()); + this->queue_.enqueue_head (lit); + return 0; + } + else + { + return nested->accept (this); + } + } + else + { + return -1; + } + } + ACE_CATCHANY + { + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); +} + +int +TAO_Log_Constraint_Visitor::visit_component_pos (TAO_ETCL_Component_Pos *pos) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + // If we are here (from visit_component) the Any containing the + // component as found in property_lookup_ will be in current_member_. + CORBA::TypeCode_var tc = this->current_member_->type (); + CORBA::TCKind kind = TAO_DynAnyFactory::unalias (tc.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + DynamicAny::DynAny_var member; + CORBA::Boolean success = 0; + CORBA::ULong slot = (CORBA::ULong) *pos->integer (); + + switch (kind) + { + case CORBA::tk_enum: + { + TAO_DynEnum_i dyn_enum; + dyn_enum.init (this->current_member_.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + success = dyn_enum.seek (slot + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (success == 0) + { + return -1; + } + + member = + dyn_enum.current_component (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + break; + } + case CORBA::tk_struct: + { + TAO_DynStruct_i dyn_struct; + dyn_struct.init (this->current_member_.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + success = dyn_struct.seek (slot + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (success == 0) + { + return -1; + } + + member = dyn_struct.current_component (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + break; + } + // @@@ (JP) I think enums and structs are the only two cases handled + // by Component_Pos, since arrays and sequences are handled by + // Component_Array, and unions are handled by Union_Pos. + default: + return -1; + } + + CORBA::Any_var value = member->to_any (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + TAO_ETCL_Constraint *comp = pos->component (); + + if (comp == 0) + { + TAO_ETCL_Literal_Constraint result (value.ptr ()); + this->queue_.enqueue_head (result); + return 0; + } + else + { + this->current_member_ = value._retn (); + return comp->accept (this); + } + } + ACE_CATCHANY + { + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); +} + +int +TAO_Log_Constraint_Visitor::visit_component_assoc ( + TAO_ETCL_Component_Assoc *assoc) +{ + // @@@ (JP) The spec reserves this type of constraint for NVLists. + // Since NVLists don't have type codes or Any operators, there's + // no way that TAO can put one into the event's filterable data. + // However, from the looks of the ETCL grammar, I believe that a + // contruct like 'exist $(foo)' is legal, and is in effect using + // the event's filterable data as one big NVList. It is + // equivalent to '$.foo'. I've implemented this method on that + // basis, while keeping in mind that a clearer interpretation of + // the spec may come along someday. + + CORBA::Any any; + ACE_CString key (assoc->identifier ()->value (), + 0, + 0); + + if (this->property_lookup_.find (key, any) != 0 + || any.impl () == 0) + { + return -1; + } + + TAO_ETCL_Constraint *comp = assoc->component (); + CORBA::Any *any_ptr = 0; + + if (comp == 0) + { + TAO_ETCL_Literal_Constraint result (&any); + this->queue_.enqueue_head (result); + return 0; + } + + ACE_NEW_RETURN (any_ptr, + CORBA::Any (any), + -1); + this->current_member_ = any_ptr; + return comp->accept (this); +} + +int +TAO_Log_Constraint_Visitor::visit_component_array ( + TAO_ETCL_Component_Array *array + ) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + // If we are here (from visit_component) the Any containing the + // component as found in property_lookup_ will be in current_member_. + CORBA::TypeCode_var tc = this->current_member_->type (); + CORBA::TCKind kind = TAO_DynAnyFactory::unalias (tc.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + DynamicAny::DynAny_var member; + CORBA::Boolean success = 0; + CORBA::ULong slot = (CORBA::ULong) *array->integer (); + + switch (kind) + { + case CORBA::tk_array: + { + TAO_DynEnum_i dyn_array; + dyn_array.init (this->current_member_.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + success = dyn_array.seek (slot + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (success == 0) + { + return -1; + } + + member = dyn_array.current_component (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + break; + } + case CORBA::tk_sequence: + { + TAO_DynStruct_i dyn_sequence; + dyn_sequence.init (this->current_member_.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + success = dyn_sequence.seek (slot + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (success == 0) + { + return -1; + } + + member = + dyn_sequence.current_component (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + break; + } + // Enums and sequences are the only two cases handled + // by Component_Array. + default: + return -1; + } + + CORBA::Any_var value = member->to_any (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + TAO_ETCL_Constraint *comp = array->component (); + + if (comp == 0) + { + TAO_ETCL_Literal_Constraint result (value.ptr ()); + this->queue_.enqueue_head (result); + return 0; + } + else + { + this->current_member_ = value._retn (); + return comp->accept (this); + } + } + ACE_CATCHANY + { + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); +} + +int +TAO_Log_Constraint_Visitor::visit_special (TAO_ETCL_Special *special) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + CORBA::TypeCode_var tc = this->current_member_->type (); + + switch (special->type ()) + { + case TAO_ETCL_LENGTH: + { + // If the TCKind is not a sequence or an array, the + // call to length() will raise an exception, and the + // catch block will return -1; + CORBA::ULong length = tc->length (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + TAO_ETCL_Literal_Constraint lit (length); + this->queue_.enqueue_head (lit); + return 0; + } + case TAO_ETCL_DISCRIMINANT: + { + // If the TCKind is not a union, the + // call to init() will raise an exception, and the + // catch block will return -1; + TAO_DynUnion_i dyn_union; + dyn_union.init (this->current_member_.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + DynamicAny::DynAny_var disc = + dyn_union.get_discriminator (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + CORBA::Any_var disc_any = disc->to_any (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + TAO_ETCL_Literal_Constraint lit (disc_any.ptr ()); + this->queue_.enqueue_head (lit); + return 0; + } + case TAO_ETCL_TYPE_ID: + { + const char *name = tc->name (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + TAO_ETCL_Literal_Constraint lit (name); + this->queue_.enqueue_head (lit); + return 0; + } + case TAO_ETCL_REPOS_ID: + { + const char *id = tc->id (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + TAO_ETCL_Literal_Constraint lit (id); + this->queue_.enqueue_head (lit); + return 0; + } + default: + return -1; + } + } + ACE_CATCHANY + { + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); +} + +int +TAO_Log_Constraint_Visitor::visit_component ( + TAO_ETCL_Component *component + ) +{ + // If this component has no sub-component, only an identifier, + // then we just visit the identifier, which puts a literal on + // the queue to be handled upon returning from this method call. + // If there is a sub-component, we store the literal's value + // in our member _var for possible examination at a more + // nested level, and visit the sub-component. + + TAO_ETCL_Constraint *nested = component->component (); + int result = component->identifier ()->accept (this); + + if (nested == 0 || result != 0) + { + return result; + } + else + { + TAO_ETCL_Literal_Constraint id; + this->queue_.dequeue_head (id); + CORBA::Any *any_ptr = 0; + ACE_NEW_RETURN (any_ptr, + CORBA::Any (*(const CORBA::Any *) id), + -1); + this->current_member_ = any_ptr; + return nested->accept (this); + } +} + +int +TAO_Log_Constraint_Visitor::visit_dot (TAO_ETCL_Dot *dot) +{ + // If we are here, we know we're headed for a more nested + // level, so we just visit it, there's nothing else in this + // constraint. + return dot->component ()->accept (this); +} + +int +TAO_Log_Constraint_Visitor::visit_eval (TAO_ETCL_Eval *eval) +{ + // Nothing to do but visit the contained component. + return eval->component ()->accept (this); +} + +int +TAO_Log_Constraint_Visitor::visit_default (TAO_ETCL_Default *def) +{ + TAO_ETCL_Constraint *comp = def->component (); + + if (comp == 0) + { + return -1; + } + + if (comp->accept (this) != 0) + { + return -1; + } + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + CORBA::TypeCode_var tc = this->current_member_->type (); + + // If the current member is not a union, this call will + // throw BadKind and the catch block will return -1. + CORBA::Long default_index = tc->default_index (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + // No default index. + if (default_index == -1) + { + TAO_ETCL_Literal_Constraint result ((CORBA::Boolean) 0); + this->queue_.enqueue_head (result); + return 0; + } + + // Okay, there's a default index, but is it active? + + TAO_ETCL_Literal_Constraint disc; + this->queue_.dequeue_head (disc); + TAO_ETCL_Literal_Constraint default_index_value (default_index); + return (disc == default_index_value); + } + ACE_CATCHANY + { + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); +} + +int +TAO_Log_Constraint_Visitor::visit_exist (TAO_ETCL_Exist *exist) +{ + TAO_ETCL_Constraint *component = exist->component (); + + if (component->accept (this) == 0) + { + TAO_ETCL_Literal_Constraint top; + + this->queue_.dequeue_head (top); + + const char *value = (const char *) top; + ACE_CString key (value, 0, 0); + + CORBA::Boolean result = (this->property_lookup_.find (key) == 0); + + this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result)); + + return 0; + } + + return -1; +} + +int +TAO_Log_Constraint_Visitor::visit_unary_expr ( + TAO_ETCL_Unary_Expr *unary_expr + ) +{ + TAO_ETCL_Constraint *subexpr = unary_expr->subexpr (); + + if (subexpr->accept (this) == 0) + { + TAO_ETCL_Literal_Constraint subexpr_result; + CORBA::Boolean result = 0; + int op_type = unary_expr->type (); + + switch (op_type) + { + case TAO_ETCL_NOT: + this->queue_.dequeue_head (subexpr_result); + result = ! (CORBA::Boolean) subexpr_result; + this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result)); + return 0; + case TAO_ETCL_MINUS: + // The leading '-' was parsed separately, so we have to pull + // the literal constraint off the queue, apply the class' own + // unary minus operator, and put it back. + this->queue_.dequeue_head (subexpr_result); + this->queue_.enqueue_head (-subexpr_result); + return 0; + case TAO_ETCL_PLUS: + // Leave the literal constraint on the queue. The leading + // '+' was just syntactic sugar - no action is necessary. + return 0; + default: + // The parser should never construct a TAO_ETCL_Unary_Constraint + // behind any operators except the above three. + return -1; + } + } + + return -1; +} + +int +TAO_Log_Constraint_Visitor::visit_binary_expr ( + TAO_ETCL_Binary_Expr *binary_expr + ) +{ + + // Evaluate the constraint + int bin_op_type = binary_expr->type (); + + switch (bin_op_type) + { + case TAO_ETCL_OR: + return this->visit_or (binary_expr); + case TAO_ETCL_AND: + return this->visit_and (binary_expr); + case TAO_ETCL_LT: + case TAO_ETCL_LE: + case TAO_ETCL_GT: + case TAO_ETCL_GE: + case TAO_ETCL_EQ: + case TAO_ETCL_NE: + case TAO_ETCL_PLUS: + case TAO_ETCL_MINUS: + case TAO_ETCL_MULT: + case TAO_ETCL_DIV: + return this->visit_binary_op (binary_expr, + bin_op_type); + case TAO_ETCL_TWIDDLE: + return this->visit_twiddle (binary_expr); + case TAO_ETCL_IN: + return this->visit_in (binary_expr); + default: + return -1; + } +} + +int +TAO_Log_Constraint_Visitor::visit_or ( + TAO_ETCL_Binary_Expr *binary + ) +{ + int return_value = -1; + CORBA::Boolean result = 0; + TAO_ETCL_Constraint *lhs = binary->lhs (); + + if (lhs->accept (this) == 0) + { + TAO_ETCL_Literal_Constraint lhs_result; + this->queue_.dequeue_head (lhs_result); + result = (CORBA::Boolean) lhs_result; + + // Short-circuiting OR. + if (result == 0) + { + TAO_ETCL_Constraint *rhs = binary->rhs (); + + if (rhs->accept (this) == 0) + { + TAO_ETCL_Literal_Constraint rhs_result; + this->queue_.dequeue_head (rhs_result); + result = (CORBA::Boolean) rhs_result; + return_value = 0; + } + } + else + { + return_value = 0; + } + } + + if (return_value == 0) + { + this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result)); + } + + return return_value; +} + +int +TAO_Log_Constraint_Visitor::visit_and ( + TAO_ETCL_Binary_Expr *binary + ) +{ + int return_value = -1; + CORBA::Boolean result = 0; + TAO_ETCL_Constraint *lhs = binary->lhs (); + + if (lhs->accept (this) == 0) + { + TAO_ETCL_Literal_Constraint lhs_result; + this->queue_.dequeue_head (lhs_result); + result = (CORBA::Boolean) lhs_result; + + // Short-circuiting AND. + if (result == 1) + { + TAO_ETCL_Constraint *rhs = binary->rhs (); + + if (rhs->accept (this) == 0) + { + TAO_ETCL_Literal_Constraint rhs_result; + this->queue_.dequeue_head (rhs_result); + result = (CORBA::Boolean) rhs_result; + return_value = 0; + } + } + else + { + return_value = 0; + } + } + + if (return_value == 0) + { + this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result)); + } + + return return_value; +} + +int +TAO_Log_Constraint_Visitor::visit_binary_op ( + TAO_ETCL_Binary_Expr *binary, + int op_type + ) +{ + int return_value = -1; + TAO_ETCL_Constraint *lhs = binary->lhs (); + CORBA::Boolean result = 0; + + // Evaluate the constraint + // Perform an operation on the results of evaluating the left and + // right branches of this subtree. + if (lhs->accept (this) == 0) + { + + // Evaluate the constraint + TAO_ETCL_Literal_Constraint left_operand; + this->queue_.dequeue_head (left_operand); + TAO_ETCL_Constraint *rhs = binary->rhs (); + + if (rhs->accept (this) == 0) + { + TAO_ETCL_Literal_Constraint right_operand; + this->queue_.dequeue_head (right_operand); + return_value = 0; + + switch (op_type) + { + case TAO_ETCL_LT: + result = left_operand < right_operand; + this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result)); + break; + case TAO_ETCL_LE: + result = left_operand <= right_operand; + this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result)); + break; + case TAO_ETCL_GT: + result = left_operand > right_operand; + this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result)); + break; + case TAO_ETCL_GE: + result = left_operand >= right_operand; + this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result)); + break; + case TAO_ETCL_EQ: + result = left_operand == right_operand; + this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result)); + break; + case TAO_ETCL_NE: + result = left_operand != right_operand; + this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result)); + break; + case TAO_ETCL_PLUS: + this->queue_.enqueue_head (left_operand + right_operand); + break; + case TAO_ETCL_MINUS: + this->queue_.enqueue_head (left_operand - right_operand); + break; + case TAO_ETCL_MULT: + this->queue_.enqueue_head (left_operand * right_operand); + break; + case TAO_ETCL_DIV: + this->queue_.enqueue_head (left_operand / right_operand); + break; + default: + return_value = -1; + } + } + } + + return return_value; +} + +int +TAO_Log_Constraint_Visitor::visit_twiddle ( + TAO_ETCL_Binary_Expr *binary + ) +{ + int return_value = -1; + TAO_ETCL_Constraint *lhs = binary->lhs (); + + // Determine if the left operand is a substring of the right. + if (lhs->accept (this) == 0) + { + TAO_ETCL_Literal_Constraint left; + this->queue_.dequeue_head (left); + TAO_ETCL_Constraint *rhs = binary->rhs (); + + if (rhs->accept (this) == 0) + { + TAO_ETCL_Literal_Constraint right; + this->queue_.dequeue_head (right); + CORBA::Boolean result = + (ACE_OS::strstr ((const char *) left, + (const char *) right) != 0); + this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result)); + return_value = 0; + } + } + + return return_value; +} + +int +TAO_Log_Constraint_Visitor::visit_in ( + TAO_ETCL_Binary_Expr *binary + ) +{ + int return_value = -1; + TAO_ETCL_Constraint *lhs = binary->lhs (); + + // Determine if the left operand is contained in the right. + + if (lhs->accept (this) == 0) + { + TAO_ETCL_Literal_Constraint left; + this->queue_.dequeue_head (left); + + TAO_ETCL_Constraint *rhs = binary->rhs (); + + if (rhs->accept (this) == 0) + { + TAO_ETCL_Literal_Constraint bag; + this->queue_.dequeue_head (bag); + + if (bag.expr_type () == TAO_ETCL_COMPONENT) + { + const CORBA::Any *component = (const CORBA::Any *) bag; + CORBA::TCKind kind = CORBA::tk_null; + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + CORBA::TypeCode_var tc = component->type (); + kind = TAO_DynAnyFactory::unalias (tc.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + return return_value; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (return_value); + + CORBA::Boolean result = 0; + + switch (kind) + { + case CORBA::tk_sequence: + result = this->sequence_does_contain (component, + left); + break; + case CORBA::tk_array: + result = this->array_does_contain (component, + left); + break; + case CORBA::tk_struct: + result = this->struct_does_contain (component, + left); + break; + case CORBA::tk_union: + result = this->union_does_contain (component, + left); + break; + case CORBA::tk_any: + result = this->any_does_contain (component, + left); + break; + default: + return return_value; + } + + this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result)); + return_value = 0; + } + } + } + + return return_value; +} + +int +TAO_Log_Constraint_Visitor::visit_preference ( + TAO_ETCL_Preference * + ) +{ + // According to OMG 00-06-20 section 2.4.1, the Notification Service + // does not use the preference operators. The method must be here + // because it is called by the ETCL node, which may be used by other + // CORBA services that do use the preference operators. + return -1; +} + +CORBA::Boolean +TAO_Log_Constraint_Visitor::sequence_does_contain ( + const CORBA::Any *any, + TAO_ETCL_Literal_Constraint &item + ) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + CORBA::TypeCode_var type = any->type (); + CORBA::TCKind kind = TAO_DynAnyFactory::unalias (type.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // The literal and the array elements must be + // of the same simple type. + CORBA::Boolean match = this->simple_type_match (item.expr_type (), + kind); + + if (match == 0) + { + return 0; + } + + TAO_DynSequence_i dyn_seq; + dyn_seq.init (*any + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + DynamicAny::AnySeq_var any_seq = + dyn_seq.get_elements (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + CORBA::ULong length = any_seq->length (); + + for (CORBA::ULong i = 0; i < length; ++i) + { + TAO_ETCL_Literal_Constraint element (&any_seq[i]); + + if (item == element) + { + return 1; + } + } + } + ACE_CATCHANY + { + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + + return 0; +} + +CORBA::Boolean +TAO_Log_Constraint_Visitor::array_does_contain ( + const CORBA::Any *any, + TAO_ETCL_Literal_Constraint &item + ) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + CORBA::TypeCode_var type = any->type (); + CORBA::TCKind kind = TAO_DynAnyFactory::unalias (type.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // The literal and the array elements must be + // of the same simple type. + CORBA::Boolean match = this->simple_type_match (item.expr_type (), + kind); + + if (match == 0) + { + return 0; + } + + TAO_DynArray_i dyn_array; + dyn_array.init (*any + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + DynamicAny::AnySeq_var any_seq = + dyn_array.get_elements (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + CORBA::ULong length = any_seq->length (); + + for (CORBA::ULong i = 0; i < length; ++i) + { + TAO_ETCL_Literal_Constraint element (&any_seq[i]); + + if (item == element) + { + return 1; + } + } + } + ACE_CATCHANY + { + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + + return 0; +} + +CORBA::Boolean +TAO_Log_Constraint_Visitor::struct_does_contain ( + const CORBA::Any *any, + TAO_ETCL_Literal_Constraint &item + ) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + TAO_DynStruct_i dyn_struct; + dyn_struct.init (*any + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + DynamicAny::NameValuePairSeq_var members = + dyn_struct.get_members (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + CORBA::ULong length = members->length (); + CORBA::TypeCode_var tc; + CORBA::TCKind kind; + + for (CORBA::ULong i = 0; i < length; ++i) + { + tc = members[i].value.type (); + kind = TAO_DynAnyFactory::unalias (tc.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // The literal and the struct member must be + // of the same simple type. + CORBA::Boolean match = this->simple_type_match (item.expr_type (), + kind); + + if (match == 0) + { + continue; + } + + TAO_ETCL_Literal_Constraint element (&members[i].value); + + if (item == element) + { + return 1; + } + } + } + ACE_CATCHANY + { + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + + return 0; +} + +CORBA::Boolean +TAO_Log_Constraint_Visitor::union_does_contain ( + const CORBA::Any *any, + TAO_ETCL_Literal_Constraint &item + ) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + TAO_DynUnion_i dyn_union; + dyn_union.init (*any + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + DynamicAny::DynAny_var cc = + dyn_union.current_component (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + CORBA::Any_var member = cc->to_any (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + CORBA::TypeCode_var tc = member->type (); + CORBA::TCKind kind = TAO_DynAnyFactory::unalias (tc.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // The literal and the union member must be + // of the same simple type. + CORBA::Boolean match = this->simple_type_match (item.expr_type (), + kind); + + if (match == 0) + { + return 0; + } + + TAO_ETCL_Literal_Constraint element (&member.inout ()); + + return (item == element); + } + ACE_CATCHANY + { + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); +} + +CORBA::Boolean +TAO_Log_Constraint_Visitor::any_does_contain ( + const CORBA::Any *any, + TAO_ETCL_Literal_Constraint &item + ) +{ + const CORBA::Any *result = 0; + + *any >>= result; + + TAO_ETCL_Literal_Constraint element (const_cast<CORBA::Any *> (result)); + + return (item == element); +} + +CORBA::Boolean +TAO_Log_Constraint_Visitor::simple_type_match (int expr_type, + CORBA::TCKind tc_kind) +{ + switch (expr_type) + { + case TAO_ETCL_STRING: + if (tc_kind != CORBA::tk_string) + { + return 0; + } + case TAO_ETCL_DOUBLE: + if (tc_kind != CORBA::tk_double + && tc_kind != CORBA::tk_float) + { + return 0; + } + case TAO_ETCL_INTEGER: + case TAO_ETCL_SIGNED: + if (tc_kind != CORBA::tk_short + && tc_kind != CORBA::tk_long + && tc_kind != CORBA::tk_longlong) + { + return 0; + } + case TAO_ETCL_UNSIGNED: + if (tc_kind != CORBA::tk_ushort + && tc_kind != CORBA::tk_ulong + && tc_kind != CORBA::tk_ulonglong) + { + return 0; + } + case TAO_ETCL_BOOLEAN: + if (tc_kind != CORBA::tk_boolean) + { + return 0; + } + default: + return 0; + } +} + +const size_t TAO_Log_Constraint_Visitor::property_lookup_size_ = 31; + +TAO_END_VERSIONED_NAMESPACE_DECL |