Merge pull request #1551 from DOCGroup/plm_jira_333
[ACE_TAO.git] / TAO / tao / DynamicAny / DynValueBox_i.cpp
blobe4c4711cfec49108ab0ec8f98334fe78551a3e10
1 // -*- C++ -*-
2 #include "tao/DynamicAny/DynValueBox_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_DynValueBox_i::TAO_DynValueBox_i (CORBA::Boolean allow_truncation)
15 : TAO_DynCommon (allow_truncation)
16 , TAO_DynAny_i (allow_truncation)
17 , TAO_DynValueCommon_i (allow_truncation)
21 TAO_DynValueBox_i::~TAO_DynValueBox_i (void)
25 void
26 TAO_DynValueBox_i::set_to_value (void)
28 if (CORBA::is_nil (this->boxed_.in ()))
30 set_to_null ();
32 else
34 this->is_null_ = false;
35 this->component_count_ = 1u;
36 this->current_position_ = 0;
40 void
41 TAO_DynValueBox_i::check_typecode (CORBA::TypeCode_ptr tc)
43 CORBA::TCKind kind = TAO_DynAnyFactory::unalias (tc);
44 if (kind == CORBA::tk_value_box)
46 return;
49 throw DynamicAny::DynAnyFactory::InconsistentTypeCode ();
52 void
53 TAO_DynValueBox_i::init (CORBA::TypeCode_ptr tc)
55 this->check_typecode (tc);
56 this->type_ = CORBA::TypeCode::_duplicate (tc);
58 // member_type() does not work with aliased type codes.
59 CORBA::TypeCode_var unaliased_tc =
60 TAO_DynAnyFactory::strip_alias (this->type_.in ());
61 CORBA::TypeCode_var
62 mtype (unaliased_tc->content_type ());
63 this->boxed_ =
64 TAO::MakeDynAnyUtils::make_dyn_any_t<CORBA::TypeCode_ptr>
65 (mtype.in (), mtype.in (), this->allow_truncation_);
67 this->init_common ();
68 this->set_to_null ();
72 void
73 TAO_DynValueBox_i::init (const CORBA::Any & any)
75 CORBA::TypeCode_ptr tc = any._tao_get_typecode ();
76 this->check_typecode (tc);
77 this->type_ = CORBA::TypeCode::_duplicate (tc);
78 this->set_from_any (any);
81 TAO_DynValueBox_i *
82 TAO_DynValueBox_i::_narrow (CORBA::Object_ptr _tao_objref)
84 return (CORBA::is_nil (_tao_objref)) ?
85 0 :
86 dynamic_cast<TAO_DynValueBox_i *> (_tao_objref);
89 CORBA::Any *
90 TAO_DynValueBox_i::get_boxed_value (void)
92 if (this->destroyed_)
94 throw ::CORBA::OBJECT_NOT_EXIST ();
97 if (CORBA::is_nil (this->boxed_.in ()))
99 throw DynamicAny::DynAny::InvalidValue ();
102 return this->boxed_->to_any ();
105 void
106 TAO_DynValueBox_i::set_boxed_value (const CORBA::Any & boxed)
108 if (this->destroyed_)
110 throw ::CORBA::OBJECT_NOT_EXIST ();
113 // content_type() does not work with aliased type codes.
114 CORBA::TypeCode_var unaliased_tc =
115 TAO_DynAnyFactory::strip_alias (this->type_.in ());
116 CORBA::TypeCode_var my_tc = unaliased_tc->content_type ();
117 CORBA::TypeCode_var value_tc = boxed._tao_get_typecode ();
118 if (!my_tc->equivalent (value_tc.in ()))
120 throw DynamicAny::DynAny::TypeMismatch ();
123 this->boxed_ =
124 TAO::MakeDynAnyUtils::make_dyn_any_t<const CORBA::Any&>
125 (boxed._tao_get_typecode (), boxed, this->allow_truncation_);
126 this->set_to_value ();
129 DynamicAny::DynAny_ptr
130 TAO_DynValueBox_i::get_boxed_value_as_dyn_any (void)
132 if (this->destroyed_)
134 throw ::CORBA::OBJECT_NOT_EXIST ();
137 if (CORBA::is_nil (this->boxed_.in ()))
139 throw DynamicAny::DynAny::InvalidValue ();
142 // A deep copy is made only by copy() (CORBA 2.4.2 section 9.2.3.6).
143 // Set the flag so the caller can't destroy.
144 this->set_flag (this->boxed_.in (), 0);
146 return DynamicAny::DynAny::_duplicate (this->boxed_.in ());
149 void
150 TAO_DynValueBox_i::set_boxed_value_as_dyn_any (DynamicAny::DynAny_ptr boxed )
152 if (this->destroyed_)
154 throw ::CORBA::OBJECT_NOT_EXIST ();
157 // content_type() does not work with aliased type codes.
158 CORBA::TypeCode_var unaliased_tc =
159 TAO_DynAnyFactory::strip_alias (this->type_.in ());
160 CORBA::TypeCode_var my_tc = unaliased_tc->content_type ();
161 CORBA::TypeCode_var value_tc = boxed->type ();
162 if (!my_tc->equivalent (value_tc.in ()))
164 throw DynamicAny::DynAny::TypeMismatch ();
166 this->boxed_ = boxed->copy ();
167 this->set_to_value ();
170 void
171 TAO_DynValueBox_i::from_any (const CORBA::Any & any)
173 if (this->destroyed_)
175 throw ::CORBA::OBJECT_NOT_EXIST ();
178 CORBA::TypeCode_var tc = any.type ();
179 if (!this->type_->equivalent (tc.in ()))
181 throw DynamicAny::DynAny::TypeMismatch ();
184 this->set_from_any (any);
187 CORBA::Boolean
188 TAO_DynValueBox_i::equal (DynamicAny::DynAny_ptr rhs)
190 if (this->destroyed_)
192 throw ::CORBA::OBJECT_NOT_EXIST ();
195 CORBA::TypeCode_var tc = rhs->type ();
196 if (!tc->equivalent (this->type_.in ()))
198 return false;
201 DynamicAny::DynValueBox_ptr rhs_v=
202 dynamic_cast<DynamicAny::DynValueBox_ptr> (rhs);
203 if (!rhs_v || this->is_null () != rhs_v->is_null ())
205 return false;
208 if (!this->is_null ())
210 DynamicAny::DynAny_var
211 tmp (rhs->current_component ());
212 return tmp->equal (this->boxed_.in ());
215 return true;
218 void
219 TAO_DynValueBox_i::destroy (void)
221 if (this->destroyed_)
223 throw ::CORBA::OBJECT_NOT_EXIST ();
226 if (!this->ref_to_component_ || this->container_is_destroying_)
228 // Do a deep destroy.
229 if (!CORBA::is_nil (this->boxed_.in ()))
231 this->set_flag (this->boxed_.in (), 1);
232 this->boxed_.in ()->destroy ();
235 this->destroyed_ = 1;
239 DynamicAny::DynAny_ptr
240 TAO_DynValueBox_i::current_component (void)
242 if (this->destroyed_)
244 throw ::CORBA::OBJECT_NOT_EXIST ();
247 // Is this an NULL ValueBoxtype?
248 if (this->is_null_)
250 return DynamicAny::DynAny::_nil ();
253 this->set_flag (this->boxed_.in (), 0);
254 return DynamicAny::DynAny::_duplicate (this->boxed_.in ());
257 // This code is common to from_any() and the init() overload that takes
258 // an Any argument.
259 void
260 TAO_DynValueBox_i::set_from_any (const CORBA::Any & any)
262 // Get the CDR stream of the Any, if there isn't one, make one.
263 TAO_OutputCDR out;
264 TAO_InputCDR in (static_cast<ACE_Message_Block *> (0));
265 TAO::Any_Impl *impl = any.impl ();
266 if (impl->encoded ())
268 TAO::Unknown_IDL_Type *unk =
269 dynamic_cast<TAO::Unknown_IDL_Type *> (impl);
270 if (!unk)
271 throw CORBA::INTERNAL ();
273 in = unk->_tao_get_cdr ();
275 else
277 impl->marshal_value (out);
278 TAO_InputCDR tmp_in (out);
279 in = tmp_in;
282 while (true)
284 TAO_InputCDR indrected_strm ((size_t) 0);
285 CORBA::Boolean is_indirected= false;
286 CORBA::Boolean is_null_object= false;
288 // Read in the ValueBox header (to skip over it) and check
289 // for the null type.
290 if (!CORBA::ValueBase::_tao_validate_box_type (
292 indrected_strm,
293 this->type_.in ()->id (),
294 is_null_object,
295 is_indirected) ||
296 is_null_object)
298 this->set_to_null ();
299 return;
302 if (!is_indirected)
304 break;
307 in = indrected_strm;
310 // content_type() does not work with aliased type codes.
311 CORBA::TypeCode_var unaliased_tc =
312 TAO_DynAnyFactory::strip_alias (this->type_.in ());
313 CORBA::TypeCode_var boxed_tc (unaliased_tc->content_type ());
314 TAO::Unknown_IDL_Type * unk = 0;
315 ACE_NEW_THROW_EX (unk,
316 TAO::Unknown_IDL_Type (boxed_tc.in (), in),
317 CORBA::NO_MEMORY ());
318 CORBA::Any boxed_any;
319 boxed_any.replace (unk);
320 this->boxed_ =
321 TAO::MakeDynAnyUtils::make_dyn_any_t<const CORBA::Any&>
322 (boxed_any._tao_get_typecode (), boxed_any, this->allow_truncation_);
323 this->init_common ();
326 CORBA::Any_ptr
327 TAO_DynValueBox_i::to_any (void)
329 if (this->destroyed_)
331 throw ::CORBA::OBJECT_NOT_EXIST ();
334 TAO_OutputCDR out_cdr;
336 // Is this an NULL Valuetype?
337 if (!CORBA::ValueBase::_tao_write_special_value (
338 out_cdr, reinterpret_cast <CORBA::ValueBase *> (
339 this->is_null_ ? 0 : this)))
341 // Build <value-tag>, which states if chunking is used
342 // and if type information ((list of) repository id(s))
343 // is provided.
344 CORBA::Long valuetag =
345 TAO_OBV_GIOP_Flags::Value_tag_base |
346 TAO_OBV_GIOP_Flags::Type_info_single;
348 ACE_CString type_id (this->type_->id ());
350 // Write <value-tag> & Marshal type information.
351 if (!out_cdr.write_long (valuetag) ||
352 !CORBA::ValueBase::_tao_write_repository_id (out_cdr, type_id))
354 throw CORBA::INTERNAL ();
357 // Now write the boxed value itself
359 TAO_InputCDR boxed_in_cdr (static_cast<ACE_Message_Block *> (0));
360 CORBA::Any_var boxed_any (this->boxed_->to_any ());
361 TAO::Any_Impl * boxed_impl = boxed_any->impl ();
362 if (boxed_impl->encoded ())
364 TAO::Unknown_IDL_Type * boxed_unk=
365 dynamic_cast<TAO::Unknown_IDL_Type *> (boxed_impl);
366 if (!boxed_unk)
368 throw CORBA::INTERNAL ();
370 boxed_in_cdr = boxed_unk->_tao_get_cdr ();
372 else
374 TAO_OutputCDR boxed_out_cdr;
375 boxed_impl->marshal_value (boxed_out_cdr);
376 TAO_InputCDR tmp (boxed_out_cdr);
377 boxed_in_cdr = tmp;
380 CORBA::TypeCode_var boxed_tc = this->boxed_->type ();
381 (void) TAO_Marshal_Object::perform_append (boxed_tc.in (),
382 &boxed_in_cdr,
383 &out_cdr);
386 // Convert the out_cdr into a new any.
387 TAO_InputCDR in_cdr (out_cdr);
388 TAO::Unknown_IDL_Type * unk = 0;
389 ACE_NEW_THROW_EX (unk,
390 TAO::Unknown_IDL_Type (this->type_.in (), in_cdr),
391 CORBA::NO_MEMORY ());
392 CORBA::Any_ptr retval = 0;
393 ACE_NEW_THROW_EX (retval, CORBA::Any, CORBA::NO_MEMORY ());
394 retval->replace (unk);
395 return retval;
398 TAO_END_VERSIONED_NAMESPACE_DECL