OpenDDS  Snapshot(2022/12/09-19:23)
XTypes/Utils.cpp
Go to the documentation of this file.
1 /*
2  * Distributed under the OpenDDS License.
3  * See: http://www.opendds.org/license.html
4  */
5 
6 #include <DCPS/DdsDcps_pch.h>
7 
8 #ifndef OPENDDS_SAFETY_PROFILE
9 # include "Utils.h"
10 
11 # include "DynamicDataImpl.h"
12 
13 # include <dds/DCPS/debug.h>
14 
15 # include <algorithm>
16 
18 namespace OpenDDS {
19 namespace XTypes {
20 
21 DDS::ReturnCode_t extensibility(DDS::DynamicType_ptr type, DCPS::Extensibility& ext)
22 {
23  DDS::DynamicType_var base_type = get_base_type(type);
24  if (!base_type) {
26  }
27  switch (base_type->get_kind()) {
28  case TK_STRUCTURE:
29  case TK_UNION:
30  {
31  DDS::TypeDescriptor_var td;
32  const DDS::ReturnCode_t rc = type->get_descriptor(td);
33  if (rc != DDS::RETCODE_OK) {
34  return rc;
35  }
36  ext = dds_to_opendds_ext(td->extensibility_kind());
37  }
38  break;
39  default:
40  ext = DCPS::FINAL;
41  }
42  return DDS::RETCODE_OK;
43 }
44 
46 {
47  DDS::ReturnCode_t rc = extensibility(type, ext);
48  if (rc != DDS::RETCODE_OK) {
49  return rc;
50  }
51 
52  DDS::DynamicType_var base_type = get_base_type(type);
53  const TypeKind tk = base_type->get_kind();
54  if (tk != TK_STRUCTURE && tk != TK_UNION) {
55  return DDS::RETCODE_OK;
56  }
57 
58  DDS::DynamicTypeMembersById_var members;
59  rc = base_type->get_all_members(members);
60  if (rc != DDS::RETCODE_OK) {
61  return rc;
62  }
63 
64  DynamicTypeMembersByIdImpl* const members_impl =
65  dynamic_cast<DynamicTypeMembersByIdImpl*>(members.in());
66  if (!members_impl) {
68  }
69 
70  for (DynamicTypeMembersByIdImpl::const_iterator it = members_impl->begin();
71  it != members_impl->end(); ++it) {
72  DDS::MemberDescriptor_var md;
73  rc = it->second->get_descriptor(md);
74  if (rc != DDS::RETCODE_OK) {
75  return rc;
76  }
77 
78  DDS::DynamicType_ptr member_type = md->type();
79  if (!member_type) {
81  }
82  DCPS::Extensibility member_ext;
83  DDS::ReturnCode_t rc = max_extensibility(member_type, member_ext);
84  if (rc != DDS::RETCODE_OK) {
85  return rc;
86  }
87  ext = std::max(member_ext, ext);
88  }
89 
90  return DDS::RETCODE_OK;
91 }
92 
94 {
95  switch (ext) {
96  case DDS::FINAL:
97  return DCPS::FINAL;
98  case DDS::APPENDABLE:
99  return DCPS::APPENDABLE;
100  case DDS::MUTABLE:
101  return DCPS::MUTABLE;
102  }
103  OPENDDS_ASSERT(false);
104  return DCPS::FINAL;
105 }
106 
108  DDS::DynamicType_ptr type, DDS::DynamicTypeMember_var& member)
109 {
110  member = 0;
111  if (ids.empty()) {
113  }
114 
115  DDS::DynamicType_var base_type = get_base_type(type);
116  if (!base_type) {
118  }
119 
120  MemberIdVec::iterator it = ids.begin();
121  DDS::DynamicType_var current_type = DDS::DynamicType::_duplicate(type);
122  DDS::DynamicTypeMember_var current_member;
123  while (true) {
124  DDS::ReturnCode_t rc = current_type->get_member(current_member, *it);
125  if (rc != DDS::RETCODE_OK) {
126  return rc;
127  }
128 
129  if (++it == ids.end()) {
130  break;
131  }
132 
133  DDS::MemberDescriptor_var md;
134  rc = current_member->get_descriptor(md);
135  if (rc != DDS::RETCODE_OK) {
136  return rc;
137  }
138  current_type = get_base_type(md->type());
139  if (!base_type) {
141  }
142  }
143  member = current_member;
144 
145  return DDS::RETCODE_OK;
146 }
147 
149  DDS::DynamicData_ptr data, DDS::DynamicData_var& container, DDS::MemberId& member_id)
150 {
151  container = 0;
152  if (ids.empty()) {
154  }
155 
156  MemberIdVec::iterator it = ids.begin();
157  DDS::DynamicData_var current_data = DDS::DynamicData::_duplicate(data);
158  while (true) {
159  const DDS::MemberId current_id = *it;
160  if (++it == ids.end()) {
161  member_id = current_id;
162  break;
163  }
164 
165  DDS::ReturnCode_t rc = current_data->get_complex_value(current_data, current_id);
166  if (rc != DDS::RETCODE_OK) {
167  return rc;
168  }
169  }
170  container = current_data._retn();
171 
172  return DDS::RETCODE_OK;
173 }
174 
175 namespace {
176  DDS::ReturnCode_t get_keys_i(DDS::DynamicType_ptr type, MemberPathVec& paths,
177  const MemberPath& base_path);
178 
179  DDS::ReturnCode_t get_keys_i_struct(DynamicTypeMembersByIdImpl* members, MemberPathVec& paths,
180  const MemberPath& base_path, bool implied_all_check = false)
181  {
182  bool implied_all = false;
183  if (!implied_all_check && base_path.level() > 0) {
184  // If there are no explicit keys, then they are implied to all be keys.
185  // TODO: Except when @key(FALSE)
186  MemberPathVec explicit_key;
187  const DDS::ReturnCode_t rc = get_keys_i_struct(members, explicit_key, base_path, true);
188  if (rc != DDS::RETCODE_OK) {
189  return rc;
190  }
191  implied_all = explicit_key.empty();
192  }
193 
195  it != members->end(); ++it) {
196  DDS::MemberDescriptor_var md;
197  DDS::ReturnCode_t rc = it->second->get_descriptor(md);
198  if (rc != DDS::RETCODE_OK) {
199  return rc;
200  }
201  if (implied_all || md->is_key()) {
202  const DDS::MemberId id = md->id();
203  if (implied_all_check) {
204  paths.push_back(MemberPath(base_path, id));
205  break; // Just need one explict key to know we can't imply all are keys
206  }
207 
208  rc = get_keys_i(md->type(), paths, MemberPath(base_path, id));
209  if (rc != DDS::RETCODE_OK) {
210  return rc;
211  }
212  }
213  }
214 
215  return DDS::RETCODE_OK;
216  }
217 
218  DDS::ReturnCode_t get_keys_i(DDS::DynamicType_ptr type, MemberPathVec& paths,
219  const MemberPath& base_path)
220  {
221  DDS::DynamicType_var base_type = get_base_type(type);
222  if (!base_type) {
224  }
225  const TypeKind kind = base_type->get_kind();
226  switch (kind) {
227  case TK_STRUCTURE:
228  {
229  DDS::DynamicTypeMembersById_var members;
230  DDS::ReturnCode_t rc = type->get_all_members(members);
231  if (rc != DDS::RETCODE_OK) {
232  return rc;
233  }
234 
235  DynamicTypeMembersByIdImpl* const members_impl =
236  dynamic_cast<DynamicTypeMembersByIdImpl*>(members.in());
237  if (!members_impl) {
239  }
240 
241  return get_keys_i_struct(members_impl, paths, base_path);
242  }
243  case TK_UNION:
244  {
245  DDS::DynamicTypeMember_var disc;
246  const MemberId id = DISCRIMINATOR_ID;
247  const MemberPath this_path(base_path, id);
248  if (base_path.level() == 0) {
249  DDS::ReturnCode_t rc = type->get_member(disc, id);
250  if (rc != DDS::RETCODE_OK) {
251  return rc;
252  }
253  DDS::MemberDescriptor_var md;
254  rc = disc->get_descriptor(md);
255  if (rc != DDS::RETCODE_OK) {
256  return rc;
257  }
258  if (md->is_key()) {
259  paths.push_back(this_path);
260  }
261  } else {
262  // If we're here then the union field has been marked so the
263  // disciminator is an implied key even if it doesn't have @key.
264  // TODO: Except when @key(FALSE)
265  paths.push_back(this_path);
266  }
267  }
268  break;
269  default:
270  if (base_path.level() == 0) {
272  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: get_keys_i: "
273  "get_keys was passed an invalid topic type: %C\n",
274  typekind_to_string(kind)));
275  }
277  }
278  paths.push_back(base_path);
279  break;
280  }
281 
282  return DDS::RETCODE_OK;
283  }
284 }
285 
286 DDS::ReturnCode_t get_keys(DDS::DynamicType_ptr type, MemberPathVec& paths)
287 {
288  return get_keys_i(type, paths, MemberPath());
289 }
290 
291 DDS::ReturnCode_t key_count(DDS::DynamicType_ptr type, size_t& count)
292 {
293  MemberPathVec paths;
294  const DDS::ReturnCode_t rc = get_keys(type, paths);
295  if (rc == DDS::RETCODE_OK) {
296  count = paths.size();
297  }
298  return rc;
299 }
300 
301 } // namespace XTypes
302 } // namespace OpenDDS
304 
305 #endif // OPENDDS_SAFETY_PROFILE
OpenDDS_Dcps_Export LogLevel log_level
DDS::ReturnCode_t max_extensibility(DDS::DynamicType_ptr type, DCPS::Extensibility &ext)
#define ACE_ERROR(X)
DDS::ReturnCode_t get_keys(DDS::DynamicType_ptr type, MemberPathVec &paths)
const ACE_CDR::ULong DISCRIMINATOR_ID
Implementation specific sentinel for a union discriminator used in DynamicData.
Definition: TypeObject.h:832
const ReturnCode_t RETCODE_ILLEGAL_OPERATION
DDS::ReturnCode_t extensibility(DDS::DynamicType_ptr type, DCPS::Extensibility &ext)
ACE_CDR::ULong MemberId
Definition: TypeObject.h:829
DDS::DynamicType_var get_base_type(DDS::DynamicType_ptr type)
const ReturnCode_t RETCODE_OK
DDS::ReturnCode_t get_member_from_data(DDS::DynamicData_ptr data, DDS::DynamicData_var &container, DDS::MemberId &member_id)
LM_NOTICE
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
DCPS::Extensibility dds_to_opendds_ext(DDS::ExtensibilityKind ext)
DDS::ReturnCode_t key_count(DDS::DynamicType_ptr type, size_t &count)
ExtensibilityKind
const TypeKind TK_UNION
Definition: TypeObject.h:173
ACE_CDR::Octet TypeKind
Definition: TypeObject.h:139
const TypeKind TK_STRUCTURE
Definition: TypeObject.h:172
const char * typekind_to_string(TypeKind tk)
The Internal API and Implementation of OpenDDS.
Definition: AddressCache.h:28
#define OPENDDS_ASSERT(C)
Definition: Definitions.h:66
const ReturnCode_t RETCODE_BAD_PARAMETER
DDS::ReturnCode_t get_member_from_type(DDS::DynamicType_ptr type, DDS::DynamicTypeMember_var &member)