Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • Headers and Trailers (which are included in the external code block)

  • external
  • internal
  • in_map
  • decoder
  • out_map
  • encoder

external

Both headers and trailers as well as record types should be included in the  external  code block.

Headers and Trailers

Since headers and trailers are treated as records, the same syntax as for external records apply. APL syntax can also be used within UFDL code.

Code Block
external FileHeader {
   ascii header : terminated_by(0xA);
};


...

The identified_by for the trailer is not crucial, however, it provides additional validation during decoding, since it evaluates that the trailer really starts with "Date".

Record Types

The definitions of TypeA and TypeB are fairly straight forward. No  encode_value  for RecordType is set, since this is evaluated from the internal UDR during encoding (see the section below, internal).

Code Block
external TypeA : identified_by( RecordType == "A" ),
    terminated_by(0xA) {
        ascii RecordType      : static_size(2), 
                                terminated_by(":");
        ascii A_number        : terminated_by(":");
        ascii B_number        : terminated_by(":");
        ascii SequenceNumber  : terminated_by(":");
        ascii Duration        : terminated_by(0xA);
};


external TypeB : identified_by( RecordType == "B" ),
    terminated_by(0xA) {
        ascii RecordType      : static_size(2),
                                terminated_by(",");
        ascii CallingCountry  : terminated_by(",");
        ascii SequenceNumber  : terminated_by(",");
        ascii LocalAreaCode   : terminated_by(",");
        ascii A_number        : terminated_by(",");
        ascii B_number        : terminated_by(",");
        ascii CauseForOutput  : terminated_by(",");
        ascii CalledCountry   : terminated_by(0xA);
}; 


internal
Anchor
internal
internal

Suppose it is desired to output one record type as a replacement for the incoming types A and B the simplest way is to create a mutual internal.

...

Both TypeA and TypeB records are mapped to MyInternal. The common fields will always be set. The others are defined as optional, hence, their presence depends on the record type. The RecordType in the internal type is required for encoding, since the encoder needs to evaluate the record type to decide whether to encode as TypeA or TypeB.

in_map

Both record types A and B are mapped to the same internal. This approach is useful to simplify APL syntax within processing (a lot of if-statements used to determine the record type, can be eliminated), or in case one resulting output type is produced.

...

Code Block
in_map Header_in : external( FileHeader ), 
   target_internal( Header ), discard_output { 
        automatic; 
};

// The trailer gets a special record type.

in_map Trailer_in : external( FileTrailer ), 
   target_internal( Trailer ) { 
        automatic; 
};


decoder

The following constructed decoder definition will expect all batches to start with a header, end with a trailer and have zero/one/several A and B records in between. If not, the decoder will abort.

Code Block
// The sub-decoders.

decoder Records : in_map( TypeA_in ), in_map( TypeB_in ); 
decoder Header : in_map( Header_in ); 
decoder Trailer : in_map( Trailer_in );

// The total (file) decoder. 
// '*' means zero/one/several records are expected between 
// one header and one trailer for each file collected.

decoder Total { 
   decoder Header; 
   decoder Records *; 
   decoder Trailer; 
};


out_map

Suppose you are required to encode back to the original format.

...

Note
titleNote!

TypeA and TypeB both are encoded from MyInternal. Which type to use depends on the value of the RecordType field.

encoder

A constructed encoder cannot be created. Hence, the following encoder definition will not care for the order of arriving records, nor that all types must be present in the output file.

Code Block
encoder Total: out_map( TypeA_out ),
               out_map( TypeB_out ), 
               out_map( Header_out ), 
                out_map( Trailer_out );

Scroll pagebreak