Notify_Constraint_Visitors.cpp

Go to the documentation of this file.
00001 // $Id: Notify_Constraint_Visitors.cpp 81641 2008-05-07 19:18:59Z parsons $
00002 
00003 #include "orbsvcs/Notify/Notify_Constraint_Visitors.h"
00004 
00005 #include "ace/ETCL/ETCL_y.h"
00006 
00007 #include "tao/ETCL/TAO_ETCL_Constraint.h"
00008 
00009 #include "tao/DynamicAny/DynArray_i.h"
00010 #include "tao/DynamicAny/DynSequence_i.h"
00011 #include "tao/DynamicAny/DynStruct_i.h"
00012 #include "tao/DynamicAny/DynUnion_i.h"
00013 #include "tao/DynamicAny/DynEnum_i.h"
00014 #include "tao/DynamicAny/DynAnyFactory.h"
00015 #include "tao/DynamicAny/DynAnyUtils_T.h"
00016 
00017 #include "tao/AnyTypeCode/Any_Unknown_IDL_Type.h"
00018 #include "tao/CDR.h"
00019 
00020 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00021 
00022 TAO_Notify_Constraint_Visitor::TAO_Notify_Constraint_Visitor (void)
00023   : implicit_id_ (TAO_Notify_Constraint_Visitor::EMPTY),
00024     implicit_ids_(implicit_ids_size_),
00025     filterable_data_(filterable_data_size_),
00026     variable_header_(variable_header_size_)
00027 {
00028   (void) this->implicit_ids_.bind (ACE_CString ("filterable_data",
00029     0,
00030     false),
00031     FILTERABLE_DATA);
00032   (void) this->implicit_ids_.bind (ACE_CString ("header",
00033     0,
00034     false),
00035     HEADER);
00036   (void) this->implicit_ids_.bind (ACE_CString ("remainder_of_body",
00037     0,
00038     false),
00039     REMAINDER_OF_BODY);
00040   (void) this->implicit_ids_.bind (ACE_CString ("fixed_header",
00041     0,
00042     false),
00043     FIXED_HEADER);
00044   (void) this->implicit_ids_.bind (ACE_CString ("variable_header",
00045     0,
00046     false),
00047     VARIABLE_HEADER);
00048   (void) this->implicit_ids_.bind (ACE_CString ("event_name",
00049     0,
00050     false),
00051     EVENT_NAME);
00052   (void) this->implicit_ids_.bind (ACE_CString ("event_type",
00053     0,
00054     false),
00055     EVENT_TYPE);
00056   (void) this->implicit_ids_.bind (ACE_CString ("domain_name",
00057     0,
00058     false),
00059     DOMAIN_NAME);
00060   (void) this->implicit_ids_.bind (ACE_CString ("type_name",
00061     0,
00062     false),
00063     TYPE_NAME);
00064 }
00065 
00066 int
00067 TAO_Notify_Constraint_Visitor::bind_structured_event (const CosNotification::StructuredEvent &s_event)
00068 {
00069   // The two sequences contained in a structured event are
00070   // copied into hash tables so iteration is done only once.
00071 
00072   CORBA::ULong length = s_event.filterable_data.length ();
00073   CORBA::ULong index = 0;
00074 
00075   for (index = 0; index < length; ++index)
00076   {
00077     ACE_CString name_str (s_event.filterable_data[index].name, 0, false);
00078 
00079     int status =
00080       this->filterable_data_.bind (
00081         name_str,
00082         s_event.filterable_data[index].value
00083         );
00084 
00085     if (status != 0)
00086       return -1;
00087   }
00088 
00089   length = s_event.header.variable_header.length ();
00090 
00091   for (index = 0; index < length; ++index)
00092   {
00093     ACE_CString name_str (s_event.header.variable_header[index].name, 0, false);
00094 
00095     int status =
00096       this->variable_header_.bind (
00097         name_str,
00098         s_event.header.variable_header[index].value
00099         );
00100 
00101     if (status != 0)
00102       return -1;
00103   }
00104 
00105   this->domain_name_ =
00106     CORBA::string_dup (s_event.header.fixed_header.event_type.domain_name);
00107 
00108   this->type_name_ =
00109     CORBA::string_dup (s_event.header.fixed_header.event_type.type_name);
00110 
00111   this->event_name_ =
00112     CORBA::string_dup (s_event.header.fixed_header.event_name);
00113 
00114   this->remainder_of_body_ = s_event.remainder_of_body;
00115 
00116   return 0;
00117 }
00118 
00119 CORBA::Boolean
00120 TAO_Notify_Constraint_Visitor::evaluate_constraint (ETCL_Constraint* root)
00121 {
00122   CORBA::Boolean result = 0;
00123   this->queue_.reset ();
00124 
00125   // Evaluate the constraint in root_;
00126   if (root != 0)
00127     {
00128       if ((root->accept (this) == 0) && (! this->queue_.is_empty ()))
00129         {
00130           TAO_ETCL_Literal_Constraint top;
00131           this->queue_.dequeue_head (top);
00132           result = (CORBA::Boolean) top;
00133         }
00134     }
00135 
00136   // If a property couldn't be evaluated we must return 0.
00137   return result;
00138 }
00139 
00140 int
00141 TAO_Notify_Constraint_Visitor::visit_literal (
00142     ETCL_Literal_Constraint *literal
00143   )
00144 {
00145   TAO_ETCL_Literal_Constraint lit (literal);
00146   this->queue_.enqueue_head (lit);
00147   return 0;
00148 }
00149 
00150 int
00151 TAO_Notify_Constraint_Visitor::visit_identifier (ETCL_Identifier *ident)
00152 {
00153   int return_value = -1;
00154   const char *name = ident->value ();
00155   ACE_CString key (name, 0, false);
00156 
00157   CORBA::Any any;
00158 
00159   if (this->filterable_data_.find (key, any) == 0)
00160     {
00161       if (any.impl () != 0)
00162         {
00163           this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (&any));
00164           return_value = 0;
00165         }
00166     }
00167 
00168   return return_value;
00169 }
00170 
00171 int
00172 TAO_Notify_Constraint_Visitor::visit_union_value (
00173     ETCL_Union_Value *union_value
00174   )
00175 {
00176   switch (union_value->sign ())
00177   {
00178     case 0:
00179       {
00180         TAO_ETCL_Literal_Constraint lit (union_value->string ());
00181         this->queue_.enqueue_head (lit);
00182       }
00183       break;
00184     case -1:
00185       {
00186         CORBA::Long value = -(*union_value->integer ());
00187         TAO_ETCL_Literal_Constraint lit (value);
00188         this->queue_.enqueue_head (lit);
00189       }
00190       break;
00191     case 1:
00192       {
00193         TAO_ETCL_Literal_Constraint lit (union_value->integer ());
00194         this->queue_.enqueue_head (lit);
00195       }
00196       break;
00197     default:
00198       return -1;
00199   }
00200 
00201   return 0;
00202 }
00203 
00204 int
00205 TAO_Notify_Constraint_Visitor::visit_union_pos (
00206     ETCL_Union_Pos *union_pos
00207   )
00208 {
00209   try
00210   {
00211     if (union_pos->union_value ()->accept (this) == 0)
00212       {
00213         TAO_ETCL_Literal_Constraint disc_val;
00214         this->queue_.dequeue_head (disc_val);
00215 
00216         TAO_DynUnion_i dyn_union;
00217         dyn_union.init (this->current_value_.in ());
00218 
00219         CORBA::TypeCode_var tc = this->current_value_->type ();
00220 
00221         switch (disc_val.expr_type ())
00222         {
00223         case ETCL_INTEGER:
00224         case ETCL_SIGNED:
00225         case ETCL_UNSIGNED:
00226           {
00227             CORBA::Any disc_any;
00228             CORBA::TypeCode_var disc_tc =
00229               tc->discriminator_type ();
00230             CORBA::TCKind disc_kind =
00231               TAO_DynAnyFactory::unalias (disc_tc.in ());
00232 
00233             switch (disc_kind)
00234             {
00235             case CORBA::tk_boolean:
00236               disc_any <<= CORBA::Any::from_boolean ((CORBA::Boolean) disc_val);
00237               break;
00238             case CORBA::tk_short:
00239               disc_any <<= (CORBA::Short) ((CORBA::Long) disc_val);
00240               break;
00241             case CORBA::tk_ushort:
00242               disc_any <<= (CORBA::UShort) ((CORBA::ULong) disc_val);
00243               break;
00244             case CORBA::tk_long:
00245               disc_any <<= (CORBA::Long) disc_val;
00246               break;
00247             case CORBA::tk_ulong:
00248               disc_any <<= (CORBA::ULong) disc_val;
00249               break;
00250             case CORBA::tk_enum:
00251               {
00252                 TAO_OutputCDR cdr;
00253                 cdr.write_ulong ((CORBA::ULong) disc_val);
00254                 TAO_InputCDR in_cdr (cdr);
00255                 TAO::Unknown_IDL_Type *unk = 0;
00256                 ACE_NEW_RETURN (unk,
00257                                 TAO::Unknown_IDL_Type (disc_tc.in (),
00258                                 in_cdr),
00259                                 -1);
00260 
00261                 disc_any.replace (unk);
00262                 break;
00263               }
00264               // @@@ (JP) I don't think ETCL handles 64-bit
00265               // integers at this point, and I also think that
00266               // chars and/or wchars will just come out in the
00267               // constraint as (w)strings of length 1.
00268             case CORBA::tk_longlong:
00269             case CORBA::tk_ulonglong:
00270             case CORBA::tk_char:
00271             case CORBA::tk_wchar:
00272             default:
00273               return -1;
00274             }
00275 
00276             DynamicAny::DynAny_var dyn_any =
00277               TAO::MakeDynAnyUtils::make_dyn_any_t<const CORBA::Any &> (
00278                 disc_tc.in (),
00279                 disc_any);
00280             dyn_union.set_discriminator (dyn_any.in ());
00281             DynamicAny::DynAny_var u_member =
00282               dyn_union.member ();
00283             this->current_value_ =
00284               u_member->to_any ();
00285 
00286             break;
00287           }
00288         case ETCL_STRING:
00289           {
00290             const char *name = (const char *) disc_val;
00291             CORBA::ULong count = tc->member_count ();
00292 
00293             const char *member_name = 0;
00294             CORBA::ULong i = 0;
00295 
00296             for (i = 0; i < count; ++i)
00297               {
00298                 member_name = tc->member_name (i);
00299 
00300                 if (ACE_OS::strcmp (name, member_name) == 0)
00301                   {
00302                     break;
00303                   }
00304               }
00305 
00306             // If there's no match, member_label will throw
00307             // CORBA::TypeCode::Bounds and the catch block will
00308             // return -1;
00309             this->current_value_ = tc->member_label (i);
00310 
00311             break;
00312           }
00313           // The ETCL_Union_Value that was put on the queue
00314           // shouldn't have any other type.
00315         default:
00316           return -1;
00317         }
00318 
00319         ETCL_Constraint *nested = union_pos->component ();
00320 
00321         // If there's no nested component, then we just want the
00322         // union member value on the queue. Otherwise, we want
00323         // the member value in current_value_ while we visit
00324         // the nested component.
00325         if (nested == 0)
00326           {
00327             TAO_ETCL_Literal_Constraint lit (this->current_value_.ptr ());
00328             this->queue_.enqueue_head (lit);
00329             return 0;
00330           }
00331         else
00332           {
00333             return nested->accept (this);
00334           }
00335       }
00336     else
00337       {
00338         return -1;
00339       }
00340   }
00341   catch (const CORBA::Exception&)
00342   {
00343     return -1;
00344   }
00345 }
00346 
00347 int
00348 TAO_Notify_Constraint_Visitor::visit_component_pos (
00349     ETCL_Component_Pos *pos
00350   )
00351 {
00352   try
00353   {
00354     // If we are here (from visit_component) the Any containing the
00355     // component as found in filterable_data_ will be in current_value_.
00356     CORBA::TypeCode_var tc = this->current_value_->type ();
00357     CORBA::TCKind kind = TAO_DynAnyFactory::unalias (tc.in ());
00358 
00359     DynamicAny::DynAny_var member;
00360     CORBA::Boolean success = 0;
00361     CORBA::ULong slot = (CORBA::ULong) *pos->integer ();
00362 
00363     switch (kind)
00364     {
00365     case CORBA::tk_enum:
00366       {
00367         TAO_DynEnum_i dyn_enum;
00368         dyn_enum.init (this->current_value_.in ());
00369         success = dyn_enum.seek (slot);
00370 
00371         if (!success)
00372           {
00373             return -1;
00374           }
00375 
00376         member = dyn_enum.current_component ();
00377         break;
00378       }
00379     case CORBA::tk_struct:
00380       {
00381         TAO_DynStruct_i dyn_struct;
00382         dyn_struct.init (this->current_value_.in ());
00383         success = dyn_struct.seek (slot);
00384 
00385         if (!success)
00386           {
00387             return -1;
00388           }
00389 
00390         member = dyn_struct.current_component ();
00391         break;
00392       }
00393       // @@@ (JP) I think enums and structs are the only two cases
00394       // handled by Component_Pos, since arrays and sequences are
00395       // handled by Component_Array, and unions are handled by
00396       // Union_Pos.
00397     default:
00398       return -1;
00399     }
00400 
00401     CORBA::Any_var value = member->to_any ();
00402     ETCL_Constraint *comp = pos->component ();
00403 
00404     if (comp == 0)
00405       {
00406         TAO_ETCL_Literal_Constraint result (value.ptr ());
00407         this->queue_.enqueue_head (result);
00408         return 0;
00409       }
00410     else
00411       {
00412         this->current_value_ = value._retn ();
00413         return comp->accept (this);
00414       }
00415   }
00416   catch (const CORBA::Exception&)
00417   {
00418     return -1;
00419   }
00420 }
00421 
00422 int
00423 TAO_Notify_Constraint_Visitor::visit_component_assoc (
00424     ETCL_Component_Assoc *assoc
00425   )
00426 {
00427   CORBA::Any any;
00428   ACE_CString name (assoc->identifier ()->value (),
00429                     0,
00430                     false);
00431 
00432   switch (this->implicit_id_)
00433   {
00434   case FILTERABLE_DATA:
00435     if (this->filterable_data_.find (name, any) != 0 || any.impl () == 0)
00436       {
00437         return -1;
00438       }
00439     break;
00440   case VARIABLE_HEADER:
00441     if (this->variable_header_.find (name, any) != 0|| any.impl () == 0)
00442       {
00443         return -1;
00444       }
00445     break;
00446     // Only the sequence members of CosNotification::StructuredEvent
00447     // can be treated as associative arrays.
00448   default:
00449     return -1;
00450   }
00451 
00452   ETCL_Constraint *comp = assoc->component ();
00453   CORBA::Any *any_ptr = 0;
00454 
00455   if (comp == 0)
00456     {
00457       TAO_ETCL_Literal_Constraint result (&any);
00458       this->queue_.enqueue_head (result);
00459 
00460       // If we're at the end of the line, put the name into
00461       // current_value_ so visit_exist can use it.
00462       ACE_NEW_RETURN (any_ptr,
00463                       CORBA::Any,
00464                       -1);
00465                       
00466       (*any_ptr) <<= name.c_str ();
00467       this->current_value_ = any_ptr;
00468 
00469       return 0;
00470     }
00471   else
00472     {
00473       ACE_NEW_RETURN (any_ptr,
00474                       CORBA::Any (any),
00475                       -1);
00476                       
00477       this->current_value_ = any_ptr;
00478       return comp->accept (this);
00479     }
00480 }
00481 
00482 int
00483 TAO_Notify_Constraint_Visitor::visit_component_array (
00484     ETCL_Component_Array *array
00485   )
00486 {
00487   try
00488   {
00489     // If we are here (from visit_component) the Any containing the
00490     // component as found in filterable_data_ will be in
00491     // current_value_.
00492     CORBA::TypeCode_var tc = this->current_value_->type ();
00493     CORBA::TCKind kind = TAO_DynAnyFactory::unalias (tc.in ());
00494 
00495     DynamicAny::DynAny_var member;
00496     CORBA::Boolean success = 0;
00497     CORBA::ULong slot = (CORBA::ULong) *array->integer ();
00498 
00499     switch (kind)
00500     {
00501     case CORBA::tk_array:
00502       {
00503         TAO_DynEnum_i dyn_array;
00504         dyn_array.init (this->current_value_.in ());
00505         success = dyn_array.seek (slot);
00506 
00507         if (!success)
00508           {
00509             return -1;
00510           }
00511 
00512         member = dyn_array.current_component ();
00513         break;
00514       }
00515     case CORBA::tk_sequence:
00516       {
00517         TAO_DynStruct_i dyn_sequence;
00518         dyn_sequence.init (this->current_value_.in ());
00519         success = dyn_sequence.seek (slot);
00520 
00521         if (!success)
00522           {
00523             return -1;
00524           }
00525 
00526         member =dyn_sequence.current_component ();
00527         break;
00528       }
00529       // Enums and sequences are the only two cases handled
00530       // by Component_Array.
00531     default:
00532       return -1;
00533     }
00534 
00535     CORBA::Any_var value = member->to_any ();
00536     ETCL_Constraint *comp = array->component ();
00537 
00538     if (comp == 0)
00539       {
00540         TAO_ETCL_Literal_Constraint result (value.ptr ());
00541         this->queue_.enqueue_head (result);
00542         return 0;
00543       }
00544     else
00545       {
00546         this->current_value_ = value._retn ();
00547         return comp->accept (this);
00548       }
00549   }
00550   catch (const CORBA::Exception&)
00551   {
00552     return -1;
00553   }
00554 }
00555 
00556 int
00557 TAO_Notify_Constraint_Visitor::visit_special (ETCL_Special *special)
00558 {
00559   try
00560   {
00561     CORBA::TypeCode_var tc = this->current_value_->type ();
00562     tc = TAO_DynAnyFactory::strip_alias (tc.in ());
00563     CORBA::TCKind kind = tc->kind ();
00564 
00565     switch (special->type ())
00566     {
00567     case ETCL_LENGTH:
00568       {
00569         CORBA::ULong length;
00570 
00571         switch (kind)
00572         {
00573         case CORBA::tk_sequence:
00574           {
00575             TAO_DynSequence_i dyn_seq;
00576             dyn_seq.init (current_value_.in());
00577 
00578             DynamicAny::AnySeq_var any_seq =
00579               dyn_seq.get_elements ();
00580 
00581             length = any_seq->length ();
00582           }
00583           break;
00584         case CORBA::tk_array:
00585           length = tc->length ();
00586           break;
00587         default:
00588           return -1;
00589         }
00590 
00591         TAO_ETCL_Literal_Constraint lit (length);
00592         this->queue_.enqueue_head (lit);
00593         return 0;
00594       }
00595     case ETCL_DISCRIMINANT:
00596       {
00597         // If the TCKind is not a union, the call to init() will
00598         // raise an exception, and the catch block will return -1;
00599         TAO_DynUnion_i dyn_union;
00600         dyn_union.init (this->current_value_.in ());
00601 
00602         DynamicAny::DynAny_var disc =
00603           dyn_union.get_discriminator ();
00604 
00605         CORBA::Any_var disc_any = disc->to_any ();
00606 
00607         TAO_ETCL_Literal_Constraint lit (disc_any.ptr ());
00608         this->queue_.enqueue_head (lit);
00609         return 0;
00610       }
00611     case ETCL_TYPE_ID:
00612       {
00613         const char *name = tc->name ();
00614 
00615         TAO_ETCL_Literal_Constraint lit (name);
00616         this->queue_.enqueue_head (lit);
00617         return 0;
00618       }
00619     case ETCL_REPOS_ID:
00620       {
00621         const char *id = tc->id ();
00622 
00623         TAO_ETCL_Literal_Constraint lit (id);
00624         this->queue_.enqueue_head (lit);
00625         return 0;
00626       }
00627     default:
00628       return -1;
00629     }
00630   }
00631   catch (const CORBA::Exception&)
00632   {
00633     return -1;
00634   }
00635 }
00636 
00637 int
00638 TAO_Notify_Constraint_Visitor::visit_component (
00639     ETCL_Component *component
00640   )
00641 {
00642   ETCL_Constraint *nested = component->component ();
00643   ETCL_Identifier *identifier = component->identifier ();
00644   ACE_CString component_name (identifier->value (),
00645                               0,
00646                               false);
00647   CORBA::Any *any_ptr = 0;
00648   int result =
00649     this->implicit_ids_.find (component_name, this->implicit_id_);
00650 
00651   if (result != 0)
00652     {
00653       this->implicit_id_ = TAO_Notify_Constraint_Visitor::EMPTY;
00654     }
00655 
00656   // If this component has no sub-component, only an identifier, then
00657   // we just visit the identifier, which puts a literal on the queue
00658   // to be handled upon returning from this method call.  If there is
00659   // a sub-component, we store the literal's value in our member _var
00660   // for possible examination at a more nested level, and visit the
00661   // sub-component. If the identifier matches one of the nested field
00662   // names in CosNotification::StructuredEvent, we just visit the
00663   // nested component, if any.
00664   if (this->implicit_id_ == TAO_Notify_Constraint_Visitor::EMPTY)
00665     {
00666       ACE_NEW_RETURN (any_ptr,
00667                       CORBA::Any,
00668                       -1);
00669 
00670       if (nested == 0)
00671         {
00672           // If this is the end of the line, we put the component name
00673           // into current_value_ so visit_exist can use it.
00674           (*any_ptr) <<= component_name.c_str ();
00675           this->current_value_ = any_ptr;
00676           return identifier->accept (this);
00677         }
00678       else
00679         {
00680           int result = identifier->accept (this);
00681 
00682           if (result != 0)
00683             {
00684               return result;
00685             }
00686 
00687           TAO_ETCL_Literal_Constraint id;
00688           this->queue_.dequeue_head (id);
00689                           
00690           any_ptr->replace (id);
00691           any_ptr->impl ()->_add_ref ();
00692           this->current_value_ = any_ptr;
00693         }
00694     }
00695 
00696   if (nested != 0)
00697     {
00698       return nested->accept (this);
00699     }
00700   else
00701     {
00702       switch (this->implicit_id_)
00703       {
00704       case TYPE_NAME:
00705         {
00706           TAO_ETCL_Literal_Constraint tn (this->type_name_.in ());
00707           this->queue_.enqueue_head (tn);
00708           return 0;
00709         }
00710       case EVENT_NAME:
00711         {
00712           TAO_ETCL_Literal_Constraint en (this->event_name_.in ());
00713           this->queue_.enqueue_head (en);
00714           return 0;
00715         }
00716       case DOMAIN_NAME:
00717         {
00718           TAO_ETCL_Literal_Constraint dn (this->domain_name_.in ());
00719           this->queue_.enqueue_head (dn);
00720           return 0;
00721         }
00722       case REMAINDER_OF_BODY:
00723         {
00724           TAO_ETCL_Literal_Constraint rob (&this->remainder_of_body_);
00725           this->queue_.enqueue_head (rob);
00726           return 0;
00727         }
00728         // The above cases are the leaves of the
00729         // CosNotification::StructuredEvent "tree". Anything else and we
00730         // should have a nested component. otherwise, it's an error.
00731       default:
00732         return -1;
00733       }
00734     }
00735 }
00736 
00737 int
00738 TAO_Notify_Constraint_Visitor::visit_dot (ETCL_Dot *dot)
00739 {
00740   // If we are here, we know we're headed for a more nested
00741   // level, so we just visit it, there's nothing else in this
00742   // constraint.
00743   return dot->component ()->accept (this);
00744 }
00745 
00746 int
00747 TAO_Notify_Constraint_Visitor::visit_eval (ETCL_Eval *eval)
00748 {
00749   // Nothing to do but visit the contained component.
00750   return eval->component ()->accept (this);
00751 }
00752 
00753 int
00754 TAO_Notify_Constraint_Visitor::visit_default (ETCL_Default *def)
00755 {
00756   ETCL_Constraint *comp = def->component ();
00757 
00758   if (comp == 0)
00759     {
00760       return -1;
00761     }
00762 
00763   if (comp->accept (this) != 0)
00764     {
00765       return -1;
00766     }
00767 
00768   try
00769   {
00770     CORBA::TypeCode_var tc = this->current_value_->type ();
00771 
00772     // If the current member is not a union, this call will throw
00773     // BadKind and the catch block will return -1.
00774     CORBA::Long default_index = tc->default_index ();
00775 
00776     // No default index.
00777     if (default_index == -1)
00778     {
00779       TAO_ETCL_Literal_Constraint result (false);
00780       this->queue_.enqueue_head (result);
00781       return 0;
00782     }
00783 
00784     // Okay, there's a default index, but is it active?
00785     TAO_ETCL_Literal_Constraint disc_value;
00786     this->queue_.dequeue_head (disc_value);
00787     TAO_ETCL_Literal_Constraint default_index_value (default_index);
00788     
00789     return (disc_value == default_index_value);
00790   }
00791   catch (const CORBA::Exception&)
00792   {
00793     return -1;
00794   }
00795 }
00796 
00797 int
00798 TAO_Notify_Constraint_Visitor::visit_exist (ETCL_Exist *exist)
00799 {
00800   ETCL_Constraint *component = exist->component ();
00801 
00802   if (component->accept (this) == 0)
00803     {
00804       const char *value = 0;
00805       CORBA::Boolean result = 0;
00806 
00807       // For the two cases below, we don't want the item at the top of
00808       // the queue, because it's the result of a hash table
00809       // lookup. For an existence test, we want the key value, which
00810       // is stored in the current_value_ member.
00811       if (this->implicit_id_ == FILTERABLE_DATA
00812           || this->implicit_id_ == VARIABLE_HEADER)
00813         {
00814           this->current_value_ >>= value;
00815         }
00816       else if (this->implicit_id_ == EMPTY)
00817         {
00818           // If the implicit id is empty, then we must default
00819           // it to the filterable data and set up the value pointer.
00820           
00821           ETCL_Identifier* ident =
00822             dynamic_cast<ETCL_Identifier*> (component);
00823             
00824           if (ident != 0)
00825             {
00826               this->implicit_id_ = FILTERABLE_DATA;
00827               value = ident->value ();
00828             }
00829         }
00830 
00831       switch (this->implicit_id_)
00832       {
00833       case FILTERABLE_DATA:
00834         result =
00835           (this->filterable_data_.find (ACE_CString (value, 0, false)) == 0);
00836         break;
00837       case VARIABLE_HEADER:
00838         result =
00839           (this->variable_header_.find (ACE_CString (value, 0, false)) == 0);
00840         break;
00841       case TYPE_NAME:
00842         result = (this->type_name_.in () != 0);
00843         break;
00844       case EVENT_NAME:
00845         result = (this->event_name_.in () != 0);
00846         break;
00847       case DOMAIN_NAME:
00848         result = (this->domain_name_.in () != 0);
00849         break;
00850         // Anything other than the above cases is an error.
00851       default:
00852         return -1;
00853       }
00854 
00855       this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result));
00856 
00857       return 0;
00858     }
00859 
00860   return -1;
00861 }
00862 
00863 int
00864 TAO_Notify_Constraint_Visitor::visit_unary_expr (
00865     ETCL_Unary_Expr *unary_expr
00866   )
00867 {
00868   ETCL_Constraint *subexpr = unary_expr->subexpr ();
00869 
00870   if (subexpr->accept (this) == 0)
00871     {
00872       TAO_ETCL_Literal_Constraint subexpr_result;
00873       CORBA::Boolean result = false;
00874       int op_type = unary_expr->type ();
00875 
00876       switch (op_type)
00877       {
00878       case ETCL_NOT:
00879         this->queue_.dequeue_head (subexpr_result);
00880         result = ! (CORBA::Boolean) subexpr_result;
00881         this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result));
00882         return 0;
00883       case ETCL_MINUS:
00884         // The leading '-' was parsed separately, so we have to pull
00885         // the literal constraint off the queue, apply the class' own
00886         // unary minus operator, and put it back.
00887         this->queue_.dequeue_head (subexpr_result);
00888         this->queue_.enqueue_head (-subexpr_result);
00889         return 0;
00890       case ETCL_PLUS:
00891         // Leave the literal constraint on the queue. The leading
00892         // '+' was just syntactic sugar - no action is necessary.
00893         return 0;
00894       default:
00895         // The parser should never construct a ETCL_Unary_Constraint
00896         // behind any operators except the above three.
00897         return -1;
00898       }
00899     }
00900 
00901   return -1;
00902 }
00903 
00904 int
00905 TAO_Notify_Constraint_Visitor::visit_binary_expr (
00906     ETCL_Binary_Expr *binary_expr
00907   )
00908 {
00909   int bin_op_type = binary_expr->type ();
00910 
00911   switch (bin_op_type)
00912   {
00913   case ETCL_OR:
00914     return this->visit_or (binary_expr);
00915   case ETCL_AND:
00916     return this->visit_and (binary_expr);
00917   case ETCL_LT:
00918   case ETCL_LE:
00919   case ETCL_GT:
00920   case ETCL_GE:
00921   case ETCL_EQ:
00922   case ETCL_NE:
00923   case ETCL_PLUS:
00924   case ETCL_MINUS:
00925   case ETCL_MULT:
00926   case ETCL_DIV:
00927     return this->visit_binary_op (binary_expr, bin_op_type);
00928   case ETCL_TWIDDLE:
00929     return this->visit_twiddle (binary_expr);
00930   case ETCL_IN:
00931     return this->visit_in (binary_expr);
00932   default:
00933     return -1;
00934   }
00935 }
00936 
00937 int
00938 TAO_Notify_Constraint_Visitor::visit_or (
00939     ETCL_Binary_Expr *binary
00940   )
00941 {
00942   int return_value = -1;
00943   CORBA::Boolean result = false;
00944   ETCL_Constraint *lhs = binary->lhs ();
00945 
00946   if (lhs->accept (this) == 0)
00947     {
00948       TAO_ETCL_Literal_Constraint lhs_result;
00949       this->queue_.dequeue_head (lhs_result);
00950       result = (CORBA::Boolean) lhs_result;
00951 
00952       // Short-circuiting OR.
00953       if (result == 0)
00954         {
00955           ETCL_Constraint *rhs = binary->rhs ();
00956 
00957           if (rhs->accept (this) == 0)
00958             {
00959               TAO_ETCL_Literal_Constraint rhs_result;
00960               this->queue_.dequeue_head (rhs_result);
00961               result = (CORBA::Boolean) rhs_result;
00962               return_value = 0;
00963             }
00964         }
00965     else
00966       {
00967         return_value = 0;
00968       }
00969   }
00970 
00971   if (return_value == 0)
00972     {
00973       this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result));
00974     }
00975 
00976   return return_value;
00977 }
00978 
00979 int
00980 TAO_Notify_Constraint_Visitor::visit_and (ETCL_Binary_Expr *binary)
00981 {
00982   int return_value = -1;
00983   CORBA::Boolean result = false;
00984   ETCL_Constraint *lhs = binary->lhs ();
00985 
00986   if (lhs->accept (this) == 0)
00987     {
00988       TAO_ETCL_Literal_Constraint lhs_result;
00989       this->queue_.dequeue_head (lhs_result);
00990       result = (CORBA::Boolean) lhs_result;
00991 
00992       // Short-circuiting AND.
00993       if (result == true)
00994         {
00995           ETCL_Constraint *rhs = binary->rhs ();
00996 
00997           if (rhs->accept (this) == 0)
00998           {
00999             TAO_ETCL_Literal_Constraint rhs_result;
01000             this->queue_.dequeue_head (rhs_result);
01001             result = (CORBA::Boolean) rhs_result;
01002             return_value = 0;
01003           }
01004         }
01005       else
01006         {
01007           return_value = 0;
01008         }
01009     }
01010 
01011   if (return_value == 0)
01012     {
01013       this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result));
01014     }
01015 
01016   return return_value;
01017 }
01018 
01019 int
01020 TAO_Notify_Constraint_Visitor::visit_binary_op (ETCL_Binary_Expr *binary,
01021                                                 int op_type)
01022 {
01023   int return_value = -1;
01024   ETCL_Constraint *lhs = binary->lhs ();
01025   CORBA::Boolean result = false;
01026 
01027   // Perform an operation on the results of evaluating the left and
01028   // right branches of this subtree.
01029   if (lhs->accept (this) == 0)
01030     {
01031       TAO_ETCL_Literal_Constraint left_operand;
01032       this->queue_.dequeue_head (left_operand);
01033       ETCL_Constraint *rhs = binary->rhs ();
01034 
01035       if (rhs->accept (this) == 0)
01036         {
01037           TAO_ETCL_Literal_Constraint right_operand;
01038           this->queue_.dequeue_head (right_operand);
01039           return_value = 0;
01040 
01041           switch (op_type)
01042           {
01043           case ETCL_LT:
01044             result = left_operand < right_operand;
01045             this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result));
01046             break;
01047           case ETCL_LE:
01048             result = left_operand <= right_operand;
01049             this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result));
01050             break;
01051           case ETCL_GT:
01052             result = left_operand > right_operand;
01053             this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result));
01054             break;
01055           case ETCL_GE:
01056             result = left_operand >= right_operand;
01057             this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result));
01058             break;
01059           case ETCL_EQ:
01060             result = left_operand == right_operand;
01061             this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result));
01062             break;
01063           case ETCL_NE:
01064             result = left_operand != right_operand;
01065             this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result));
01066             break;
01067           case ETCL_PLUS:
01068             this->queue_.enqueue_head (left_operand + right_operand);
01069             break;
01070           case ETCL_MINUS:
01071             this->queue_.enqueue_head (left_operand - right_operand);
01072             break;
01073           case ETCL_MULT:
01074             this->queue_.enqueue_head (left_operand * right_operand);
01075             break;
01076           case ETCL_DIV:
01077             this->queue_.enqueue_head (left_operand / right_operand);
01078             break;
01079           default:
01080             return_value = -1;
01081           }
01082         }
01083     }
01084 
01085   return return_value;
01086 }
01087 
01088 int
01089 TAO_Notify_Constraint_Visitor::visit_twiddle (ETCL_Binary_Expr *binary)
01090 {
01091   int return_value = -1;
01092   ETCL_Constraint *lhs = binary->lhs ();
01093 
01094   // Determine if the left operand is a substring of the right.
01095   if (lhs->accept (this) == 0)
01096     {
01097       TAO_ETCL_Literal_Constraint left;
01098       this->queue_.dequeue_head (left);
01099       ETCL_Constraint *rhs = binary->rhs ();
01100 
01101       if (rhs->accept (this) == 0)
01102         {
01103           TAO_ETCL_Literal_Constraint right;
01104           this->queue_.dequeue_head (right);
01105           CORBA::Boolean result =
01106             (ACE_OS::strstr ((const char *) right,
01107                              (const char *) left) != 0);
01108           this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result));
01109           return_value = 0;
01110         }
01111     }
01112 
01113   return return_value;
01114 }
01115 
01116 int
01117 TAO_Notify_Constraint_Visitor::visit_in (ETCL_Binary_Expr *binary)
01118 {
01119   int return_value = -1;
01120   ETCL_Constraint *lhs = binary->lhs ();
01121 
01122   // Determine if the left operand is contained in the right.
01123   if (lhs->accept (this) == 0)
01124     {
01125       TAO_ETCL_Literal_Constraint left;
01126       this->queue_.dequeue_head (left);
01127 
01128       ETCL_Constraint *rhs = binary->rhs ();
01129 
01130       if (rhs->accept (this) == 0)
01131         {
01132           TAO_ETCL_Literal_Constraint bag;
01133           this->queue_.dequeue_head (bag);
01134 
01135           if (bag.expr_type () == ETCL_COMPONENT)
01136             {
01137               CORBA::Any_ptr any_ptr = 0;
01138               ACE_NEW_RETURN (any_ptr,
01139                               CORBA::Any,
01140                               -1);
01141                               
01142               CORBA::Any_var component = any_ptr;
01143               component->replace (bag);
01144               component->impl ()->_add_ref ();
01145               CORBA::TCKind kind = CORBA::tk_null;
01146 
01147               try
01148               {
01149                 CORBA::TypeCode_var tc = component->type ();
01150                 kind = TAO_DynAnyFactory::unalias (tc.in ());
01151               }
01152               catch (const CORBA::Exception&)
01153               {
01154                 return return_value;
01155               }
01156 
01157               CORBA::Boolean result = 0;
01158 
01159               switch (kind)
01160               {
01161               case CORBA::tk_sequence:
01162                 result = this->sequence_does_contain (&component.in (),
01163                                                       left);
01164                 break;
01165               case CORBA::tk_array:
01166                 result = this->array_does_contain (&component.in (),
01167                                                    left);
01168                 break;
01169               case CORBA::tk_struct:
01170                 result = this->struct_does_contain (&component.in (),
01171                                                     left);
01172                 break;
01173               case CORBA::tk_union:
01174                 result = this->union_does_contain (&component.in (),
01175                                                    left);
01176                 break;
01177               case CORBA::tk_any:
01178                 result = this->any_does_contain (&component.in (),
01179                                                  left);
01180                 break;
01181               default:
01182                 return return_value;
01183               }
01184 
01185               this->queue_.enqueue_head (TAO_ETCL_Literal_Constraint (result));
01186               return_value = 0;
01187             }
01188         }
01189     }
01190 
01191   return return_value;
01192 }
01193 
01194 int
01195 TAO_Notify_Constraint_Visitor::visit_preference (ETCL_Preference *)
01196 {
01197   // According to OMG 00-06-20 section 2.4.1, the Notification Service
01198   // does not use the preference operators. The method must be here
01199   // because it is called by the ETCL node, which may be used by other
01200   // CORBA services that do use the preference operators.
01201   return -1;
01202 }
01203 
01204 CORBA::Boolean
01205 TAO_Notify_Constraint_Visitor::sequence_does_contain (
01206     const CORBA::Any *any,
01207     TAO_ETCL_Literal_Constraint &item
01208   )
01209 {
01210   try
01211   {
01212     CORBA::TypeCode_var type = any->type ();
01213     CORBA::TypeCode_var base_type =
01214       TAO_DynAnyFactory::strip_alias (type.in ());
01215     CORBA::TypeCode_var content_type =
01216       base_type->content_type ();
01217     CORBA::TCKind kind =
01218       TAO_DynAnyFactory::unalias (content_type.in ());
01219 
01220     // The literal and the array elements must be
01221     // of the same simple type.
01222     CORBA::Boolean match =
01223       this->simple_type_match (item.expr_type (),
01224                                kind);
01225 
01226     if (!match)
01227       {
01228         return false;
01229       }
01230 
01231     TAO_DynSequence_i dyn_seq;
01232     dyn_seq.init (*any);
01233 
01234     DynamicAny::AnySeq_var any_seq = dyn_seq.get_elements ();
01235 
01236     CORBA::ULong length = any_seq->length ();
01237 
01238     for (CORBA::ULong i = 0; i < length; ++i)
01239       {
01240         TAO_ETCL_Literal_Constraint element (&any_seq[i]);
01241 
01242         if (item == element)
01243           {
01244             return true;
01245           }
01246       }
01247   }
01248   catch (const CORBA::Exception&)
01249   {
01250     return false;
01251   }
01252 
01253   return false;
01254 }
01255 
01256 CORBA::Boolean
01257 TAO_Notify_Constraint_Visitor::array_does_contain (
01258     const CORBA::Any *any,
01259     TAO_ETCL_Literal_Constraint &item
01260   )
01261 {
01262   try
01263   {
01264     CORBA::TypeCode_var type = any->type ();
01265     CORBA::TCKind kind = TAO_DynAnyFactory::unalias (type.in ());
01266 
01267     // The literal and the array elements must be
01268     // of the same simple type.
01269     CORBA::Boolean match =
01270       this->simple_type_match (item.expr_type (),
01271                                kind);
01272 
01273     if (!match)
01274       {
01275         return false;
01276       }
01277 
01278     TAO_DynArray_i dyn_array;
01279     dyn_array.init (*any);
01280 
01281     DynamicAny::AnySeq_var any_seq = dyn_array.get_elements ();
01282 
01283     CORBA::ULong length = any_seq->length ();
01284 
01285     for (CORBA::ULong i = 0; i < length; ++i)
01286       {
01287         TAO_ETCL_Literal_Constraint element (&any_seq[i]);
01288 
01289         if (item == element)
01290           {
01291             return true;
01292           }
01293       }
01294   }
01295   catch (const CORBA::Exception&)
01296   {
01297     return false;
01298   }
01299 
01300   return false;
01301 }
01302 
01303 CORBA::Boolean
01304 TAO_Notify_Constraint_Visitor::struct_does_contain (
01305     const CORBA::Any *any,
01306     TAO_ETCL_Literal_Constraint &item
01307   )
01308 {
01309   try
01310   {
01311     TAO_DynStruct_i dyn_struct;
01312     dyn_struct.init (*any);
01313 
01314     DynamicAny::NameValuePairSeq_var members =
01315       dyn_struct.get_members ();
01316 
01317     CORBA::ULong length = members->length ();
01318     CORBA::TypeCode_var tc;
01319     CORBA::TCKind kind;
01320 
01321     for (CORBA::ULong i = 0; i < length; ++i)
01322       {
01323         tc = members[i].value.type ();
01324         kind = TAO_DynAnyFactory::unalias (tc.in ());
01325 
01326         // The literal and the struct member must be
01327         // of the same simple type.
01328         CORBA::Boolean match =
01329           this->simple_type_match (item.expr_type (),
01330                                    kind);
01331 
01332         if (!match)
01333           {
01334             continue;
01335           }
01336 
01337         TAO_ETCL_Literal_Constraint element (&members[i].value);
01338 
01339         if (item == element)
01340           {
01341             return true;
01342           }
01343       }
01344   }
01345   catch (const CORBA::Exception&)
01346   {
01347     return false;
01348   }
01349 
01350   return false;
01351 }
01352 
01353 CORBA::Boolean
01354 TAO_Notify_Constraint_Visitor::union_does_contain (
01355     const CORBA::Any *any,
01356     TAO_ETCL_Literal_Constraint &item
01357   )
01358 {
01359   try
01360   {
01361     TAO_DynUnion_i dyn_union;
01362     dyn_union.init (*any);
01363 
01364     DynamicAny::DynAny_var cc =
01365       dyn_union.current_component ();
01366 
01367     CORBA::Any_var member = cc->to_any ();
01368 
01369     CORBA::TypeCode_var tc = member->type ();
01370     CORBA::TCKind kind = TAO_DynAnyFactory::unalias (tc.in ());
01371 
01372     // The literal and the union member must be
01373     // of the same simple type.
01374     CORBA::Boolean match =
01375       this->simple_type_match (item.expr_type (),
01376                                kind);
01377 
01378     if (!match)
01379       {
01380         return false;
01381       }
01382 
01383     TAO_ETCL_Literal_Constraint element (&member.inout ());
01384 
01385     return (item == element);
01386   }
01387   catch (const CORBA::Exception&)
01388   {
01389     return false;
01390   }
01391 }
01392 
01393 CORBA::Boolean
01394 TAO_Notify_Constraint_Visitor::any_does_contain (
01395     const CORBA::Any *any,
01396     TAO_ETCL_Literal_Constraint &item
01397   )
01398 {
01399   const CORBA::Any *result = 0;
01400   *any >>= result;
01401 
01402   TAO_ETCL_Literal_Constraint element (const_cast<CORBA::Any *>(result));
01403   return item == element;
01404 }
01405 
01406 CORBA::Boolean
01407 TAO_Notify_Constraint_Visitor::simple_type_match (int expr_type,
01408                                                   CORBA::TCKind tc_kind)
01409 {
01410   switch (expr_type)
01411   {
01412   case ETCL_STRING:
01413     if (tc_kind != CORBA::tk_string)
01414       {
01415         return false;
01416       }
01417     break;
01418   case ETCL_DOUBLE:
01419     if (tc_kind != CORBA::tk_double && tc_kind != CORBA::tk_float)
01420       {
01421         return false;
01422       }
01423     break;
01424   case ETCL_INTEGER:
01425   case ETCL_SIGNED:
01426     if (tc_kind != CORBA::tk_short
01427         && tc_kind != CORBA::tk_long
01428         && tc_kind != CORBA::tk_longlong)
01429       {
01430         return false;
01431       }
01432     break;
01433   case ETCL_UNSIGNED:
01434     if (tc_kind != CORBA::tk_ushort
01435         && tc_kind != CORBA::tk_ulong
01436         && tc_kind != CORBA::tk_ulonglong)
01437       {
01438         return false;
01439       }
01440     break;
01441   case ETCL_BOOLEAN:
01442     if (tc_kind != CORBA::tk_boolean)
01443       {
01444         return false;
01445       }
01446     break;
01447   default:
01448     return false;
01449   }
01450   
01451   return true;
01452 }
01453 
01454 const size_t TAO_Notify_Constraint_Visitor::implicit_ids_size_ = 27;
01455 const size_t TAO_Notify_Constraint_Visitor::filterable_data_size_ = 31;
01456 const size_t TAO_Notify_Constraint_Visitor::variable_header_size_ = 31;
01457 
01458 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Tue Feb 2 17:45:29 2010 for TAO_CosNotification by  doxygen 1.4.7