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


- type: ModificationMethod
  attributes:
    displayName: IMEI
    description: |
          Generates an IMEI based on an existing IMEI and the seed parameter.'RAND' will generate a random value. All other values are used as they are for the seed.
    inputType: COLUMN
    mappingTableContainers: []
    mappingTableAccessMode: READ
    code: |
        /*
         * *****************************************************************************
         * IMEI
         * *****************************************************************************
         *
         * 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.
         * 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 IMEI is zero-based.
         * *****************************************************************************
         */
        importClass(Packages.de.ubs.xdm3.batch.modification.ModificationException);
        
        /*
         * This function is called once before the processing starts. The method
         * is called once per table.
         */
        function init() {
        
        }
        
        /*
         * 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 seedValue = "";
        
            if (ctx.indexOf(seed) != -1) {
                seedValue = dataArray[ctx.indexOf(seed)];
            } else {
                if (seed == "RAND") {
                    seedValue = Math.floor(Math.random() * 1000000000);
                } else {
                    seedValue = seed;
                }
            }
        
            var imei = new java.lang.String(dataArray[columnIndex]).trim();
            var numbers = /^\d{15}$/;
            if (imei.match(numbers) === null) {
                throw new ModificationException("Invalid imei '" + imei + "' found, only numeric digits with a length of 15 allowed.");
            }
        
            var length = imei.length;
            var tacPart = imei.substring(length - 15, length - 7);
            var snrPart = imei.substring(length - 7, length - 1);
        
            var snr = get6DigitHash(seedValue + snrPart);
            var checkDigit = getCheckDigit(tacPart + snr);
            dataArray[columnIndex] = tacPart + snr + checkDigit;
        }
        
        /*
         * This function is executed once after the modification of a table is complete. The method
         * is called once per table.
         */
        function close() {
        }
        
        function get6DigitHash(value) {
            var hash = 0, i, chr, len;
            value = String(value);
            if (value.length === 0) {
                value = "1234567890";
            }
        
            for (i = 0, len = value.length; i < len || hash < 0; i++) {
                chr = value.charCodeAt(i % value.length);
                hash = ((hash << 5) - hash) + chr;
                hash |= 0; // Convert to 32bit integer
            }
        
            var ret = String((hash % 1000000));
            while (ret.length < 6) {
                ret = "0" + ret;
            }
            return ret;
        }
        
        /*
         * Calculate the check digit (checksum) for the IMEI
         *
         * Computation of check digit from the IMEI proceeds as follows:
         * Step 1:  Double the imeis of the odd labelled digits D1, D3, D5 ... D13
         *          of the IMEI.
         * Step 2:  Add together the individual digits of all the seven numbers
         *          obtained in Step 1, and then add this sum to the sum of all the
         *          even labelled digits D2, D4, D6 ... D14 of the IMEI.
         * Step 3:  If the number obtained in Step 2 ends in 0, then set CD to be 0.
         *          If the number obtained in Step 2 does not end in 0, then set CD
         *          to be that number subtracted from the next higher number which
         *          does end in 0.
         */
        function getCheckDigit(digits) {
            var sum = 0;
            var length = digits.length;
        
            //process digits in reverse order
            for (var i = 0; i < length; i++) {
                // get digits in reverse order
                var digit = parseInt(digits[length - i - 1], 10);
        
                // every odd number multiply with 2 and add the single digits to sum
                if (i % 2 === 0) {
                    digit *= 2;
        
                    // add the first digit to sum if the imei is > 10 else add 0
                    sum += Math.floor(digit / 10);
                    // add the second digit to sum or the only digit if the number is < 10
                    sum += (digit % 10);
                } else {
                    // add every even digit directly to sum
                    sum += digit;
                }
            }
        
            // if the sum ends in 0 then return 0 as CD checksum
            if (sum % 10 === 0) {
                return 0;
            }
        
            // if the sum does not end by 0 then substract sum from the next higher number ending in 0 and return the result
            return ((Math.floor(sum / 10) + 1) * 10) - sum;
        }
    parameters:
    - displayName: Seed
      description: |
          Specifies the value that is used to calculate the hash.
      variableName: seed
      dataType: STRING
