Automatic Maps
Automatic mapping is used when all the fields of the external format should be included in the internal format. This does not preclude explicit mapping of selected fields or types. Automatic mapping complies with the following steps for each field in the external format:
Evaluate if theÂ
in_map
 contains an explicit mapping for the external field. If so, use that explicit mapping.
ÂIf the preceding step fails, evaluate if theÂ
internal
 format (if specified) contains a field name that is identical to the external field name. If so, create, with appropriate type conversions, a mapping between the two field names.
ÂIf the preceding step fails and the external field is not marked asÂ
external_only
, create a new field (with the same field name and the appropriate type) in theÂtarget_internal
. Then create a mapping from the external field to this new internal field.
The type of the created internal field is controlled by the external field type.
External Type | Ultra Type mapped to |
---|---|
Primitive external | Maps to the corresponding primitive internal type. This depends on the external format specification. |
External format (sub-record) | Unless a |
List | Maps to an internal list type, where the list element type is deduced from the external list element type according to these rules (recursively). |
target_internal
When using automatic
, a new internal format may be automatically generated if any new internal fields are needed for the automatic mapping. The name of this new internal format is given by the target_internal
 specification of an in_map
 declaration. If no target_internal
name specification is given, the format is still generated if needed, however without usable name (that is, the format cannot be directly referred to in APL).
If a target_internal
 name has been given, this format is created even if no new fields are created.
If the in_map
 has a specified internal format, the generated format is a subtype of this format (hence, inherits all its fields).
Automatic Mapping Specifications
It is possible to modify the behavior of the automatic mapping algorithm when generating the sub-maps. The most direct way to do this is to specify how each external type will be mapped, either by explicitly specifying the sub-map or specifying the internal
 and/or target_internal
 name.
The syntax for the two forms of mapping specifications  is declared as follows:
<external type>: <in_map (target_)internal options> ;
and
<external type>: using in_map <map name>;
Example - Automatic mapping specifications
internal IntBase { int recordSequenceNumber; }; asn_block { ExtDataFile ::= CHOICE( mc MobileCall, dp DataPacket) MobileCall ::= SET ( ... ) DataPacket ::= SET ( ... ) }; in_map InMapDataFile : external(ExtDataFile), target_internal(IntDataFile) { automatic; };
In this case two new internal types are automatically generated for MobileCall
 and DataPacket
. However, they must usually be given a name or in other cases inherit the fields of some declared base internal format. This can be accomplished by adding some automatic mapping specifications:
Example - Adding automatic mapping specifications
in_map InMapDataFile : external(ExtDataFile), target_internal(IntDataFile) { automatic { MobileCall: internal(BaseInt), target_internal(TIMobileCall); DataPacket: internal(BaseInt), target_internal(TIDataPacket); }; };
This can also be done by specifying a using in_map
 declaration. For instance, the previous example is equivalent to the more complicated one:
Example - using in_map declaration
in_map MobileCallMap: internal(BaseInt), target_internal(TIMobileCall) { automatic; }; in_map DataPacketMap: internal(BaseInt), target_internal(TIDataPacket) { automatic; }; in_map InMapDataFile : external(ExtDataFile), target_internal(IntDataFile) { automatic { MobileCall: using in_map MobileCallMap; DataPacket: using in_map DataPacketMap; }; };
The type map specifications are inherited by every automatically generated sub-map:
Example - type map specifications inherited
asn_block { ... MobileCall ::= SET (location Location;) ... }; external Location { int longitude; int latitude; }; in_map InMapDataFile : external(ExtDataFile), target_internal(IntDataFile) { automatic { MobileCall: internal(BaseInt), target_internal(TIMobileCall); DataPacket: internal(BaseInt), target_internal(TIDataPacket); Location: internal(BaseInt), target_internal(TILocation); }; };
In this example, even though Location
 is not a part of the direct mapping of ExtDataFile
 itself, the type map information is still considered when creating TIMobileCall
.
use_external_names Automatic Option
When declaring a target_internal
 name for a large number of sub-formats the use_external_names
 option on the automatic
 block is a useful option. It gives all generated maps a target_internal
 name identical to the name of the external format.
Example - use_external_names option on the automatic block
in_map AMARecord_Map : external(AMARecord), target_internal(AMARecord) { automatic { RecordOwnerType : target_internal(RecordOwnerType); RecordOwnerDN : target_internal(RecordOwnerDN); Package_100 : target_internal(Package_100); Package_101 : target_internal(Package_101); Package_102 : target_internal(Package_102); }; };
The use_external_names
 specification eases the syntax by removing the need of all the target_internal
 specifications. The general syntax for a use_external_names
 declaration is as follows:
use_external_names(<external 1>, <external 2>, ...)
The previous example includes all of the specified external definitions within the file. Hence, the in_map
 can be rewritten as:
Example - in_map
in_map AMARecord_Map : external(AMARecord), target_internal(AMARecord) { automatic : use_external_names; };
It is possible to combine this with automatic mapping specifications. In this case the explicit specifications override the use_external_names
 behavior.
Automatic Block Internal Specification
It is also possible to append internal type specifications to the constructed in_maps
:
Example - Internal type specifications
in_map AMARecord_Map : external(AMARecord), target_internal(AMARecord) { automatic : use_external_names, internal(myInternal); };
If automatic mapping specifications are in use, these override the internal specifications on the automatic
 level (even if they only specify target_internal
).