Custom Distributions
Goal
A Distribution function are defined for the dependent tables when creating data for foreign key columns. It determines the distribution of the foreign key values that will exist in the dependet table.
Place your custom Java function inside your root package/distributions
folder in the genereated project.
- The custom class must implement the IDistribution interface and override the distribute and calculateNewRows methods
Distribution Interface
public interface IDistribution {
int calculateNewRows(CreateParent[] parents, int numrows, List<String[]> existing) throws Exception;
void distribute(List<String> columns, CreateParent[] parents, List<String[]> rows) throws Exception;
}
Java Examples
- MinPerParent.java
- NullDistro,java
/**
* Simple distribution where it ensures a minimum occurrences of each parent
* when creating new records
*/
public class MinPerParent implements IDistribution {
public static final String LABEL =
"MinPerParent - Ensures a minimum number of occurrences of each parent value";
public static final String PARENT_LABEL= "Minimum #rows / parent";
int[] min;
@Override
public int calculateNewRows(CreateParent[] parents, int numExistRows, List<String[]> existing) {
min=new int[parents.length];
for (int i = 0; i < parents.length; i++) {
min[i]=Integer.valueOf(parents[i].params);
}
int x1 = 0;
for (int i = 0; i < parents.length; i++) {
CreateParent ct = parents[i];
int dmin = 0;
for (int j : ct.count) {
dmin += Math.max(min[i] - j, 0);
}
x1 = Math.max(x1,dmin );
}
return x1;
}
@Override
public void distribute(List<String> columns, CreateParent[] parents, List<String[]> rows) {
for (int i = 0; i < parents.length; i++) {
CreateParent parent = parents[i];
int irow = 0;
int[] a = parent.count;
for (int icol = 0; icol < a.length; icol++) {
for (int j = a[icol]; j < min[i]; j++) {
if (irow >= rows.size())
break;
IDistribution.assignRow(parent, columns, rows.get(irow++), icol);
}
}
int icol = 0;
int size = parent.parentRows.size();
while (size > 0 && irow < rows.size()) {
IDistribution.assignRow(parent, columns, rows.get(irow++), icol++);
if (icol >= size)
icol = 0;
}
}
}
}
/**
* Sample distribution to randomly assign foreign keys with chance of setting null
*/
public class NullDistro extends AbstractRandom implements IDistribution {
public static final String LABEL = "DistroWithNullValues";
public static final String MAIN_LABEL= "Allow orphans";
public static final String PARENT_LABEL= "% Chance of null value";
private boolean allowOrphans;
private Random random;
public NullDistro(boolean allowOrphans) { // MAIN_LABEL parameter
this.allowOrphans=allowOrphans;
}
@Override
public int calculateNewRows(CreateParent[] parents, int numExistRows, List<String[]> existing) {
return 0;
}
@Override
public void distribute(List<String> columns, CreateParent[] parents, List<String[]> rows) {
for (String[] row : rows) {
boolean orphan = true;
do {
for (CreateParent parent : parents) {
int chance=Integer.parseInt(parent.params); // PARENT_LABEL ( % null)
if(random.nextInt(100) >= chance) { // assign if random gives a roll higher
randomAssignColumn(columns, row, parent); // helper method in AbstractRandom
orphan=false;
}
}
} while (orphan && !allowOrphans); // Continue running until not orphan
}
}
@Override
public void setRandom(Random random) {
this.random = random;
}
@Override
public Random getRandom() {
return random;
}
}
ANO Usage Examples
- You must explicitly import Transformation functions before the Tasks and Rules Section
- MinPerParent in ANO
- NullDistro in ANO
distribution example.anonymizer.distributions.MinPerParent
task <task-name> {
create Booking minimum-rows 100
distribute MinPerParent
table Customer
child customer_customerNo
parent customerNo
table Hotel
child hotel_id
parent id
table RoomCategory
child roomCategory_id
parent id
}
distribution example.anonymizer.distributions.NullDistro
task <task-name> {
create Booking minimum-rows 100
distribute NullDistro
table Customer
child customer_customerNo
parent customerNo
table Hotel
child hotel_id
parent id
table RoomCategory
child roomCategory_id
parent id
}