Skip to main content

Module java

Module java 

Source
Expand description

The Java CST as the other end of a rule. Spec §3.2.

The counterpart of crate::adapter::c, which does the same for C, and of crate::adapter::cst, which does it for Rust. Reading two of them side by side is the point: where they differ, the difference is the language’s, and it is written down here rather than spread through a renderer.

Values are resolved from the model, never from the overlay — the same rule the other two materialisers follow and for the same reason (spec §2.3).

§The four things Java forces that C does not

  1. No unsigned integer. Every Java integer is signed, so the width of the IDL type cannot decide the Java type. What decides it is what the field has to hold: unsigned short takes an int because 65535 is not a short, and unsigned long takes a long because 4294967295 is not an int. Only unsigned long long has no type wide enough, and it takes a long holding the bit pattern. The table below says which of the two every unsigned type is.
  2. Arrays instead of declared collection types. C has to declare a named struct for sequence<long>; Java writes int[]. So there is no structural-name machinery here and no forward declaration — a Java class may name a class declared after it — but ordered_types is still what the walk uses, so two runs over one model produce the same file.
  3. One public top-level type per file. Everything nests inside one outer class; see “Modules” below.
  4. No typedef. An IDL typedef has no Java declaration at all. It is not dropped: the member takes the target’s Java type and the outer class carries a comment naming the alias and what it resolved to.

§The integer mapping

IDLJavawhat the field holds
booleanboolean
charcharone code unit; the wire form is one octet
wcharcharone UTF-16 code unit
int8bytea number, -128..127
octetbytea bit pattern, which the codec writes as the number 0..255
uint8inta number, 0..255
shortshorta number
unsigned shortinta number, 0..65535
longinta number
unsigned longlonga number, 0..4294967295
long longlonga number
unsigned long longlonga bit pattern, not a number
floatfloat
doubledouble
long doubleorg.zerodds.wire.Float128never a double

The unsigned types, stated once more because this is the decision that reaches the wire: uint8 and unsigned short are numbers in an int; unsigned long is a number in a long; unsigned long long is a pattern in a long, and writeU64(-1L) writes ffffffffffffffff, which is 18446744073709551615. octet is the exception, and follows the OMG mapping.

This is not a choice made here alone. runtime/java/.../Writer.java had to make it first, for its own arguments: writeU8(int value) says “a number in [0, 255], not a pattern: the argument is an int because Java’s byte is signed, and 200 arriving as -56 would be a caller who has already lost the value”; writeU32(long value) says the same of 3735928559; writeU64(long pattern) says the opposite, because there is no wider type. The generated code calls those methods, so a field typed against a different rule would either not compile or arrive already wrong.

octet is a byte. CORBA 3.3 part 3 §1.5.2 maps octet to byte, the JacORB column measured in crates/wire-probe/src/corba_java.rs does the same, and DDS-XTypes 1.3 §7.5.1 reuses that mapping for the Plain Language Binding. A signed byte holds 200 as -56; the codec says so at both ends: Writer.writeU8(byte) writes the number the eight bits are and the reader’s (byte) readU8() keeps them, so the wire form is unchanged. uint8 has no OMG mapping and stays a number in an int.

§The shapes

IDLJava
string, wstringjava.lang.String
fixed<P,S>java.math.BigDecimal
sequence<T>, T[N]T[]
T[N][M]T[][]
map<K,V>ZdMap_k_v, a java.util.LinkedHashMap of the boxed types (ZdEntry_k_v[] for a key Java compares by identity)
uniona class with _d and one field per case
enuma class with one instance per enumerator, value() and from_int (CORBA 3.3 part 3 §1.5.9)
bitmaskthe unsigned holder of its bound, beside constants
bitseta class of one field per bitfield
@optional T mthe boxed T, null when absent
@external T mthe boxed T for a primitive, the reference otherwise
typedefnothing; a comment, and the target’s type at each use

§fixed<P,S> is a BigDecimal

§1.5.6 of the OMG mapping says java.math.BigDecimal, and the JacORB column follows it. So does this one. The digits a fixed-point value carries on the wire come from the type (fixed<P,S>), and a BigDecimal keeps its scale, so new BigDecimal("0.00") writes the digits 0.00 has; Writer.writeFixed takes the decimal text, which the codec gets from toPlainString(), and Reader.readFixed hands back text the codec turns into a BigDecimal. What a BigDecimal does not keep is leading zeroes (precision() of 0.00 is 1), so the FixedDigitCount::ValueStringDigits axis, which counts the digits of the text a caller wrote, sees the normalised text.

§The collections

A sequence<T> and an IDL array are both a Java T[], which is what §1.5.7 does and what the JacORB column records (“a Java array — so a sequence is allocated, not lengthened”). A multi-dimensional array is a nested Java array, one [] per dimension.

A map<K,V> is a java.util.Map (XTypes 1.3 §7.5.1.3.5): a generated class extending LinkedHashMap of the boxed key and value types, so that the order the entries were put in is the order they go on the wire in; MapEntryOrder sorts them when asked to. The codec reads and writes the entries in the generated entry class, in order (ZdMap….entries() and ZdMap….of(entries)), and the class carries the operations of Table 47 that Java does not have. A key a java.util.Map would compare by identity (a structure, a sequence) keeps the array of entries.

§@optional is a boxed type and null

