Create Custom Masking Functions

Before you can use custom functions, you have to configure them.
If the out-of-the-box functions that FDM provides do not meet your needs, you can write your own custom masking functions. You also choose to implement custom functions if, for example, your masking logic is proprietary. FastDataMasker provides a framework that lets you write custom masking functions as Java plugins.
We recommend to make backups of your custom functions and of the configuration file
. During updates or upgrades of TDM, the configuration file
is overwritten. The "
" folder inside the FDM install folder is not deleted or changed.
This article contains the following procedures and example files:
Implement Custom Functions
  1. Open the IDE of your choice, for example, Eclipse, and create a Java project.
  2. Go to the FDM install folder in the Explorer.
    C:\Program Files\Grid-Tools\FastDataMasker
  3. Copy the file
    and add it to the project's build path.
  4. Create a Java class which implements the interface
    Examples: Create class
  5. Override the
    1. Note that the
      method takes varargs:
      • arg[0]
        holds the original value that you want to mask.
      • arg[1]
        holds Parm 1
      • arg[2]
        holds Parm 2
      • arg[3]
        holds Parm 3
      • arg[4]
        holds Parm 4
    2. Modify the original value through the
      method, based on your masking requirements. You can use the
      parameters that you have passed.
    3. Return the masked value.
  6. Build a JAR file from this source and name it.
    Example: Build
  7. Create a folder called "custom" in the FDM install folder.
    C:\Program Files\Grid-Tools\FastDataMasker
  8. Place the
    file in the "custom" folder.
