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 collapse

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

#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) ⇒ Specification

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

#a2_country_codeObject (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

#bank_position_fromObject (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

#bank_position_toObject (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

#bban_lengthObject (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

#bban_structureObject (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

#branch_position_fromObject (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

#branch_position_toObject (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

#country_nameObject (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

#iban_lengthObject (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

#iban_structureObject (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

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

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

.parse_file(path) ⇒ Array<ISO::IBAN::Specification>

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

.structure_regex(structure, anchored = true) ⇒ Object

*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

#account_code_lengthFixnum

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

#bank_code_lengthFixnum

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

#branch_code_lengthFixnum

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

#component_lengthsArray<Integer>

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

#iban_regexRegexp

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

#to_aArray

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

#unanchored_iban_regexRegexp

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