# Mon, 22 Dec 2025 14:57:12 GMT
---
version: 23
data:


- type: ModificationMethod
  attributes:
    displayName: Credit card number
    description: |
          Generates a credit card number. The first parameter should be an existing credit card number. The second parameter specifies how many digits should be copied without modification from the original number.
    inputType: COLUMN
    mappingTableContainers: []
    mappingTableAccessMode: READ
    code: |
        /*
         * *****************************************************************************
         * Credit Card Number
         * *****************************************************************************
         * 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 dataArray.
         * dataArray       : 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.
         * *****************************************************************************
         */
        importClass(Packages.de.ubs.xdm3.batch.modification.ModificationUtils);
        importClass(Packages.de.ubs.xdm3.batch.modification.ModificationException);
        importClass(Packages.de.ubs.xdm3.batch.modification.CompositeKey);
        importClass(Packages.de.ubs.xdm3.batch.modification.HashUtils);
        importClass(Packages.java.math.BigInteger);
        
        /*
         * This function is called once before the processing starts. The method
         * is called once per table.
         */
        function init() {
            ctx.require("big.js");
        }
        
        /*
         * This function should modify the row that is provided by the dataArray. The
         * method is called for each single row of the table.
         */
        function apply() {
            var value = "";
        
            if (ctx.indexOf(seed) != -1) {
                value = dataArray[ctx.indexOf(seed)];
            } else {
                if (seed == "RAND") {
                    value = Math.floor(Math.random() * 10000000000000000);
                } else {
                    value = seed;
                }
            }
            if (Number.isNaN(Number(value)) || value < 0) {
                value = HashUtils.hashInt(HashUtils.hashStringLikeInt(value));
                var shift = (Math.pow(10, 16 - (Math.floor(java.lang.Math.log10(value)) + 1)));
                value = (value * shift) + (HashUtils.hashInt(HashUtils.hashStringLikeInt(value)) % shift);
            }
            value = Math.floor(value);
            if ((Math.floor(java.lang.Math.log10(Math.floor(value))) + 1) != 16) {
                if (value == 0) {
                    value = 1;
                }
                var shift = (Math.pow(10, 16 - (Math.floor(java.lang.Math.log10(value)) + 1)));
                value = (value * shift) + (HashUtils.hashInt(HashUtils.hashStringLikeInt(value)) % shift);
            }
        
            var Hex100000000 = new Big(2147483648);
            var l = Math.floor(java.lang.Math.log10(value)) + 1;
            if (retain >= l) {
                dataArray[columnIndex] = value;
                return;
            }
            var a = (value / 0x100000000) & 0x7FFFFFFF;
            var b = value & 0x7FFFFFFF;
            var m = new Big(HashUtils.hashInt(a ^ b));
            var n = new Big(HashUtils.hashInt(m));
            var s = m.times(Hex100000000).plus(n);
            s = s.mod(Math.pow(10, l));
            if (retain > 0) {
                var v = new Big(value);
                var left = v.minus(v.mod(Math.pow(10, l - retain)));
                var right = s.mod(Math.pow(10, l - retain));
                s = left.plus(right);
            }
            var r = HashUtils.luhn(s);
            dataArray[columnIndex] = r.toFixed(0);
        }
        
        /*
         * This function is executed once after the modification of a table is complete. The method
         * is called once per table.
         */
        function close() {
        }
    parameters:
    - displayName: Seed
      description: |
          The original credit card number.
      variableName: seed
      dataType: STRING
    - displayName: Retain
      description: |
          The number of digits to retain from the original number.
      variableName: retain
      dataType: NUMBER