One field, not a field beside a boolean. A boolean _has_m and an m are two things that can disagree, and nothing in the type system stops them; null cannot disagree with itself. @optional long m therefore takes java.lang.Long, because a primitive long has no value that means absent — which is the case that decides this, and the reason C needs the parallel flag it has.

§An enumeration is a class of instances

CORBA 3.3 part 3 §1.5.9, which DDS-XTypes 1.3 §7.5.1 reuses: a final class with one public static final instance per enumerator, the int constants _NAME, value() and from_int. A member of the type is an instance of the class and the codec writes value().

The JacORB column records the same shape. from_int refuses a value no enumerator has; the codec never meets that, because it reads a value through the chain of enumerators and applies the position’s try-construct behaviour to one it does not know (Table 18), and assigns the instance of the enumerator it found.

§Modules are nested classes, in one file

Not packages. Two facts decide it. Java requires the public top-level type of a file to be named after the file, so real packages mean many files; and this function returns Vec<java::TypeDecl> with no file boundary in it, so a package-per-module mapping could not be expressed by the signature at all — the package would be lost between here and the renderer, and module a { struct P; } and module b { struct P; } would collide in one scope. That collision is the defect MaterialiseError::NoModule was added for in the Rust column.

The consumer decides it the same way: tools/wireprobe compiles one probe per corpus case, and runtime/java/run-tests.sh invokes javac --release 8 -Xlint:all,-options -Werror over a directory of sources. One generated file with one outer class is one javac argument; it also keeps -Xlint:auxiliaryclass quiet, which a file of several top-level classes would not.

So everything nests inside OUTER, each IDL module becomes a public static final class of that name, and every reference to a generated type is written from OUTER down — ZdTypes.a.P. The qualification is not decoration: JLS §6.5.2 resolves the first segment of a qualified name to a variable before a type, so a field named common in a class that also names the type common.util.Point would be a compile error that only some corpora would show.

§Identifiers

Through zerodds_lang_cst::java::escape_keyword, which appends an underscore: the module package becomes the class package_ and the enumeration class becomes class_. crates/wire-probe/src/ target_keywords.rs prefixes one instead — _package, _class — because that is what JacORB was measured to emit over tests/interop-corpus/identifier-target-keywords. Both avoid the keyword and neither reaches the wire; this crate does not depend on zerodds-wire-probe, and the one CST spelling keeps the four generated columns’ identifiers consistent with each other rather than with one ORB. Only a Java keyword moves, so the enumerators template, virtual and friend keep their spelling here as they do there.

§What is refused

any, ValueBase and an object reference have no Java data form here and are named as MaterialiseError::NoLanguageForm rather than left out of the class. A generator that leaves a member out emits a type missing a field and reports success, which is the defect class this whole file is arranged against.

Enums§

JavaMapping
The shape generated Java types take.

Constants§

ARRAY_LIST
What a new unbounded sequence is under JavaMapping::Psm.
MAP_PREFIX
The prefix a generated map class carries.
OUTER
The class every generated declaration nests inside.
SEQUENCES
The runtime class the Psm mapping’s codec calls for the one thing it cannot decide by type: indexing, counting, allocating and filling a sequence that may be an array or a Collection. Overload resolution does it, and the class is org.zerodds.wire.Sequences.

Functions§

accessor
base.getX(): the read of a member under JavaMapping::Psm, and the pseudo l-value that assign turns into base.setX(value).
assign
place = value;, in the form the mapping in force can write.
assignment
A statement the walk built as place = value or as the bare expression place = value, rewritten by assign; anything else is returned as it is.
boolean_getter_name
isX for a boolean member field; see getter_name.
declared_path
Where a declaration sits, as Java has to write it: ZdTypes.a.b.Name.
entry_class_of_map_class
The entry class of the map class class (ZdMap<bound>_<key>_<value>, the bound being absent or _b<digits> or _bx): ZdEntry_<key>_<value>.
getter_name
getX for the member field, which is the escaped Java name.
index
a[i] for an array, and Sequences.at(v, i) for the sequence the codec marked with sequence_view.
java_items
Build the Java declarations a rule application produced.
java_member_type
The Java type of a value in a position that has to hold one, refusing the constructs Java cannot hold.
java_primitive
The Java primitive an IDL primitive becomes.
map_class_name
The class of a map<K,V>: ZdMap<bound>_<key>_<value>.
map_entry_name
The map entry class a map<K,V> needs a name for.
map_key_supported
Whether the key type of a map is one a java.util.Map can be keyed by: a primitive, a string, an enumeration or a bitmask, whose Java objects compare by value, and a structure, a union or a bit set, whose generated class has equals and hashCode over its members (see equals_and_hash_code).
mapping
The mapping in force on this thread.
sequence_slot
The place an element of a sequence is written into: a pseudo l-value that assign turns into Sequences.put(v, i, value).
sequence_view
Sequences.view(v): marks the expression the codec indexes into, so that index can tell a sequence from a nested array.
sequences_alloc
Sequences.alloc(v, n): a new container of the kind v is, with room for n elements.
sequences_count
Sequences.count(v): the length of an array or a Collection.
sequences_first
Sequences.first(v, n): the first n elements, in a container of the kind v is.
setter_name
setX for the member field; see getter_name.
type_tag
The name component an entry class takes from one of its halves.
unsigned_holder
The Java type an unsigned value of bits bits is held in.
with_mapping
Run body with mapping in force, and restore what was before — also when body panics.