Dragonite.Parser (Dragonite v0.1.1) View Source

Dragonite.Parser is the module to handle decode and encode for an EDI message.

Decoding

To decode a message, use the decode/1 function, providing a string as argument. The decode function tries to decode the message into an %DragoniteEDI.Message{} struct and raises an error if the message provided is not a valid message. To decode the parser follow the next rules:

  • Must start with ISA struct.

  • Must end with IEA struct.

  • Function groups start with GS and end with GE.

  • Segments start with ST and end with SE.

  • Separator for elements is ~

  • Separator for elements into fields is *

This is a single example of an EDI message:

iex(1)> msg = "ISA*00* *00* *32*0000*32*0000 *121206*1142*U*00601*000000003*1*T*>~" <>
"GS*SM*300237446*351538247*20121206*1142*3*X*006010~ST*204*000000001~B2**BWEM**317749**CC*L~" <>
"B2A*00*FR~L11*SMC LTL Fuel*XX7*Fuel Schedule: SMC LTL Fuel~L11*104*ZZ*Total Distance:104~G6" <>
"2*64*20121206*1*1244*LT~AT5*400**Transport~RTT*FC*550~C3*USD~N1*BT*Pokemon GO*93*2649" <>
"~N3*19661 Brownstown Center Dr*Suite 600~N4*Brownstown*MI*48183-1679*USA~G61*LG*Contact Phone" <>
"*TE*000-000-000 ext 3~G61*LG*Contact Mobile*CP*000-000-0000~G61*LG*Contact Email*EM*" <>
"dratini@pokemon.com~N7**Unknown*********53****0636*****110*98~S5*0*LD~L11*602465*SI~" <>
"G62*69*20120810*U*1600*LT~N1*SH*POKEMON GO*93*5715~N3*603 7th St~N4*Pokemon*MI*49601-1344*" <>
"USA~G61*LG*Contact Phone*TE*000-000-0000 ext 1357~G61*LG*Contact Email*EM*dratini@pokemon.com" <>
"~N1*CN*ABC Undercar Products Group*93*9889~N3*4247 Paleta Town SE~N4*Wyoming*MI*49508-3400*USA~N1*" <>
"SF*AVON AUTOMOTIVE*93*5715~N3*603 7th St~N4*Pokemon*MI*49601-1344*USA~G61*LG*Contact Phone*TE*" <>
"000-000-0000 ext 1357~G61*LG*Contact Email*EM*dratini@pokemon.com~LAD*PLT****L**S1*264" <>
"*****Freight All Kinds~L5*1**60*N~S5*1*UL~L11*602465*SI~G62*69*20120813*U*1600*LT~N1*SH*POKEMON" <>
" GO*93*5715~N3*603 7th St~N4*Pokemon*MI*49601-1344*USA~G61*LG*Contact Phone*TE*000-000" <>
"-0000 ext 1357~G61*LG*Contact Email*EM*dratini@pokemon.com~N1*CN*ABC " <>
"Products Group*93*9889~N3*4247 Paleta Town SE~N4*Wyoming*MI*49508-3400*USA~N1*ST*ABC " <>
" Products Group*93*9889~N3*4247 Paleta Town SE~N4*Wyoming*MI*49508-3400*USA~LAD*PLT" <>
"****L**S1*264*****Freight All Kinds~L5*1**60*N~SE*51*000000001~GE*1*3~IEA*1*000000003"

Now to decode the above message just call to decode/1:

iex(2)> Dragonite.Parser.decode msg

The response (if valid) will be an %DragoniteEDI.Message{} struct containing all elements considered from parsing rules. New rules can de added if nedeed.

Decoding multiple STs

Sometimes the incoming messages will contain multiple ST, this means that multiple messages are sent once a time.

To support this, the decode/1 returns a list of messages instead a single response (even if only 1).

Encoding

To encode a message use the encode/1 function, providing a DragoniteEDI.Message{} as argument. The encode function tries to encode the struct as a string message and raises an errir if the message provided is not a valid message. To encode a message:

iex(1)> Dragonite.Parser.encode %DragoniteEDI.Message{}

The response is a single string as an original EDI message.

Verification

By default decode/1 verifies the struct and return {:ok, %DragoniteEDI.Message{}} or {:error, error} where error will describe the missing or incomplete struct. Missing or incomplete structs are marked when sub-structs are nil or empty lists.

Validation can be skipped using verify: false when calling decode/2 using opts (2nd argument) as keywords.

By default encode/1 verifies the struct of edi message, this is mandatory.

Rules

A single message can be passed (after parsed) for a set of rules to check if passed the criteria or not.

The rules criteria are defined in a single YML file (see Config for more info).

To check if a message pass the criteria:

iex(1)> Dragonite.Parser.to_rules %DragoniteEDI.Message{}, 204

