Class: ISO::IBAN::Specification

Inherits:
Object
  • Object
show all
Defined in:
lib/iso/iban/specification.rb

Overview

Specification of the IBAN format for one country. Every country has its own specification of the IBAN format. SWIFT is the official authority where those formats are registered.

Constant Summary

StructureCodes =

A mapping from SWIFT structure specification to PCRE regex.

{
  'n' => '\d',
  'a' => '[A-Z]',
  'c' => '[A-Za-z0-9]',
  'e' => ' ',
}

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Specification) initialize(country_name, a2_country_code, iban_structure, iban_length, bban_structure, bban_length, bank_position_from, bank_position_to, branch_position_from, branch_position_to)

Returns a new instance of Specification



87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/iso/iban/specification.rb', line 87

def initialize(country_name, a2_country_code, iban_structure, iban_length, bban_structure, bban_length, bank_position_from, bank_position_to, branch_position_from, branch_position_to)
  @country_name         = country_name
  @a2_country_code      = a2_country_code
  @iban_structure       = iban_structure
  @iban_length          = iban_length
  @bban_structure       = bban_structure
  @bban_length          = bban_length
  @bank_position_from   = bank_position_from
  @bank_position_to     = bank_position_to
  @branch_position_from = branch_position_from
  @branch_position_to   = branch_position_to
end

Instance Attribute Details

- (Object) a2_country_code (readonly)

Returns the value of attribute a2_country_code



76
77
78
# File 'lib/iso/iban/specification.rb', line 76

def a2_country_code
  @a2_country_code
end

- (Object) bank_position_from (readonly)

Returns the value of attribute bank_position_from



76
77
78
# File 'lib/iso/iban/specification.rb', line 76

def bank_position_from
  @bank_position_from
end

- (Object) bank_position_to (readonly)

Returns the value of attribute bank_position_to



76
77
78
# File 'lib/iso/iban/specification.rb', line 76

def bank_position_to
  @bank_position_to
end

- (Object) bban_length (readonly)

Returns the value of attribute bban_length



76
77
78
# File 'lib/iso/iban/specification.rb', line 76

def bban_length
  @bban_length
end

- (Object) bban_structure (readonly)

Returns the value of attribute bban_structure



76
77
78
# File 'lib/iso/iban/specification.rb', line 76

def bban_structure
  @bban_structure
end

- (Object) branch_position_from (readonly)

Returns the value of attribute branch_position_from



76
77
78
# File 'lib/iso/iban/specification.rb', line 76

def branch_position_from
  @branch_position_from
end

- (Object) branch_position_to (readonly)

Returns the value of attribute branch_position_to



76
77
78
# File 'lib/iso/iban/specification.rb', line 76

def branch_position_to
  @branch_position_to
end

- (Object) country_name (readonly)

Returns the value of attribute country_name



76
77
78
# File 'lib/iso/iban/specification.rb', line 76

def country_name
  @country_name
end

- (Object) iban_length (readonly)

Returns the value of attribute iban_length



76
77
78
# File 'lib/iso/iban/specification.rb', line 76

def iban_length
  @iban_length
end

- (Object) iban_structure (readonly)

Returns the value of attribute iban_structure



76
77
78
# File 'lib/iso/iban/specification.rb', line 76

def iban_structure
  @iban_structure
end

Class Method Details

+ (Hash<String => ISO::IBAN::Specification>) load_yaml(path)

Load the specifications YAML.

Returns:



22
23
24
# File 'lib/iso/iban/specification.rb', line 22

def self.load_yaml(path)
  Hash[YAML.load_file(path).map { |country, spec| [country, new(*spec)] }]
end

+ (Array<ISO::IBAN::Specification>) parse_file(path)

Parse the SWIFT provided file (which sadly is a huge mess and not machine friendly at all).

Returns:



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/iso/iban/specification.rb', line 29

