# 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: E-Mail
    description: |
          Generates an email address based on the specified seed value.
          The country parameter specifies the country/region of origin for the first name ('EN', 'DE', 'FR', 'IT', 'NL').
          The sex parameter specifies the sex ('M' for male, 'F' for female).
          For both parameters, only a single value can be specified (e.g. 'DE' and 'F').
          The domain parameter specifies the domain name of the email address.
          If the domain parameter is omitted, it defaults to 'example.com'.
          *This method requires the lookup tables to be installed.*
    scriptLanguage: "GROOVY"
    legacyScript: false
    inputType: "COLUMN"
    mappingTableContainers:
      - "XDM Lookup Table"
    mappingTableAccessMode: READ
    code: |
        /*
         * *****************************************************************************
         * Email
         * *****************************************************************************
         *
         * 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
        
        FIRST_NAME_TABLE = 'FIRST_NAMES'
        LAST_NAME_TABLE  = 'LAST_NAMES'
        firstNameCountMap = [:]
        lastNameCountMap  = [:]
        mappingTableUtils = new MappingTableUtils(lookupTable)
        
        /*
         * This function is called once before the processing starts. The method
         * is called once per table.
         */
        
        def init() {
            // Pre-calculate, for each country (KEY_01) and gender (KEY_02), how many rows exist in the lookup table.
            // The result is stored in countMap and used later to compute a valid row number.
            firstNameCountMap = mappingTableUtils.count(FIRST_NAME_TABLE, "KEY_01", "KEY_02")
        
            // Pre-calculate, for each country (KEY_01), how many rows exist in the lookup table.
            // The result is stored in countMap and used later to compute a valid row number.
            lastNameCountMap  = mappingTableUtils.count(LAST_NAME_TABLE, "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() {
            // The configured seed is hashed twice to prevent deriving the original seed value
            def seedHash = HashUtils.hashInt(HashUtils.hashStringLikeInt(modificationMethod.seed.toString()))
        
            // Country parameter configured on the modification set
            def countryValue =  modificationMethod.country.toString()
            // Gender parameter configured on the modification set
            def sexValue = modificationMethod.sex.toString()
        
            // Check how many lookup entries exist for the selected country and gender
            def firstNameCount = firstNameCountMap.get(new CompositeKey(countryValue, sexValue))
        
            // Compute a 1-based row number within the lookup table
            // based on the hashed seed and the number of available entries for that country and gender.
            def firstNameRowNumber = (seedHash % firstNameCount) + 1
        
            // Fetch the selected row from the lookup table for the given country and gender.
            def firstName = mappingTableUtils.get(FIRST_NAME_TABLE, firstNameRowNumber, countryValue, sexValue)
            if(!firstName) throw new ModificationException("Failed to retrieve data from table $FIRST_NAME_TABLE")
        
            // Check how many lookup entries exist for the selected country
            def lastNameCount = lastNameCountMap.get(new CompositeKey(countryValue))
        
            // Compute a 1-based row number within the lookup table
            // based on the hashed seed and the number of available entries for that country.
            def lastNameRowNumber = (seedHash % lastNameCount) + 1
        
            // Fetch the selected row from the lookup table for the given country.
            def lastName = mappingTableUtils.get(LAST_NAME_TABLE, lastNameRowNumber, countryValue)
            if(!lastName) throw new ModificationException("Failed to retrieve data from table $LAST_NAME_TABLE")
        
            // Concatenate the result from the first and last name and add a domain specified in the modification set parameters
            data[columnIndex] = "${firstName[0]}.${lastName[0]}@${modificationMethod.domain}"
            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: |
          Specifies the value that is used to calculate the hash.
      variableName: seed
      dataType: STRING
    - displayName: Country
      description: |
          Specifies the origin of the email.
      variableName: country
      dataType: STRING
    - displayName: Sex
      description: |
          Specifies the gender of the first name.
      variableName: sex
      dataType: STRING
    - displayName: Domain
      description: |
          Domain that is used to generate e-mail addresses.
      variableName: domain
      defaultValue: "example.com"
      dataType: STRING
