2 #include "tao/DynamicAny/DynStruct_i.h"
3 #include "tao/DynamicAny/DynAnyFactory.h"
4 #include "tao/DynamicAny/DynAnyUtils_T.h"
6 #include "tao/AnyTypeCode/Marshal.h"
7 #include "tao/AnyTypeCode/Any_Unknown_IDL_Type.h"
8 #include "tao/AnyTypeCode/AnyTypeCode_methods.h"
12 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
14 TAO_DynStruct_i::TAO_DynStruct_i (CORBA::Boolean allow_truncation
)
15 : TAO_DynCommon (allow_truncation
)
19 TAO_DynStruct_i::~TAO_DynStruct_i ()
24 TAO_DynStruct_i::check_typecode (CORBA::TypeCode_ptr tc
)
26 CORBA::TCKind kind
= TAO_DynAnyFactory::unalias (tc
);
28 if (kind
== CORBA::tk_struct
|| kind
== CORBA::tk_except
)
33 throw DynamicAny::DynAnyFactory::InconsistentTypeCode ();
37 TAO_DynStruct_i::init_common ()
39 this->ref_to_component_
= false;
40 this->container_is_destroying_
= false;
41 this->has_components_
= true;
42 this->destroyed_
= false;
43 this->component_count_
= static_cast <CORBA::ULong
> (this->da_members_
.size ());
44 this->current_position_
= this->component_count_
? 0 : -1;
48 TAO_DynStruct_i::init (const CORBA::Any
& any
)
50 CORBA::TypeCode_ptr tc
= any
._tao_get_typecode ();
51 this->check_typecode (tc
);
53 this->type_
= CORBA::TypeCode::_duplicate (tc
);
55 this->set_from_any (any
);
59 // This code is common to from_any() and the init() overload that takes
62 TAO_DynStruct_i::set_from_any (const CORBA::Any
& any
)
64 // member_type() does not work with aliased type codes.
65 CORBA::TypeCode_var unaliased_tc
=
66 TAO_DynAnyFactory::strip_alias (any
._tao_get_typecode ());
68 CORBA::ULong numfields
=
69 unaliased_tc
->member_count ();
72 this->da_members_
.size (numfields
);
76 // Get the CDR stream of the Any, if there isn't one, make one.
77 TAO::Any_Impl
*impl
= any
.impl ();
79 TAO_InputCDR
in (static_cast<ACE_Message_Block
*> (0));
80 TAO::Unknown_IDL_Type
*unk
= 0;
84 unk
= dynamic_cast<TAO::Unknown_IDL_Type
*> (impl
);
87 throw CORBA::INTERNAL ();
89 in
= unk
->_tao_get_cdr ();
93 impl
->marshal_value (out
);
94 TAO_InputCDR
tmp_in (out
);
98 // If we have an exception type, unmarshal the repository ID.
99 CORBA::TCKind kind
= TAO_DynAnyFactory::unalias (any
._tao_get_typecode ());
101 if (kind
== CORBA::tk_except
)
103 CORBA::String_var str
;
107 for (CORBA::ULong i
= 0; i
< numfields
; i
++)
109 CORBA::TypeCode_var field_tc
=
110 unaliased_tc
->member_type (i
);
112 CORBA::Any field_any
;
113 TAO_InputCDR
unk_in (in
);
115 TAO::Unknown_IDL_Type (field_tc
.in (),
117 field_any
.replace (unk
);
119 // This recursive step will call the correct constructor
120 // based on the type of field_any.
121 this->da_members_
[i
] =
122 TAO::MakeDynAnyUtils::make_dyn_any_t
<const CORBA::Any
&> (
123 field_any
._tao_get_typecode (),
125 this->allow_truncation_
);
127 // Move to the next field in the CDR stream.
128 (void) TAO_Marshal_Object::perform_skip (field_tc
.in (), &in
);
133 TAO_DynStruct_i::init (CORBA::TypeCode_ptr tc
)
135 this->check_typecode (tc
);
137 this->type_
= CORBA::TypeCode::_duplicate (tc
);
139 // member_type() does not work with aliased type codes.
140 CORBA::TypeCode_var unaliased_tc
=
141 TAO_DynAnyFactory::strip_alias (this->type_
.in ());
143 this->component_count_
=
144 unaliased_tc
->member_count ();
147 this->da_members_
.size (this->component_count_
);
149 this->init_common ();
151 CORBA::TypeCode_var mtype
;
153 for (CORBA::ULong i
= 0; i
< this->component_count_
; ++i
)
155 mtype
= unaliased_tc
->member_type (i
);
157 // Recursively initialize each member.
158 this->da_members_
[i
] =
159 TAO::MakeDynAnyUtils::make_dyn_any_t
<CORBA::TypeCode_ptr
> (
162 this->allow_truncation_
);
166 // ****************************************************************
169 TAO_DynStruct_i::_narrow (CORBA::Object_ptr _tao_objref
)
171 if (CORBA::is_nil (_tao_objref
))
176 return dynamic_cast<TAO_DynStruct_i
*> (_tao_objref
);
179 // ****************************************************************
181 DynamicAny::FieldName
182 TAO_DynStruct_i::current_member_name ()
184 if (this->destroyed_
)
186 throw ::CORBA::OBJECT_NOT_EXIST ();
189 // Is this an empty exception?
190 if (this->component_count_
== 0)
192 throw DynamicAny::DynAny::TypeMismatch ();
195 if (this->current_position_
== -1)
197 throw DynamicAny::DynAny::InvalidValue ();
200 // member_name() does not work with aliased type codes.
201 CORBA::TypeCode_var unaliased_tc
=
202 TAO_DynAnyFactory::strip_alias (this->type_
.in ());
204 unaliased_tc
->member_name (this->current_position_
);
206 return CORBA::string_dup (name
);
209 // Returns the unaliased TCKind.
211 TAO_DynStruct_i::current_member_kind ()
213 if (this->destroyed_
)
215 throw ::CORBA::OBJECT_NOT_EXIST ();
218 // Is this an empty exception?
219 if (this->component_count_
== 0)
221 throw DynamicAny::DynAny::TypeMismatch ();
224 if (this->current_position_
== -1)
226 throw DynamicAny::DynAny::InvalidValue ();
229 // member_type() does not work with aliased type codes.
230 CORBA::TypeCode_var unaliased_tc
=
231 TAO_DynAnyFactory::strip_alias (this->type_
.in ());
232 CORBA::TypeCode_var tc
=
233 unaliased_tc
->member_type (this->current_position_
);
235 CORBA::TCKind retval
= TAO_DynAnyFactory::unalias (tc
.in ());
240 DynamicAny::NameValuePairSeq
*
241 TAO_DynStruct_i::get_members ()
243 if (this->destroyed_
)
245 throw ::CORBA::OBJECT_NOT_EXIST ();
248 DynamicAny::NameValuePairSeq
* members
;
249 ACE_NEW_THROW_EX (members
,
250 DynamicAny::NameValuePairSeq (this->component_count_
),
251 CORBA::NO_MEMORY ());
253 // We must do this explicitly.
254 members
->length (this->component_count_
);
256 DynamicAny::NameValuePairSeq_var safe_retval
= members
;
258 CORBA::TypeCode_var unaliased_tc
;
260 CORBA::TCKind
const tc_kind
=
261 this->type_
->kind ();
263 if (tc_kind
== CORBA::tk_alias
)
265 unaliased_tc
= TAO_DynAnyFactory::strip_alias (this->type_
.in ());
269 unaliased_tc
= CORBA::TypeCode::_duplicate (this->type_
.in ());
272 // Assign name and value to each pearl on the string.
273 for (CORBA::ULong i
= 0; i
< this->component_count_
; ++i
)
276 CORBA::string_dup (unaliased_tc
->member_name (i
));
278 temp
= this->da_members_
[i
]->to_any ();
280 safe_retval
[i
].value
= temp
.in ();
283 return safe_retval
._retn ();
287 TAO_DynStruct_i::set_members (const DynamicAny::NameValuePairSeq
& values
)
289 if (this->destroyed_
)
291 throw ::CORBA::OBJECT_NOT_EXIST ();
294 CORBA::ULong length
= values
.length ();
296 // Check for length match.
297 if (length
!= this->component_count_
)
299 throw DynamicAny::DynAny::InvalidValue ();
302 CORBA::TypeCode_var value_tc
;
303 CORBA::TypeCode_var my_tc
;
304 CORBA::Boolean equivalent
;
306 // member_type() does not work with aliased type codes.
307 CORBA::TypeCode_var unaliased_tc
=
308 TAO_DynAnyFactory::strip_alias (this->type_
.in ());
310 for (CORBA::ULong i
= 0; i
< length
; ++i
)
312 // Check for type and name match.
313 my_tc
= unaliased_tc
->member_type (i
);
315 value_tc
= values
[i
].value
.type ();
317 equivalent
= my_tc
->equivalent (value_tc
.in ());
321 throw DynamicAny::DynAny::TypeMismatch ();
324 this->da_members_
[i
]->destroy ();
326 this->da_members_
[i
] =
327 TAO::MakeDynAnyUtils::make_dyn_any_t
<const CORBA::Any
&> (
328 values
[i
].value
._tao_get_typecode (),
330 this->allow_truncation_
);
333 this->current_position_
= length
? 0 : -1;
336 DynamicAny::NameDynAnyPairSeq
*
337 TAO_DynStruct_i::get_members_as_dyn_any ()
339 if (this->destroyed_
)
341 throw ::CORBA::OBJECT_NOT_EXIST ();
344 DynamicAny::NameDynAnyPairSeq
* members
;
345 ACE_NEW_THROW_EX (members
,
346 DynamicAny::NameDynAnyPairSeq (this->component_count_
),
347 CORBA::NO_MEMORY ());
349 // We must do this explicitly.
350 members
->length (this->component_count_
);
352 DynamicAny::NameDynAnyPairSeq_var safe_retval
= members
;
354 // member_name() does not work with aliased type codes.
355 CORBA::TypeCode_var unaliased_tc
=
356 TAO_DynAnyFactory::strip_alias (this->type_
.in ());
358 // Assign name and value to each pearl on the string.
359 for (CORBA::ULong i
= 0; i
< this->component_count_
; ++i
)
361 safe_retval
[i
].id
= CORBA::string_dup (unaliased_tc
->member_name (i
));
363 // A deep copy is made only by copy() (CORBA 2.4.2 section 9.2.3.6).
364 // Set the flag so the caller can't destroy.
365 this->set_flag (this->da_members_
[i
].in (), 0);
367 safe_retval
[i
].value
=
368 DynamicAny::DynAny::_duplicate (this->da_members_
[i
].in ());
371 return safe_retval
._retn ();
375 TAO_DynStruct_i::set_members_as_dyn_any (
376 const DynamicAny::NameDynAnyPairSeq
& values
380 if (this->destroyed_
)
382 throw ::CORBA::OBJECT_NOT_EXIST ();
385 CORBA::ULong length
= values
.length ();
387 // Check for length match.
388 if (length
!= this->component_count_
)
390 throw DynamicAny::DynAny::InvalidValue ();
393 CORBA::TypeCode_var value_tc
;
394 CORBA::TypeCode_var my_tc
;
395 CORBA::Boolean equivalent
;
397 // member_type() does not work with aliased type codes.
398 CORBA::TypeCode_var unaliased_tc
=
399 TAO_DynAnyFactory::strip_alias (this->type_
.in ());
401 for (CORBA::ULong i
= 0; i
< length
; ++i
)
403 // Check for type and name match.
404 my_tc
= unaliased_tc
->member_type (i
);
406 value_tc
= values
[i
].value
->type ();
408 equivalent
= my_tc
->equivalent (value_tc
.in ());
412 throw DynamicAny::DynAny::TypeMismatch ();
415 this->da_members_
[i
]->destroy ();
417 this->da_members_
[i
] =
418 values
[i
].value
->copy ();
421 this->current_position_
= length
? 0 : -1;
424 // ****************************************************************
427 TAO_DynStruct_i::from_any (const CORBA::Any
& any
)
429 if (this->destroyed_
)
431 throw ::CORBA::OBJECT_NOT_EXIST ();
434 CORBA::TypeCode_var tc
= any
.type ();
435 CORBA::Boolean equivalent
=
436 this->type_
->equivalent (tc
.in ());
440 // Get the CDR stream of the Any, if there isn't one, make one.
441 TAO::Any_Impl
*impl
= any
.impl ();
443 TAO_InputCDR
in (static_cast<ACE_Message_Block
*> (0));
444 TAO::Unknown_IDL_Type
*unk
= 0;
446 if (impl
->encoded ())
448 unk
= dynamic_cast<TAO::Unknown_IDL_Type
*> (impl
);
451 throw CORBA::INTERNAL ();
453 in
= unk
->_tao_get_cdr ();
457 impl
->marshal_value (out
);
458 TAO_InputCDR
tmp_in (out
);
462 // If we have an exception type, unmarshal the repository ID.
464 TAO_DynAnyFactory::unalias (this->type_
.in ());
466 if (kind
== CORBA::tk_except
)
468 CORBA::String_var str
;
472 CORBA::TypeCode_var field_tc
;
473 CORBA::TypeCode_var unaliased
=
474 TAO::unaliased_typecode (this->type_
.in ());
476 for (CORBA::ULong i
= 0; i
< this->component_count_
; ++i
)
478 field_tc
= unaliased
->member_type (i
);
480 CORBA::Any field_any
;
481 TAO_InputCDR
unk_in (in
);
482 TAO::Unknown_IDL_Type
*unk
= 0;
484 TAO::Unknown_IDL_Type (field_tc
.in (),
486 field_any
.replace (unk
);
488 this->da_members_
[i
]->destroy ();
490 this->da_members_
[i
] =
491 TAO::MakeDynAnyUtils::make_dyn_any_t
<const CORBA::Any
&> (
492 field_any
._tao_get_typecode (),
494 this->allow_truncation_
);
496 // Move to the next field in the CDR stream.
497 (void) TAO_Marshal_Object::perform_skip (field_tc
.in (), &in
);
500 this->current_position_
= this->component_count_
? 0 : -1;
504 throw DynamicAny::DynAny::TypeMismatch ();
509 TAO_DynStruct_i::to_any ()
511 if (this->destroyed_
)
513 throw ::CORBA::OBJECT_NOT_EXIST ();
516 TAO_OutputCDR out_cdr
;
518 // If we have an exception type, marshal the repository ID.
519 CORBA::TCKind kind
= TAO_DynAnyFactory::unalias (this->type_
.in ());
521 if (kind
== CORBA::tk_except
)
523 out_cdr
<< this->type_
->id ();
526 TAO::Any_Impl
*field_impl
= 0;
527 TAO::Unknown_IDL_Type
*field_unk
= 0;
528 TAO_InputCDR
field_in_cdr (static_cast<ACE_Message_Block
*> (0));
530 for (CORBA::ULong i
= 0; i
< this->component_count_
; ++i
)
532 CORBA::TypeCode_var field_tc
=
533 this->da_members_
[i
]->type ();
536 CORBA::Any_var field_any
=
537 this->da_members_
[i
]->to_any ();
539 TAO_OutputCDR field_out_cdr
;
540 field_impl
= field_any
->impl ();
542 if (field_impl
->encoded ())
545 dynamic_cast<TAO::Unknown_IDL_Type
*> (field_impl
);
548 throw CORBA::INTERNAL ();
550 field_in_cdr
= field_unk
->_tao_get_cdr ();
554 field_impl
->marshal_value (field_out_cdr
);
555 TAO_InputCDR
tmp (field_out_cdr
);
559 (void) TAO_Marshal_Object::perform_append (field_tc
.in (),
564 TAO_InputCDR
in_cdr (out_cdr
);
566 CORBA::Any_ptr retval
= 0;
567 ACE_NEW_THROW_EX (retval
,
569 CORBA::NO_MEMORY ());
571 TAO::Unknown_IDL_Type
*unk
= 0;
572 ACE_NEW_THROW_EX (unk
,
573 TAO::Unknown_IDL_Type (this->type_
.in (),
575 CORBA::NO_MEMORY ());
577 retval
->replace (unk
);
582 TAO_DynStruct_i::equal (DynamicAny::DynAny_ptr rhs
)
584 if (this->destroyed_
)
586 throw ::CORBA::OBJECT_NOT_EXIST ();
589 CORBA::TypeCode_var tc
= rhs
->type ();
591 if (!tc
->equivalent (this->type_
.in ()))
596 DynamicAny::DynAny_var tmp
;
597 CORBA::Boolean member_equal
;
599 for (CORBA::ULong i
= 0; i
< this->component_count_
; ++i
)
601 rhs
->seek (static_cast <CORBA::Long
> (i
));
603 tmp
= rhs
->current_component ();
606 member_equal
= tmp
->equal (this->da_members_
[i
].in ());
618 TAO_DynStruct_i::destroy ()
620 if (this->destroyed_
)
622 throw ::CORBA::OBJECT_NOT_EXIST ();
625 if (!this->ref_to_component_
|| this->container_is_destroying_
)
627 // Do a deep destroy.
628 for (CORBA::ULong i
= 0; i
< this->component_count_
; ++i
)
630 this->set_flag (da_members_
[i
].in (), 1);
632 this->da_members_
[i
]->destroy ();
635 this->destroyed_
= 1;
639 DynamicAny::DynAny_ptr
640 TAO_DynStruct_i::current_component ()
642 if (this->destroyed_
)
644 throw ::CORBA::OBJECT_NOT_EXIST ();
647 if (this->component_count_
== 0)
649 // Empty exception - no component.
650 throw DynamicAny::DynAny::TypeMismatch ();
653 if (this->current_position_
== -1)
655 return DynamicAny::DynAny::_nil ();
658 CORBA::ULong index
= static_cast <CORBA::ULong
> (this->current_position_
);
660 this->set_flag (this->da_members_
[index
].in (), 0);
662 return DynamicAny::DynAny::_duplicate (this->da_members_
[index
].in ());
665 TAO_END_VERSIONED_NAMESPACE_DECL