Section G.11. Value Type Declarations


G.11. Value Type Declarations

Value types are a new IDL construct introduced when Objects by Value was adopted in the CORBA specification, for Version 2.3. Prior to the adoption of Objects by Value, there were two argument-passing semantics available in IDL. Interface types were passed by reference, and basic data types were passed by value. But there wasn't any way to pass an object by value between remote agents, in the way that Java serialization provides when using Java RMI. The CORBA Objects by Value specification extends IDL to include a new entity, called a value type, that is similar in syntax to an interface or a struct.

Value types are declared using the valuetype IDL keyword:

 valuetype Coord3DVal { ... }; 

Any entity declared as a valuetype is passed by value when used as the argument to an operation. In other words, the servant of the operation receives a copy of the entity, not a remote reference to the entity residing on the caller, as is the normal case for IDL interfaces.

Value types can be declared with a custom modifier, which indicates that it will use custom marshaling code provided by the developer in an implementation class:

 custom valuetype Coord3DValCustom { ... }; 

This modifier alters the nature of the generated "native" code, as described in the next section.

Value types can also inherit other value types , which have semantics similar to interface inheritance: the value type inherits all of the attributes, operations, state members, and initializers of its parent(s). The syntax of value type inheritance is the same as interface inheritance:

 valuetype childVal : parentVal { ... }; 

Value type definitions can contain everything an interface can, as well as state members and initializers. Any members declared as state members are considered part of the state of the value type, which needs to be marshaled and transmitted over the network when this valuetype is used in a remote operation call. Any attributes declared in a valuetype aren't considered part of the state that is passed by valueinstead, they're considered part of the local state of the entity. State members are declared using either a public or private modifier, followed by a type specification and the declaration of the member identifier itself. Public state members are publicly available to the application code; private members are accessible only in the implementation code and during marshal operations. It's the responsibility of the language mapping to determine how this is implemented in a particular language.

An initializer is a declaration of a constructor for this valuetype. Initializer declarations are identical to operation declarations, except that they start with a special factory modifier. An initializer should have arguments that are sufficient for the entity's state to be initialized fully.

For example, suppose we want to declare an object-like version of our Coord3d typedef, in that we want our Coord3d to be able to have operations of its own. But we still want to be able to pass these coordinates by value in remote operations. We can declare a new valuetype:

 valuetype Coord3DVal {     // The state that should be passed by value     private Coord3d coord;     // A local short attribute, not passed in remote operations     attribute short localShort;     // Initializer for this type     factory makeCoord(in long x, in long y, in long z);     // Operations to access state, etc.     long getX(  );     long getY(  );     long getZ(  ); }; 

The Coord3DVal valuetype has a single state member, coord, that holds the coordinate value as a Coord3D (our earlier typedef). This state data is marshaled and passed by value when a Coord3DVal is used as an argument in a remote operation. The coord member is declared as private, so it is not directly accessible to the application code. The Coord3DVal also has a local attribute, localShort, that is not considered part of the state and is not transferred in remote operation calls. We declare a single initializer, makeCoord( ), for our valuetype, which takes the three coordinate values for the Coord3d state member. Finally, our valuetype has some operations that provide access to the individual coordinate values of the Coord3d state member.

G.11.1. Mapping Valuetypes to Java

For the most part, valuetypes are mapped to Java along the same lines as interfaces, but with some key differences. A valuetype is mapped into an abstract Java class of the same name, rather than into a Java interface. Each attribute is mapped to instance variables in the same manner that interface attributes are mapped, using accessors that suit the modifiers on the attribute. State members, however, are mapped directly to instance variables. Public state members are mapped to public instance variables, and private state members become protected instance variables. Regular IDL operations are mapped to methods on the Java class in the same way as interface operations. Initializers, however, are mapped into a separate Java interface, named xxxValueFactory, where xxx is the name of the valuetype. Each initializer declared in the IDL valuetype is mapped to an equivalent method on the xxxValueFactory interface. To complete the mapping of the valuetype, you need to provide concrete implementations of both the mapped abstract class and the xxxValueFactory interface.

Our Coord3dVal valuetype is mapped by idlj to the following Java abstract class:

 public abstract class Coord3DVal implements org.omg.CORBA.portable.StreamableValue {    // The state that should be passed by value   protected int coord[] = null;     private static String[] _truncatable_ids = {     test.Coord3DValHelper.id (  )   };     public String[] _truncatable_ids(  ) {     return _truncatable_ids;   }     // A local short attribute, not passed in remote operations   public abstract short localShort (  );     // A local short attribute, not passed in remote operations   public abstract void localShort (short newLocalShort);     // Operations to access state, etc.   public abstract int getX (  );     public abstract int getY (  );     public abstract int getZ (  );     public void _read (org.omg.CORBA.portable.InputStream istream)   {     this.coord = test.Coord3dHelper.read (istream);   }     public void _write (org.omg.CORBA.portable.OutputStream ostream)   {     test.Coord3dHelper.write (ostream, this.coord);   }     public org.omg.CORBA.TypeCode _type (  )   {     return test.Coord3DValHelper.type (  );   } } 

The generated class inherits from org.omg.CORBA.portable.StreamableValue, which ensures that it is streamable over an I/O stream. The generated _write( ) and _read( ) methods provide the code to marshal and unmarshal this value type when it is passed in a remote CORBA method call.

In addition, a Coord3DValValueFactory interface is generated to hold our single initializer method:

 public interface Coord3DValValueFactory extends   org.omg.CORBA.portable.ValueFactory {   // Initializer for this type   Coord3DVal makeCoord (int x, int y, int z); } 

Once you provide the concrete implementations of these interfaces, an application creates one of these valuetypes by constructing a concrete subclass of the Coord3DValValueFactory interface and calling its makeCoord( ) method to obtain a Coord3DVal. This object can then be passed by value into any CORBA remote method.



Java Enterprise in a Nutshell
Java Enterprise in a Nutshell (In a Nutshell (OReilly))
ISBN: 0596101422
EAN: 2147483647
Year: 2004
Pages: 269

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net