def self.parse_file(path)
  File.read(path, encoding: Encoding::Windows_1252).encode(Encoding::UTF_8).split("\r\n").tap(&:shift).flat_map { |line|
    country_name, country_codes, iban_structure_raw, iban_length, bban_structure, bban_length, bank_position = line.split(/\t/).values_at(0,1,11,12,4,5,6)
    codes        = country_codes.size == 2 ? [country_codes] : country_codes.scan(/\b[A-Z]{2}\b/)
    primary_code = codes.first
    bank_position_from, bank_position_to, branch_position_from, branch_position_to = bank_position.match(/(?:[Pp]ositions?|) (\d+)-(\d+)(?:.*Branch identifier positions?: (\d+)-(\d+))?/).captures.map { |pos| pos && pos.to_i+3 }

    codes.map { |a2_country_code|
      iban_structure = iban_structure_raw[/#{a2_country_code}[acen\!\d]*/] || iban_structure_raw[/#{primary_code}[acen\!\d]*/]
      bban_structure = bban_structure[/[acen\!\d]*/]

      new(
        country_name.strip,
        a2_country_code,
        iban_structure,
        iban_length.to_i,
        bban_structure.strip,
        bban_length.to_i,
        bank_position_from,
        bank_position_to,
        branch_position_from,
        branch_position_to
      )
    }
  }
end

+ (Object) structure_regex(structure, anchored = true)

*n: Digits (numeric characters 0 to 9 only) *a: Upper case letters (alphabetic characters A-Z only) *c: upper and lower case alphanumeric characters (A-Z, a-z and 0-9) *e: blank space *nn!: fixed length *nn: maximum length

Example: “AL2!n8!n16!c”



64
65
66
67
68
69
70
71
72
73
74
# File 'lib/iso/iban/specification.rb', line 64

def self.structure_regex(structure, anchored=true)
  source = structure.scan(/([A-Z]+)|(\d+)(!?)([nac])/).map { |exact, length, fixed, code|
    if exact
      Regexp.escape(exact)
    else
      StructureCodes[code]+(fixed ? "{#{length}}" : "{,#{length}}")
    end
  }.join(')(')

  anchored ? /\A(#{source})\z/ : /(#{source})/n
end

Instance Method Details

- (Fixnum) account_code_length

Returns The length of the account code in the IBAN.

Returns:

  • (Fixnum)

    The length of the account code in the IBAN.



129
130
131
# File 'lib/iso/iban/specification.rb', line 129

def 
  bban_length-bank_code_length-branch_code_length
end

- (Fixnum) bank_code_length

Returns The length of the bank code in the IBAN, 0 if the IBAN has no bank code.

Returns:

  • (Fixnum)

    The length of the bank code in the IBAN, 0 if the IBAN has no bank code.



117
118
119
# File 'lib/iso/iban/specification.rb', line 117

def bank_code_length
  @bank_position_from && @bank_position_to ? @bank_position_to-@bank_position_from+1 : 0
end

- (Fixnum) branch_code_length

Returns The length of the bank code in the IBAN, 0 if the IBAN has no branch code.

Returns:

  • (Fixnum)

    The length of the bank code in the IBAN, 0 if the IBAN has no branch code.



123
124
125
# File 'lib/iso/iban/specification.rb', line 123

def branch_code_length
  @branch_position_from && @branch_position_to ? @branch_position_to-@branch_position_from+1 : 0
end

- (Array<Integer>) component_lengths

Returns An array with the lengths of all components.

Returns:

  • (Array<Integer>)

    An array with the lengths of all components.



111
112
113
# File 'lib/iso/iban/specification.rb', line 111

def component_lengths
  [bank_code_length, branch_code_length, ].tap { |lengths| lengths.delete(0) }
end

- (Regexp) iban_regex

Returns A regex to verify the structure of the IBAN.

Returns:

  • (Regexp)

    A regex to verify the structure of the IBAN.



101
102
103
# File 'lib/iso/iban/specification.rb', line 101

def iban_regex
  @_iban_regex ||= self.class.structure_regex(@iban_structure)
end

- (Array) to_a

Returns An array with the Specification properties. Used for serialization.

Returns:

  • (Array)

    An array with the Specification properties. Used for serialization.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/iso/iban/specification.rb', line 134

def to_a
  [
    @country_name,
    @a2_country_code,
    @iban_structure,
    @iban_length,
    @bban_structure,
    @bban_length,
    @bank_position_from,
    @bank_position_to,
    @branch_position_from,
    @branch_position_to,
  ]
end

- (Regexp) unanchored_iban_regex

Returns A regex to identify the structure of the IBAN, without anchors.

Returns:

  • (Regexp)

    A regex to identify the structure of the IBAN, without anchors.



106
107
108
# File 'lib/iso/iban/specification.rb', line 106

def unanchored_iban_regex
  self.class.structure_regex(@iban_structure, false)
end