VisiBroker for C++ Developer’s Guide : Using dynamically managed types

Using dynamically managed types
This section describes the DynAny feature of VisiBroker, which allows you to construct and interpret data types at runtime.
DynAny interface overview
The DynAny interface provides a way to dynamically create basic and constructed data types at runtime. It also allows information to be interpreted and extracted from an Any object, even if the type it contains was not known to the server at compile-time. Using the DynAny interface, you can build powerful client and server applications that create and interpret data types at runtime.
DynAny examples
Example client and server applications that illustrate the use of DynAny are included as part of the VisiBroker distribution. The examples are located in the following directory:
<install_dir>\examples\vbe\dynany\
These example programs are used to illustrate DynAny concepts throughout this section.
DynAny types
A DynAny object has an associated value that may either be a basic data type (such as boolean, int, or float) or a constructed data type. The DynAny interface, its methods and classes are also documented in the VisiBroker for C++ API Reference. “Programmer tools for C++” provides methods for determining the type of the contained data as well as for setting and extracting the value of primitive data types.
Constructed data types are represented by the following interfaces, which are all derived from DynAny. Each of these interfaces provides its own set of methods that are appropriate for setting and extracting the values it contains.
DynAny usage restrictions
A DynAny object may only be used locally by the process which created it. Any attempt to use a DynAny object as a parameter on an operation request for a bound object or to externalize it using the ORB::object_to_string method will cause a MARSHAL exception to be raised.
Furthermore, any attempt to use a DynAny object as a parameter on DII request will cause a NO_IMPLEMENT exception to be raised.
This version does not support the long double and fixed types as specified in CORBA 3.0.
Creating a DynAny
A DynAny object is created by invoking an operation on a DynAnyFactory object. First obtain a reference to the DynAnyFactory object, and then use that object to create the new DynAny object.
CORBA::Object_var obj = orb->resolve_initial_references("DynAnyFactory");
DynamicAny::DynAnyFactory_var factory = DynamicAny::DynAnyFactory::_narrow(obj);
// Create Dynamic struct
DynamicAny::DynAny_var dynany = factory->create_dyn_any_from_type_code(
Printer::_tc_StructType);
DynamicAny::DynStruct_var info = DynamicAny::DynStruct::_narrow(dynany);
info->set_members(seq);
CORBA::Any_var any = info->to_any();
Initializing and accessing the value in a DynAny
The DynAny::insert_<type> methods allow you to initialize a DynAny object with a variety of basic data types, where <type> is boolean, octet, char, and so on. Any attempt to insert a type that does not match the TypeCode defined for the DynAny will cause an TypeMismatch exception to be raised.
The DynAny::get_<type> methods in C++ or the DynAny.get_<type> methods in Java allow you to access the value contained in a DynAny object, where <type> is boolean, octet, char, and so on. Any attempt to access a value from a DynAny component which does not match the TypeCode defined for the DynAny will cause a TypeMismatch exception to be raised.
The DynAny interface also provides methods for copying, assigning, and converting to or from an Any object. The sample programs, described in “DynAny example client application” and “DynAny example server application”, provide examples of how to use some of these methods.
Constructed data types
The following types are derived from the DynAny interface and are used to represent constructed data types.
Traversing the components in a constructed data type
Several of the interfaces that are derived from DynAny actually contain multiple components. The DynAny interface provides methods that allow you to iterate through these components. The DynAny-derived objects that contain multiple components maintain a pointer to the current component.
Returns a DynAny object, which may be narrowed to the appropriate type, based on the component's TypeCode.
Sets the current component pointer to the component with the specified, zero-based index. Returns false if there is no component at the specified index. Sets the current component pointer to -1 (no component) if specified with a negative index.
DynEnum
The DynEnum interface represents a single enumeration constant. Methods are provided for setting and obtaining the value as a string or as an integral value.
DynStruct
The DynStruct interface represents a dynamically constructed struct type. The members of the structure can be retrieved or set using a sequence of NameValuePair objects. Each NameValuePair object contains the member's name and an Any containing the member's Type and value.
You may use the rewind, next, current_component, and seek methods to traverse the members in the structure. Methods are provided for setting and obtaining the structure's members.
DynUnion
The DynUnion interface represents a union and contains two components. The first component represents the discriminator and the second represents the member value.
You may use the rewind, next, current_component, and seek methods to traverse the components. Methods are provided for setting and obtaining the union's discriminator and member value.
DynSequence and DynArray
A DynSequence or DynArray represents a sequence of basic or constructed data types without the need of generating a separate DynAny object for each component in the sequence or array. The number of components in a DynSequence may be changed, while the number of components in a DynArray is fixed.
You can use the rewind, next, current_component, and seek methods to traverse the members in a DynArray or DynSequence.
DynAny example IDL
The following code sample shows the IDL used in the example client and server applications. The StructType structure contains two basic data types and an enumeration value. The PrinterManager interface is used to display the contents of an Any without any static information about the data type it contains.
// Printer.idl
module Printer {
enum EnumType {first, second, third, fourth};
struct StructType {
string str;
EnumType e;
float fl;
};
interface PrinterManager {
void printAny(in any info);
oneway void shutdown();
};
};
DynAny example client application
The following code sample shows a client application that can be found in the following VisiBroker distribution directory:
<install_dir>\examples\vbe\dynany\
The client application uses the DynStruct interface to dynamically create a StructType structure.
The DynStruct interface uses a sequence of NameValuePair objects to represent the structure members and their corresponding values. Each name-value pair consists of a string containing the structure member's name and an Any object containing the structure member's value.
After initializing the VisiBroker ORB in the usual manner and binding to a PrintManager object, the client performs the following steps:
1
Creates an empty DynStruct with the appropriate type.
2
Creates a sequence of NameValuePair objects that will contain the structure members.
3
Creates and initializes Any objects for each of the structure member's values.
4
Initializes each NameValuePair with the appropriate member name and value.
5
Initializes the DynStruct object with the NameValuePair sequence.
6
Invokes the PrinterManager::printAny method, passing the DynStruct converted to a regular Any.
Note
You must use the DynAny::to_any method to convert a DynAny object, or one of its derived types, to an Any before passing it as a parameter on an operation request.
The following code sample is an example of a client application that uses DynStruct:
// Client.C
#include "Printer_c.hh"
#include "dynany.h"
int main(int argc, char* const* argv) {
try {
// Initialize the ORB.
CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);
DynamicAny::DynAnyFactory_var factory =
DynamicAny::DynAnyFactory::_narrow(
orb->resolve_initial_references("DynAnyFactory"));
// Get the manager Id
PortableServer::ObjectId_var managerId =
PortableServer::string_to_ObjectId("PrinterManager");
// Locate an account manager. Give the full POA name and the servant ID.
Printer::PrinterManager_ptr manager =
Printer::PrinterManager::_bind("/serverPoa", managerId);
DynamicAny::NameValuePairSeq seq(3);
seq.length(3);
CORBA::Any strAny,enumAny,floatAny;
strAny <<= "String";
enumAny <<= Printer::second;
floatAny <<= (CORBA::Float)864.50;
CORBA::NameValuePair nvpairs[3];
nvpairs[0].id = CORBA::string_dup("str");
nvpairs[0].value = strAny;
nvpairs[1].id = CORBA::string_dup("e");
nvpairs[1].value = enumAny;
nvpairs[2].id = CORBA::string_dup("fl");
nvpairs[2].value = floatAny;
seq[0] = nvpairs[0];
seq[1] = nvpairs[1];
seq[2] = nvpairs[2];
// Create Dynamic struct
DynamicAny::DynStruct_var info =
DynamicAny::DynStruct::_narrow(
factory->create_dyn_any_from_type_code(
Printer::_tc_StructType));
info->set_members(seq);
manager->printAny(*(info->to_any()));
manager->shutdown();
}
catch(const CORBA::Exception& e) {
cerr << "Caught " << e << "Exception" << endl;
}
}
DynAny example server application
The following code sample shows a server application that can be found in the following VisiBroker distribution directory:
<install_dir>\examples\vbe\dynany\
The server application performs the following steps.
1
2
3
Creates a PrintManager object.
4
Exports the PrintManager object.
5
...
int main(int argc, char* const* argv) {
try {
// Initialize the ORB.
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
int Verbose = 0;
// get a reference to the root POA
PortableServer::POA_var rootPOA =
PortableServer::POA::_narrow(
orb->resolve_initial_references("RootPOA"));
CORBA::PolicyList policies;
policies.length(1);
policies[(CORBA::ULong)0] = rootPOA->create_lifespan_policy(
PortableServer::PERSISTENT);
// Create serverPOA with the right policies
PortableServer::POA_var serverPOA = rootPOA->create_POA( "serverPoa",
rootPOA->the_POAManager(),
policies );
// Resolve Dynamic Any Factory
DynamicAny::DynAnyFactory_var factory =
orb->resolve_initial_references("DynAnyFactory");
PortableServer::ObjectId_var managerId =
PortableServer::string_to_ObjectId("PrinterManager");
// Create the printer manager object.
PrinterManagerImpl manager( orb, factory, serverPOA, managerId);
// Export the newly create object.
serverPOA->activate_object_with_id(managerId,&manager);
// Activate the POA Manager
rootPOA->the_POAManager()->activate();
cout << serverPOA->servant_to_reference(&manager)
<< " is ready" << endl;
// Wait for incoming requests
orb->run();
}
catch(const CORBA::Exception& e) {
cerr << e << endl;
}
}
The following code sample shows how the PrinterManager implementation follows these steps in using a DynAny to process the Any object, without any compile-time knowledge of the type the Any contains.
1
Creates a DynAny object, initializing it with the received Any.
2
Performs a switch on the DynAny object's type.
3
If the DynAny contains a basic data type, simply prints out the value.
4
If the DynAny contains an Any type, creates a DynAny for it, determines its contents, and then prints out the value.
5
If the DynAny contains an enum, creates a DynEnum for it and then prints out the string value.
6
If the DynAny contains a union, creates a DynUnion for it and then prints out the union's discriminator and the member.
7
If the DynAny contains a struct, array, or sequence, traverses through the contained components and prints out each value.
// PrinterManager Implementation
class PrinterManagerImpl : public POA_Printer::PrinterManager
{
CORBA::ORB_var _orb;
DynamicAny::DynAnyFactory_var _factory;
PortableServer::POA_var _poa;
PortableServer::ObjectId_var _oid;

public:
PrinterManagerImpl(CORBA::ORB_ptr orb,
DynamicAny::DynAnyFactory_ptr DynAnyFactory,
PortableServer::POA_ptr poa,
PortableServer::ObjectId_ptr oid
) : _orb(orb), _factory(DynAnyFactory),
_poa(poa), _oid(oid) {}

void printAny(const CORBA::Any& info) {
try {
// Create a DynAny object
DynamicAny::DynAny_var dynAny = _factory->create_dyn_any(info);
display(dynAny);
}
catch (CORBA::Exception& e) {
cout << "Unable to create Dynamic Any from factory" << endl;
}
}
void shutdown() {
try {
_poa->deactivate_object(_oid);
cout << "Server shutting down..." << endl;
_orb->shutdown(0UL);
}
catch (const CORBA::Exception& e) {
cout << e << endl;
}
}

void display(DynamicAny::DynAny_var value) {
switch(value->type()->kind()) {
case CORBA::tk_null:
case CORBA::tk_void: {
break;
}
case CORBA::tk_short: {
cout << value->get_short() << endl;
break;
}
case CORBA::tk_ushort: {
cout << value->get_ushort() << endl;
break;
}
case CORBA::tk_long: {
cout << value->get_long() << endl;
break;
}
case CORBA::tk_ulong: {
cout << value->get_ulong() << endl;
break;
}
case CORBA::tk_float: {
cout << value->get_float() << endl;
break;
}
case CORBA::tk_double: {
cout << value->get_double() << endl;
break;
}
case CORBA::tk_boolean: {
cout << value->get_boolean() << endl;
break;
}
case CORBA::tk_char: {
cout << value->get_char() << endl;
break;
}
case CORBA::tk_octet: {
cout << value->get_octet() << endl;
break;
}
case CORBA::tk_string: {
cout << value->get_string() << endl;
break;
}
case CORBA::tk_any: {
DynamicAny::DynAny_var dynAny = _factory->create_dyn_any(*(
value->get_any()));
display(dynAny);
break;
}
case CORBA::tk_TypeCode: {
cout << value->get_typecode() << endl;
break;
}
case CORBA::tk_objref: {
cout << value->get_reference() << endl;
break;
}
case CORBA::tk_enum: {
DynamicAny::DynEnum_var dynEnum = DynamicAny::DynEnum::_narrow(value);
cout << dynEnum->get_as_string() << endl;
break;
}
case CORBA::tk_union: {
DynamicAny::DynUnion_var dynUnion = DynamicAny::DynUnion::_narrow(value);
display(dynUnion->get_discriminator());
display(dynUnion->member());
break;
}
case CORBA::tk_struct:
case CORBA::tk_array:
case CORBA::tk_sequence: {
value->rewind();
CORBA::Boolean next = 1UL;
while(next) {
DynamicAny::DynAny_var d = value->current_component();
display(d);
next = value->next();
}
break;
}
case CORBA::tk_longlong: {
cout << value->get_longlong() << endl;
break;
}
case CORBA::tk_ulonglong: {
cout << value->get_ulonglong() << endl;
break;
}
case CORBA::tk_wstring: {
cout << value->get_wstring() << endl;
break;
}
case CORBA::tk_wchar: {
cout << value->get_wchar() << endl;
break;
}
default:
cout << "Invalid Type" << endl;
}
}
};