# Thu, 20 Aug 2026 13:11:52 GMT
---
version: 23
data:


- type: Credential
  attributes:
    displayName: XDM Lookup Table Credential
    description: Credential for XDM Lookup Table
    user: sa
    password: ""

- type: MappingTableContainer
  attributes:
    displayName: XDM Lookup Table
    description: Mapping table to use the xdm lookup tables
    variableName: lookupTable
    credential: XDM Lookup Table Credential

- type: ModificationMethod
  attributes:
    displayName: International bank account number
    description: |
          Generates an international bank account number (IBAN) based on the specified seed value.
          The country parameter specifies the country/region of origin ('AT', 'CH', 'DE', 'NL').
          Only a single country value can be specified (e.g. 'DE').
          *This method requires the lookup tables to be installed.*
    scriptLanguage: "GROOVY"
    legacyScript: false
    inputType: "COLUMN"
    mappingTableContainers:
      - "XDM Lookup Table"
    mappingTableAccessMode: READ
    code: |
        /*
         * *****************************************************************************
         * IBAN
         * *****************************************************************************
         *
         * The following variables are available in this script:
         * =====================================================
         * ctx             : A context object that offers a number of methods.
         *                   The method indexOf() can be used to get the index of a
         *                   specific column within the data.
         * data       : The data array. This array contains the contents of all
         *                   columns of the current row of the table that is being
         *                   masked by this method.
         *
         * Additionally for column based modification methods the following two
         * variables are available:
         * columnName      : The name of the column that matched the pattern.
         * columnIndex     : The position of the column that matched the pattern within
         *                   the data array. This value is zero-based.
         * *****************************************************************************
         */
        import de.ubs.xdm3.batch.modification.MappingTableUtils
        import de.ubs.xdm3.batch.modification.ModificationException
        import de.ubs.xdm3.batch.modification.CompositeKey
        import de.ubs.xdm3.batch.modification.HashUtils
        
        
        TABLE_NAME = 'BANKS';
        countMap = [:]
        mappingTableUtils = new MappingTableUtils(lookupTable)
        
        /*
         * This function is called once before the processing starts. The method
         * is called once per table.
         */
        def init() {
            countMap = mappingTableUtils.count(TABLE_NAME, "KEY_01")
        
            return null
        }
        
        /*
         * This function should modify the row that is provided by the data. The
         * method is called for each single row of the table.
         */
        def apply() {
            def seedHash = HashUtils.hashInt(HashUtils.hashStringLikeInt(modificationMethod.seed.toString()))
        
            def countryValue = modificationMethod.country.toString()
        
            def count = countMap.get(new CompositeKey(countryValue))
            if (count == null || count <= 0) {
                throw new ModificationException("No entries for country ='${modificationMethod.country}'.")
            }
        
            def rowNumber = (seedHash % count) + 1
            def result = mappingTableUtils.get(TABLE_NAME, rowNumber, countryValue)
            if (result == null) {
                throw new ModificationException("Failed to retrieve data from table ${TABLE_NAME}")
            }
        
            def blz = result[0]
            def knr = seedHash
            def blzknr, length, s = ""
        
            switch (countryValue) {
                case "DE":
                    length = 22
                    blzknr = blz.toString().padLeft(8, '0') + knr.toString().padLeft(10, '0')
                    break
                case "AT":
                    length = 20
                    blzknr = blz.toString().padLeft(5, '0') + knr.toString().padLeft(11, '0')
                    break
                case "CH":
                    length = 21
                    blzknr = blz.toString().padLeft(5, '0') + knr.toString().padLeft(12, '0')
                    break
                case "NL":
                    length = 18
                    blzknr = blz.toString().padLeft(4, '0') + knr.toString().padLeft(10, '0')
                    break
                default:
                    throw new IllegalArgumentException("Unsupported country")
            }
            blzknr = blzknr + countryValue + "00"
        
            for(int i = 0; i < length; i++) {
                def c = blzknr.charAt(i)
                if (c >= '0' && c <= '9') {
                    s += c
                } else {
                    s += ((int)c - 55).toString()
                }
            }
        
            def t = new java.math.BigDecimal(s).remainder(new java.math.BigDecimal(97))
            def code = 98 - (t % 97)
            data[columnIndex] = countryValue + code.toString().padLeft(2, '0') + s.substring(0, length - 4)
            return true
        }
        
        /*
         * This function is executed once after the modification of a table is complete. The method
         * is called once per table.
         */
        
        def close() {
            mappingTableUtils.close()
        }
    parameters:
    - displayName: Seed
      description: |
          Column that is used to calculate the hash.
      variableName: seed
      dataType: STRING
    - displayName: Country
      description: |
          Specifies the origin of the international bank account number.
      variableName: country
      dataType: STRING