Before you can use custom functions, you have to configure them.
Example File (Template)
package com.example; import com.grid_tools.products.datamasker.IMaskFunction; public class CustomFunction implements IMaskFunction { @Override public Object mask(Object... args) { String originalValue = (String) args[0]; Boolean isFoo = Boolean.parseBoolean((String) args[1]); String maskedValue; if (isFoo) { maskedValue = originalValue.concat((String) args[2]); } else { maskedValue = originalValue.replaceAll((String) args[3], (String) args[4]); } return maskedValue; } }
Example File
This example class uses two parameters, args[1] and args[2]. They correspond to parm1 and parm2.
package com.example; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Random; import com.grid_tools.products.datamasker.IMaskFunction; public class GambianID implements IMaskFunction { /** * In The Gambia, the National Identification Number (NIN) * consists of 11 digits in the form DDMMYY-PG-##CS. * DD MM YY indicates date of birth * PG indicates place of issuance and nationality * ## is a serial number and also indicates sex * CS is a check sum. */ @Override public Object mask(Object... args) { // Assuming original value is a String // Parts of original value may be a driving factor in obtaining the masked value String originalValue = (String) args[0]; // Assume date of birth format as yyyy-MM-dd SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // Date of Birth comes from parm 1 Date dob = null; try { dob = sdf.parse((String) args[1]); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } Calendar calendar = Calendar.getInstance(); calendar.setTime(dob); Integer dd = calendar.get(Calendar.DATE); Integer mm = calendar.get(Calendar.MONTH) + 1; Integer yyyy = calendar.get(Calendar.YEAR); // Form the DDMMYY part of the ID. Assume that string manipulations are done. StringBuilder maskedValue = new StringBuilder(); maskedValue.append(dd).append(mm).append(yyyy).append("-"); String pg = getPlaceOfIssuanceAndNationality("Serekunda", "Mandinka"); maskedValue.append(pg).append("-"); // Gender comes from parm 2 and takes say, M | F | U String gender = (String) args[2]; Integer nn = getNN(gender); Integer checksum = getChecksum(dob, pg, gender); maskedValue.append(nn).append(checksum); return maskedValue.toString(); } private String getPlaceOfIssuanceAndNationality(String place, String nationality) { return "PG"; } private static Integer getNN(String gender) { // Assume proprietary code to generate nn based on gender Random random = new Random(); Integer nn = 0; nn = random.nextInt(100); if (0 == nn) { nn = 1; } if ("M".equalsIgnoreCase(gender)) { nn = nn % 2 != 0 ? nn : nn + 1; nn = nn == 99 ? nn - 2: nn; } else if ("F".equalsIgnoreCase(gender)) { nn = nn % 2 == 0 ? nn : nn + 1; } return nn; } private Integer getChecksum(Date dob, String pg, String gender) { // Assume proprietary code to generate checksum based on various factors // For this example we return 0 - 9 Random random = new Random(); return random.nextInt(10); } }
Example File
This example class does not use the args[1] to args[4] parameters.
package com.example; import java.util.ArrayList; import java.util.Collections; import java.util.List; import com.grid_tools.products.datamasker.IMaskFunction; /* A custom function with no parameters that masks the original value and appends a check digit */ public class MaskCheckDigit implements IMaskFunction { @Override public Object mask(Object... args) { // Get original value from args[0] String originalValue = (String) args[0]; if (null == originalValue) { return null; } // Proprietary validations and modifications if (originalValue.length() < 10) { return originalValue; } originalValue = originalValue.substring(0, 10); List<Integer> digits = new ArrayList<Integer>(); for (int i = 0; i < originalValue.length();i++) { if (Character.isDigit(originalValue.charAt(i))) { digits.add(i, Character.getNumericValue(originalValue.charAt(i))); } else { return originalValue; } } // Shuffle digits in original value Collections.shuffle(digits); // More proprietary code to generate check digit based on shuffled digits int[] multiplier = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 9 }; if (0 == digits.get(0)) { digits.set(0, multiplier[0]); } int checkDigit = 0; for (int i = 0; i < 10; i++) { checkDigit += (digits.get(i) * multiplier[i]); } checkDigit /= 10; checkDigit %= 10; StringBuilder maskedValue = new StringBuilder(); for (Integer i : digits) { maskedValue.append(i); } maskedValue.append(checkDigit); return maskedValue.toString(); } }
Configure Custom Functions
  1. Go to the FDM install folder.
    C:\Program Files\Grid-Tools\FastDataMasker
  2. Modify the provided example file
  3. Add a
    section for each custom function, and configure it.
    1. Define the name of the custom function and provide a description.
      This text appears on the masking definition screen in FDM for your users.
      • name
      • description
    2. Define labels for zero to four parameters. Leave unused
      elements empty.
      The labels appear on the masking definition screen in FDM for your users.
      • parm1
      • parm2
      • parm3
      • parm4
    1. Define to which data format the custom function can be applied.
      Examples: If you set the
      element to
      , the function masks character data. If you set the
      element to
      , the function cannot be applied to dates.
      • char
      • number
      • date
      • char_date
      • custom
    1. Provide the class path and class name of the custom function file that you placed in the "
      " folder.
      • class_name
  4. Save the configuration file.
  5. Start FDM.
The custom functions appear on the masking definition screen in FDM. You can now use them for masking.
Example File custom_config.xml (Template)
<?xml version="1.0" encoding="UTF-8"?> <configuration> <functions> <function> <name>CUSTOMFUNCTION</name> <description>CUSTOMFUNCTION - A custom function written by the user</description> <parm1>Field1</parm1> <parm2>Field2</parm2> <parm3>Field3</parm3> <parm4>Field4</parm4> <char>true</char> <number>true</number> <date>false</date> <char_date>false</char_date> <custom>true</custom> <class_name>com.example.CustomFunction</class_name> </function> </functions> </configuration>
Example File custom_config.xml with MaskCheckDigit and GambianID
<?xml version="1.0" encoding="UTF-8"?> <configuration> <functions> <function> <name>MASKCHECKDIGIT</name> <description>MASKCHECKDIGIT - A custom function with no parameters that masks the original value and appends a check digit.</description> <parm1></parm1> <parm2></parm2> <parm3></parm3> <parm4></parm4> <char>true</char> <number>true</number> <date>false</date> <char_date>false</char_date> <custom>true</custom> <class_name>com.example.MaskCheckDigit</class_name> </function> <function> <name>GAMBIANID</name> <description> GAMBIANID - A custom function with two parameters that masks the Gambian ID.</description> <parm1>Date of Birth (yyyy-MM-dd):</parm1> <parm2>Gender (M | F | U):</parm2> <parm3></parm3> <parm4></parm4> <char>true</char> <number>false</number> <date>false</date> <char_date>false</char_date> <custom>true</custom> <class_name>com.example.GambianID</class_name> </function> </functions> </configuration>