If passed the struct is returned, otherwise an error is returned.

Seek

Seek allows search in values of ST segment, match criteria and return values based on custom functions provided as a part of seek process. Seek process needs the values (that can be extracted using struct_at/3), the matching criteria, the values to return and a fn with two args, the first one is the resulting of matching criteria and the second one the return data.

Link to this section Summary

Functions

Tries to decode a single EDI message from a string into %DragoniteEDI.Message{}. Raises an argument error if message provided is not a valid message with the struct of EDI protocol.

Same as decode/1 but raises an error instead of return the error message.

Tries to encode a single EDI message from struct into string. Raises an argument error if message provided is not a valid message with the struct of EDI protocol.

Same as encode/1 but raises an error instead of return the error message.

Verifies if a DragoniteEDI.Message{} is valid, checking if all sub-structs are non empty and then mark message as valid. Return error at sub-struct incompleted.

Seek criteria and apply fun to elements found

Get value at position, length or full values of some segment in Edi message struct

Check if a %DragoniteEDI.Message{} is valid against rules defined in environment, so don't need to pass rules, since they are loaded from pre-loaded config.

Link to this section Functions

Link to this function

decode(msg, opts \\ [verify: true])

View Source

Tries to decode a single EDI message from a string into %DragoniteEDI.Message{}. Raises an argument error if message provided is not a valid message with the struct of EDI protocol.

Example

iex(1)> Dragonite.Parser.decode "ISA..."
Link to this function

decode!(msg, opts \\ [verify: true])

View Source

Same as decode/1 but raises an error instead of return the error message.

Example

iex(1)> Dragonite.Parse.decode! "ISA..."

Specs

encode(%DragoniteEDI.Message{iea: term(), isa: term(), sts: term()}) ::
  {:ok, String.t()} | {:error, atom()}

Tries to encode a single EDI message from struct into string. Raises an argument error if message provided is not a valid message with the struct of EDI protocol.

Example

iex(1)> Dragonite.Parser.encode %DragoniteEDI.Message{}

Specs

encode!(%DragoniteEDI.Message{iea: term(), isa: term(), sts: term()}) ::
  String.t() | no_return()

Same as encode/1 but raises an error instead of return the error message.

Example

iex(1)> Dragonite.Parser.encode! %DragoniteEDI.Message{}
Link to this function

is_valid(struct, check \\ true)

View Source

Specs

is_valid(
  %DragoniteEDI.Message{iea: term(), isa: term(), sts: term()},
  true | false
) ::
  {:ok, %DragoniteEDI.Message{iea: term(), isa: term(), sts: term()}}
  | {:error, atom()}

Verifies if a DragoniteEDI.Message{} is valid, checking if all sub-structs are non empty and then mark message as valid. Return error at sub-struct incompleted.

A custom check can be passed to skip the validation in order to use in some pipelines.

Example

iex(1)> Dragonite.Parser.is_valid(%DragoniteEDI.Message{})
Link to this function

seek(values, condition, extractor, fun)

View Source

Specs

seek([list()], list(), [list()], (list(), [list()] -> binary() | number())) ::
  binary() | number()

Seek criteria and apply fun to elements found

Example

iex(1)> Dragonite.Parser.seek([["L11", "", ""]], [], [%{key: "L11", pos: 1}], fn _, _ -> :ok end)
Link to this function

struct_at(struct, arg2, position)

View Source

Specs

struct_at(
  %DragoniteEDI.Message{iea: term(), isa: term(), sts: term()},
  String.t(),
  any()
) :: String.t() | list() | non_neg_integer()

Get value at position, length or full values of some segment in Edi message struct

Example

iex(1)> Dragonite.Parser.struct_at(%DragoniteEDI.Message{}, "isa", 1)
Link to this function

to_rules(struct, for_type, wildcards \\ [])

View Source

Specs

to_rules(
  %DragoniteEDI.Message{iea: term(), isa: term(), sts: term()},
  integer(),
  [String.t()]
) ::
  {:ok, %DragoniteEDI.Message{iea: term(), isa: term(), sts: term()}}
  | {:error, {:rules_not_passed, list()}}

Check if a %DragoniteEDI.Message{} is valid against rules defined in environment, so don't need to pass rules, since they are loaded from pre-loaded config.

If rules are empty the message is marked as valid, since there are no rules to check.

The function returns either the message or an error containing the validation that breaks the rules.

To work with wildcards just pass the wildcard as an enumerable of one struct:

Dragonite.Parser.to_rules(%DragoniteEDI.Message{}, 204, [%MyStruct{qualifier: "Q1"}])

After that definitions in YML against $custom.? will run extracting the value from custom struct provided.

Example

iex(1)> Dragonite.Parser.to_rules(%DragoniteEDI.Message{}, 204)