Merge pull request #1551 from DOCGroup/plm_jira_333
[ACE_TAO.git] / TAO / tao / DynamicAny / DynArray_i.cpp
blobc70f37b176355a4b884686a8e84b92d58ced52bd
1 // -*- C++ -*-
2 #include "tao/DynamicAny/DynArray_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"
10 #include "tao/CDR.h"
12 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
14 TAO_DynArray_i::TAO_DynArray_i (CORBA::Boolean allow_truncation)
15 : TAO_DynCommon (allow_truncation)
19 TAO_DynArray_i::~TAO_DynArray_i (void)
23 void
24 TAO_DynArray_i::init_common (void)
26 this->ref_to_component_ = false;
27 this->container_is_destroying_ = false;
28 this->has_components_ = true;
29 this->destroyed_ = false;
30 this->current_position_ = 0;
31 this->component_count_ = static_cast<CORBA::ULong> (this->da_members_.size ());
34 void
35 TAO_DynArray_i::init (const CORBA::Any & any)
37 CORBA::TypeCode_var tc = any.type ();
39 CORBA::TCKind kind = TAO_DynAnyFactory::unalias (tc.in ());
41 if (kind != CORBA::tk_array)
43 throw DynamicAny::DynAnyFactory::InconsistentTypeCode ();
46 this->type_ = tc;
48 CORBA::ULong numfields = this->get_tc_length (tc.in ());
49 // Resize the array.
50 this->da_members_.size (numfields);
52 this->init_common ();
54 // Get the CDR stream of the Any, if there isn't one, make one.
55 TAO::Any_Impl *impl = any.impl ();
56 TAO_OutputCDR out;
57 TAO_InputCDR cdr (static_cast<ACE_Message_Block *> (0));
59 if (impl->encoded ())
61 TAO::Unknown_IDL_Type * const unk =
62 dynamic_cast<TAO::Unknown_IDL_Type *> (impl);
64 if (!unk)
65 throw CORBA::INTERNAL ();
67 cdr = unk->_tao_get_cdr ();
69 else
71 impl->marshal_value (out);
72 TAO_InputCDR tmp_in (out);
73 cdr = tmp_in;
76 CORBA::TypeCode_var field_tc =
77 this->get_element_type ();
79 for (CORBA::ULong i = 0; i < numfields; ++i)
81 CORBA::Any field_any;
82 TAO::Unknown_IDL_Type *field_unk = 0;
83 TAO_InputCDR unk_in (cdr);
84 ACE_NEW (field_unk,
85 TAO::Unknown_IDL_Type (field_tc.in (), unk_in));
86 field_any.replace (field_unk);
88 // This recursive step will call the correct constructor
89 // based on the type of field_any.
90 this->da_members_[i] =
91 TAO::MakeDynAnyUtils::make_dyn_any_t<const CORBA::Any&> (
92 field_any._tao_get_typecode (),
93 field_any,
94 this->allow_truncation_ );
96 // Move to the next field in the CDR stream.
97 (void) TAO_Marshal_Object::perform_skip (field_tc.in (), &cdr);
101 void
102 TAO_DynArray_i::init (CORBA::TypeCode_ptr tc)
104 CORBA::TCKind kind = TAO_DynAnyFactory::unalias (tc);
106 if (kind != CORBA::tk_array)
108 throw DynamicAny::DynAnyFactory::InconsistentTypeCode ();
111 this->type_ = CORBA::TypeCode::_duplicate (tc);
113 CORBA::ULong numfields = this->get_tc_length (tc);
115 // Resize the array.
116 this->da_members_.size (numfields);
118 this->init_common ();
120 CORBA::TypeCode_var elemtype = this->get_element_type ();
122 for (CORBA::ULong i = 0; i < numfields; ++i)
124 // Recursively initialize each element.
125 this->da_members_[i] =
126 TAO::MakeDynAnyUtils::make_dyn_any_t<CORBA::TypeCode_ptr> (
127 elemtype.in (),
128 elemtype.in (),
129 this->allow_truncation_ );
133 CORBA::TypeCode_ptr
134 TAO_DynArray_i::get_element_type (void)
136 CORBA::TypeCode_var element_type =
137 CORBA::TypeCode::_duplicate (this->type_.in ());
139 // Strip away aliases (if any) on top of the outer type
140 CORBA::TCKind kind = element_type->kind ();
142 while (kind != CORBA::tk_array)
144 element_type = element_type->content_type ();
146 kind = element_type->kind ();
149 // Return the content type.
150 return element_type->content_type ();
153 // Get the length from the (possibly aliased) typecode.
154 CORBA::ULong
155 TAO_DynArray_i::get_tc_length (CORBA::TypeCode_ptr tc)
157 CORBA::TypeCode_var tctmp = CORBA::TypeCode::_duplicate (tc);
158 CORBA::TCKind kind = tctmp->kind ();
160 while (kind == CORBA::tk_alias)
162 tctmp = tctmp->content_type ();
163 kind = tctmp->kind ();
166 return tctmp->length ();
169 // ****************************************************************
171 TAO_DynArray_i *
172 TAO_DynArray_i::_narrow (CORBA::Object_ptr _tao_objref)
174 if (CORBA::is_nil (_tao_objref))
176 return 0;
179 return dynamic_cast<TAO_DynArray_i *> (_tao_objref);
182 // ****************************************************************
184 DynamicAny::AnySeq *
185 TAO_DynArray_i::get_elements (void)
187 if (this->destroyed_)
189 throw ::CORBA::OBJECT_NOT_EXIST ();
192 CORBA::ULong length = static_cast<CORBA::ULong> (this->da_members_.size ());
194 DynamicAny::AnySeq *elements = 0;
195 ACE_NEW_THROW_EX (elements,
196 DynamicAny::AnySeq (length),
197 CORBA::NO_MEMORY ());
199 elements->length (length);
200 DynamicAny::AnySeq_var safe_retval (elements);
202 CORBA::Any_var tmp;
204 // Initialize each Any.
205 for (CORBA::ULong i = 0; i < length; i++)
207 tmp = this->da_members_[i]->to_any ();
209 safe_retval[i] = tmp.in ();
212 return safe_retval._retn ();
215 void
216 TAO_DynArray_i::set_elements (const DynamicAny::AnySeq & value)
218 if (this->destroyed_)
220 throw ::CORBA::OBJECT_NOT_EXIST ();
223 CORBA::ULong const length = value.length ();
225 if (length != this->da_members_.size ())
227 throw DynamicAny::DynAny::InvalidValue ();
230 CORBA::TypeCode_var value_tc;
231 CORBA::TypeCode_var element_type = this->get_element_type ();
233 for (CORBA::ULong i = 0; i < length; i++)
235 // Check each arg element for type match.
236 value_tc = value[i].type ();
237 CORBA::Boolean equivalent =
238 value_tc->equivalent (element_type.in ());
240 if (equivalent)
242 this->da_members_[i]->destroy ();
244 this->da_members_[i] =
245 TAO::MakeDynAnyUtils::make_dyn_any_t<const CORBA::Any&> (
246 value[i]._tao_get_typecode (),
247 value[i],
248 this->allow_truncation_ );
250 else
252 throw DynamicAny::DynAny::TypeMismatch ();
257 DynamicAny::DynAnySeq *
258 TAO_DynArray_i::get_elements_as_dyn_any (void)
260 if (this->destroyed_)
262 throw ::CORBA::OBJECT_NOT_EXIST ();
265 DynamicAny::DynAnySeq *retval = 0;
266 ACE_NEW_THROW_EX (retval,
267 DynamicAny::DynAnySeq (this->component_count_),
268 CORBA::NO_MEMORY ());
270 retval->length (this->component_count_);
271 DynamicAny::DynAnySeq_var safe_retval (retval);
273 for (CORBA::ULong i = 0; i < this->component_count_; ++i)
275 // A deep copy is made only by copy() (CORBA 2.4.2 section 9.2.3.6).
276 // Set the flag so the caller can't destroy.
277 this->set_flag (this->da_members_[i].in (), 0);
279 safe_retval[i] =
280 DynamicAny::DynAny::_duplicate (this->da_members_[i].in ());
283 return safe_retval._retn ();
286 void
287 TAO_DynArray_i::set_elements_as_dyn_any (
288 const DynamicAny::DynAnySeq & values
292 if (this->destroyed_)
294 throw ::CORBA::OBJECT_NOT_EXIST ();
297 CORBA::ULong length = static_cast<CORBA::ULong> (this->da_members_.size ());
299 if (values.length () != length)
301 throw DynamicAny::DynAny::InvalidValue ();
304 CORBA::TypeCode_var element_type = this->get_element_type ();
306 CORBA::TypeCode_var val_type;
307 CORBA::Boolean equivalent;
309 for (CORBA::ULong i = 0; i < length; ++i)
311 val_type = values[i]->type ();
313 equivalent = val_type->equivalent (element_type.in ());
316 if (equivalent)
318 this->da_members_[i] = values[i]->copy ();
320 else
322 throw DynamicAny::DynAny::TypeMismatch ();
327 // ****************************************************************
329 void
330 TAO_DynArray_i::from_any (const CORBA::Any& any)
332 if (this->destroyed_)
334 throw ::CORBA::OBJECT_NOT_EXIST ();
337 CORBA::TypeCode_var tc = any.type ();
338 CORBA::Boolean equivalent = this->type_.in ()->equivalent (tc.in ());
340 if (equivalent)
342 // Get the CDR stream of the Any,if there isn't one, make one.
343 TAO::Any_Impl *impl = any.impl ();
344 TAO_OutputCDR out;
345 TAO_InputCDR cdr (static_cast<ACE_Message_Block *> (0));
347 if (impl->encoded ())
349 TAO::Unknown_IDL_Type * const unk =
350 dynamic_cast<TAO::Unknown_IDL_Type *> (impl);
352 if (!unk)
353 throw CORBA::INTERNAL ();
355 cdr = unk->_tao_get_cdr ();
357 else
359 impl->marshal_value (out);
360 TAO_InputCDR tmp_in (out);
361 cdr = tmp_in;
364 CORBA::ULong length = static_cast<CORBA::ULong> (this->da_members_.size ());
365 CORBA::ULong arg_length = this->get_tc_length (tc.in ());
367 if (length != arg_length)
369 throw DynamicAny::DynAny::TypeMismatch ();
372 CORBA::TypeCode_var field_tc = this->get_element_type ();
374 for (CORBA::ULong i = 0; i < arg_length; ++i)
376 CORBA::Any field_any;
377 TAO_InputCDR unk_in (cdr);
378 TAO::Unknown_IDL_Type *field_unk = 0;
379 ACE_NEW (field_unk,
380 TAO::Unknown_IDL_Type (field_tc.in (), unk_in));
381 field_any.replace (field_unk);
383 this->da_members_[i]->destroy ();
385 this->da_members_[i] =
386 TAO::MakeDynAnyUtils::make_dyn_any_t<const CORBA::Any&> (
387 field_any._tao_get_typecode (),
388 field_any,
389 this->allow_truncation_ );
391 // Move to the next field in the CDR stream.
392 (void) TAO_Marshal_Object::perform_skip (field_tc.in (), &cdr);
395 this->current_position_ = arg_length ? 0 : -1;
397 else
399 throw DynamicAny::DynAny::TypeMismatch ();
403 CORBA::Any_ptr
404 TAO_DynArray_i::to_any (void)
406 if (this->destroyed_)
408 throw ::CORBA::OBJECT_NOT_EXIST ();
411 CORBA::TypeCode_var field_tc = this->get_element_type ();
413 TAO_OutputCDR out_cdr;
414 CORBA::Any_var field_any;
415 size_t length = this->da_members_.size ();
417 for (size_t i = 0; i < length; ++i)
419 // Recursive step.
420 field_any = this->da_members_[i]->to_any ();
422 TAO::Any_Impl *field_impl = field_any->impl ();
423 TAO_OutputCDR field_out;
424 TAO_InputCDR field_cdr (static_cast<ACE_Message_Block *> (0));
426 if (field_impl->encoded ())
428 TAO::Unknown_IDL_Type * const field_unk =
429 dynamic_cast<TAO::Unknown_IDL_Type *> (field_impl);
431 if (!field_unk)
432 throw CORBA::INTERNAL ();
434 field_cdr = field_unk->_tao_get_cdr ();
436 else
438 field_impl->marshal_value (field_out);
439 TAO_InputCDR tmp_in (field_out);
440 field_cdr = tmp_in;
443 (void) TAO_Marshal_Object::perform_append (field_tc.in (),
444 &field_cdr,
445 &out_cdr);
448 TAO_InputCDR in_cdr (out_cdr);
450 CORBA::Any_ptr retval = 0;
451 ACE_NEW_THROW_EX (retval,
452 CORBA::Any,
453 CORBA::NO_MEMORY ());
455 TAO::Unknown_IDL_Type *unk = 0;
456 ACE_NEW_THROW_EX (unk,
457 TAO::Unknown_IDL_Type (this->type_.in (),
458 in_cdr),
459 CORBA::NO_MEMORY ());
461 retval->replace (unk);
462 return retval;
465 CORBA::Boolean
466 TAO_DynArray_i::equal (DynamicAny::DynAny_ptr rhs)
468 if (this->destroyed_)
470 throw ::CORBA::OBJECT_NOT_EXIST ();
473 CORBA::TypeCode_var tc = rhs->type ();
475 CORBA::Boolean equivalent = tc->equivalent (this->type_.in ());
477 if (!equivalent)
479 return false;
482 DynamicAny::DynAny_var tmp;
483 CORBA::Boolean member_equal;
485 for (CORBA::ULong i = 0; i < this->component_count_; ++i)
487 rhs->seek (static_cast<CORBA::Long> (i));
489 tmp = rhs->current_component ();
491 // Recursive step.
492 member_equal = tmp->equal (this->da_members_[i].in ());
494 if (!member_equal)
496 return false;
500 return true;
503 void
504 TAO_DynArray_i::destroy (void)
506 if (this->destroyed_)
508 throw ::CORBA::OBJECT_NOT_EXIST ();
511 if (!this->ref_to_component_ || this->container_is_destroying_)
513 // Do a deep destroy.
514 for (CORBA::ULong i = 0; i < this->component_count_; ++i)
516 this->set_flag (da_members_[i].in (), 1);
518 this->da_members_[i]->destroy ();
521 this->destroyed_ = 1;
525 DynamicAny::DynAny_ptr
526 TAO_DynArray_i::current_component (void)
528 if (this->destroyed_)
530 throw ::CORBA::OBJECT_NOT_EXIST ();
533 if (this->current_position_ == -1)
535 return DynamicAny::DynAny::_nil ();
538 CORBA::ULong index = static_cast<CORBA::ULong> (this->current_position_);
540 this->set_flag (this->da_members_[index].in (), 0);
542 return DynamicAny::DynAny::_duplicate (this->da_members_[index].in ());
545 TAO_END_VERSIONED_NAMESPACE_DECL