Copyright © TIBCO Software Inc. All Rights Reserved
Copyright © TIBCO Software Inc. All Rights Reserved


Chapter 6 Metadata : Creating Runtime Data

Creating Runtime Data
Each time information has to be sent over the wire, the custom adapter creates MInstance instances for those MModeledClassDescription instances it wants to work with. It adds attributes by iterating through the MModeledClassDescription attributes.
As part of instance creation, custom adapters encapsulate the attributes as instances of MData subclasses.
Metadata Encapsulation Classes
MData and its subclasses encapsulate the data itself.
MInstance encapsulates class data.
MSequence encapsulates sequences to be used as a type.
MUnion encapsulates union data. Unions have a name and have as subelements one or more Union Member attributes. At any given time there is one, but only one, active member.
MInterval encapsulates a time interval.
MAssocList encapsulates association lists.
MChar, MStringData, MReal, MFixed, MBinary, MDate, MDateTime, etc. support the appropriate corresponding types. See AE Schema Types and SDK Classes.
Metadata Attribute Encapsulation Classes
Metadata attribute encapsulation classes are represented differently depending on the API in use:
Because Java provides encapsulated types, the Java SDK metadata interface does not include the type description classes such as MInteger or MBoolean. Instead, adapters use the native Java classes. See AE Schema Types and SDK Classes.
C++ MData Subclasses
In the C++ SDK, there are a number of MData subclasses for types, such as MInteger or MBool.
The C++ SDK chose this rather complex hierarchy because it facilitates introspection. Assume a custom adapter receives an MInstance that consists of chunks of MData. The design of the classes allows the custom adapter to first find out what type of data it is dealing with, for example, MInteger. The adapter can then downcast this MInteger and retrieve information about the exact type, as encapsulated by the MPrimitiveClassDescription data member, for example "i4".
When custom adapters get ready to send data across the wire, they create instances of MInstance for each item defined as a class in the adapter instance. Custom adapters then set values for each instance. MData and its subclasses allow the custom adapter to encapsulate data at a high level. For example, you can use MInteger for all integer primitive types, while at the same time maintaining the information about the specific primitive type that is used.
The Java SDK does not have SDK subclasses such as MInteger or MStringData because these classes are available as part of Java.
C++ Data Encapsulation Classes
When a C++ custom adapter wants to send data or retrieve data, it uses the data encapsulation classes.
1.
2.
3.
4.
The type of the instance value is the class that encapsulates the attribute’s class in the adapter instance. For example, if the attribute had the class “i4”, the code for setting the value would use an MInteger.
5.
The custom adapter sends the MInstance and the SDK serializes and publishes it.
Metadata Example
The adapter first accesses the class registry to retrieve the information about the type of data that it publishes or subscribes to.

 
//retrieve the registry
MClassRegistry* pClassRegistry = m_pMApp->getClassRegistry();
//retrieve class descripton from class registry, downcast because we’re
//working with MModeledClassDescription.
MModeledClassDescription* pMCD = MModeledClassDescription::downCast
                                 (pClassRegistry->getClassDescription());
 
//get the attributes for the class we just retrieved.
MMap<MString, MAttributeDescription*>* pAttributes = pMCD->getAttributes()

 
The adapter then creates the instance using one of the metadata classes. For example:
 
MInstance orderInstance(this,"Order");
The custom adapter provides the first three attribute values for the attributes of the predefined class. Note that the attributes are defined in the adapter instance description object as "i4". The custom adapter can set values of any integer type attribute by defining the value as an MInteger.

 
MInteger iOrderId = 1000;
MInteger iCustomerId = 112;
 
// set the order
orderInstance.set("OrderId", iOrderId);
orderInstance.set("CustomerId", iCustomerId);
orderInstance.set("ShipToAddress", MStringData("3165 Porter Dr"));
//
//The fourth attribute value is a sequence of Orderline instances. The application
//creates them as follows:
//
// create a orderline sequence
MSequence orderLineSequence(this, "sequence[OrderLine]");
 
//create one orderLine instance
MInstance orderLineInstance(this, "OrderLine");
orderLineInstance.set("OrderId", iOrderId);
orderLineInstance.set("ItemId", MInteger(1));
orderLineInstance.set("Quantity", MInteger(345));
//append to sequence
orderLineSequence.append(&orderLineInstance );
 
// create another orderline
orderLineInstance.set("OrderId", iOrderId);
orderLineInstance.set("ItemId", MInteger(1));
orderLineInstance.set("Quantity", MInteger(345));
//append to sequence
orderLineSequence.append(&orderLineInstance );
//
//The application can then set the fourth attribute of the Order instance:
//
orderInstance.set("Orderlines", &orderLineSequence);

 

Copyright © TIBCO Software Inc. All Rights Reserved
Copyright © TIBCO Software Inc. All Rights Reserved