/*
* ARX: Powerful Data Anonymization
* Copyright 2012 - 2017 Fabian Prasser, Florian Kohlmayer and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.deidentifier.arx.framework.check.transformer;
import java.util.concurrent.Callable;
import org.deidentifier.arx.ARXConfiguration;
import org.deidentifier.arx.ARXConfiguration.ARXConfigurationInternal;
import org.deidentifier.arx.framework.check.StateMachine.TransitionType;
import org.deidentifier.arx.framework.check.distribution.IntArrayDictionary;
import org.deidentifier.arx.framework.check.groupify.HashGroupifyEntry;
import org.deidentifier.arx.framework.check.groupify.HashGroupify;
import org.deidentifier.arx.framework.data.GeneralizationHierarchy;
/**
* This class implements an abstract base class for all transformers.
*
* @author Fabian Prasser
* @author Florian Kohlmayer
*/
public abstract class AbstractTransformer implements Callable<HashGroupify> {
/**
* Implementation of the delegate for Requirements.COUNTER
* @author Kohlmayer, Prasser
*/
protected final class GroupifyCounter implements IGroupify {
@Override
public final void callAll(final int[] outtuple, final int i) {
groupify.addFromBuffer(outtuple, null, i, 1, -1);
}
@Override
public final void callGroupify(final int[] outtuple, final HashGroupifyEntry element) {
groupify.addFromGroupify(outtuple, null, element.representative, element.count, -1);
}
@Override
public final void callSnapshot(final int[] outtuple, final int[] snapshot, final int i) {
groupify.addFromSnapshot(outtuple, null, null, snapshot[i], snapshot[i + 1], -1);
}
}
/**
* Implementation of the delegate for Requirements.COUNTER | Requirements.DISTRIBUTION
* @author Kohlmayer, Prasser
*/
protected final class GroupifyCounterDistribution implements IGroupify {
@Override
public final void callAll(final int[] outtuple, final int i) {
groupify.addFromBuffer(outtuple, otherData[i], i, 1, -1);
}
@Override
public final void callGroupify(final int[] outtuple, final HashGroupifyEntry element) {
groupify.addFromGroupify(outtuple, element.distributions, element.representative, element.count, -1);
}
@Override
public final void callSnapshot(final int[] outtuple, final int[] snapshot, final int i) {
// TODO: Improve!
int[][] values = new int[otherData[0].length][];
int[][] frequencies = new int[otherData[0].length][];
int index = 0;
int offset = i + 2;
int length = config.getSnapshotLength() - 1 - 2;
for (int j = offset; j < offset + length; j += 2) {
values[index] = dictionarySensValue.get(snapshot[j]);
frequencies[index++] = dictionarySensFreq.get(snapshot[j + 1]);
}
groupify.addFromSnapshot(outtuple, values, frequencies, snapshot[i], snapshot[i + 1], -1);
}
}
/**
* Implementation of the delegate for Requirements.COUNTER | Requirements.SECONDARY_COUNTER
* @author Kohlmayer, Prasser
*/
protected final class GroupifyCounterSecondaryCounter implements IGroupify {
@Override
public final void callAll(final int[] outtuple, final int i) {
groupify.addFromBuffer(outtuple, null, i, 1, 1);
}
@Override
public final void callGroupify(final int[] outtuple, final HashGroupifyEntry element) {
groupify.addFromGroupify(outtuple, null, element.representative, element.count, element.pcount);
}
@Override
public final void callSnapshot(final int[] outtuple, final int[] snapshot, final int i) {
groupify.addFromSnapshot(outtuple, null, null, snapshot[i], snapshot[i + 1], snapshot[i + 2]);
}
}
/**
* Implementation of the delegate for Requirements.COUNTER | Requirements.SECONDARY_COUNTER | Requirements.DISTRIBUTION
* @author Kohlmayer, Prasser
*/
protected final class GroupifyCounterSecondaryCounterDistribution implements IGroupify {
@Override
public final void callAll(final int[] outtuple, final int i) {
groupify.addFromBuffer(outtuple, otherData[i], i, 1, 1);
}
@Override
public final void callGroupify(final int[] outtuple, final HashGroupifyEntry element) {
groupify.addFromGroupify(outtuple, element.distributions, element.representative, element.count, element.pcount);
}
@Override
public final void callSnapshot(final int[] outtuple, final int[] snapshot, final int i) {
// TODO: Improve!
int[][] values = new int[otherData[0].length][];
int[][] frequencies = new int[otherData[0].length][];
int index = 0;
int offset = i + 3;
int length = config.getSnapshotLength() - 1 - 3;
for (int j = offset; j < offset + length; j += 2) {
values[index] = dictionarySensValue.get(snapshot[j]);
frequencies[index++] = dictionarySensFreq.get(snapshot[j + 1]);
}
groupify.addFromSnapshot(outtuple, values, frequencies, snapshot[i], snapshot[i + 1], snapshot[i + 2]);
}
}
/**
* Implementation of the delegate for Requirements.DISTRIBUTION
* @author Kohlmayer, Prasser
*/
protected final class GroupifyDistribution implements IGroupify {
@Override
public final void callAll(final int[] outtuple, final int i) {
groupify.addFromBuffer(outtuple, otherData[i], i, 1, -1);
}
@Override
public final void callGroupify(final int[] outtuple, final HashGroupifyEntry element) {
groupify.addFromGroupify(outtuple, element.distributions, element.representative, element.count, -1);
}
@Override
public final void callSnapshot(final int[] outtuple, final int[] snapshot, final int i) {
// TODO: Improve!
int[][] values = new int[otherData[0].length][];
int[][] frequencies = new int[otherData[0].length][];
int index = 0;
int offset = i + 2;
int length = config.getSnapshotLength() - 1 - 2;
for (int j = offset; j < offset + length; j += 2) {
values[index] = dictionarySensValue.get(snapshot[j]);
frequencies[index++] = dictionarySensFreq.get(snapshot[j + 1]);
}
groupify.addFromSnapshot(outtuple, values, frequencies, snapshot[i], snapshot[i + 1], -1);
}
}
/**
* Interface for delegates to the groupify .
*
* @author Kohlmayer, Prasser
*/
protected interface IGroupify {
/**
* Mode ALL.
*
* @param outtuple
* @param i
*/
public abstract void callAll(final int[] outtuple, final int i);
/**
* Mode GROUPIFY.
*
* @param outtuple
* @param element
*/
public abstract void callGroupify(final int[] outtuple, final HashGroupifyEntry element);
/**
* Mode SNAPSHOT.
*
* @param outtuple
* @param snapshot
* @param i
*/
public abstract void callSnapshot(final int[] outtuple, final int[] snapshot, final int i);
}
/** The hash groupify. */
private HashGroupify groupify;
/** The bucket. */
protected int bucket;
/** The buffer. */
protected int[][] buffer;
/** The column index array. */
protected final int[] columnIndexArray;
/** The column map array. */
protected final int[][][] columnMapArray;
/** The mode of operation *. */
protected final ARXConfigurationInternal config;
/** The data. */
protected final int[][] data;
/** The delegate. */
protected final IGroupify delegate;
/** The dictionary for the snapshot compression *. */
protected final IntArrayDictionary dictionarySensFreq;
/** The dictionary for the snapshot compression *. */
protected final IntArrayDictionary dictionarySensValue;
/** The dimensions. */
protected final int dimensions;
/** The element. */
protected HashGroupifyEntry element;
/** The groupify array. */
protected HashGroupifyEntry[] groupifyArray;
/** The hierarchies. */
protected final GeneralizationHierarchy[] hierarchies;
/** The idindex14. */
protected int[][] idindex0, idindex1, idindex2, idindex3, idindex4, idindex5,
idindex6, idindex7, idindex8, idindex9, idindex10, idindex11, idindex12, idindex13, idindex14;
/** The index14. */
protected int index0, index1, index2, index3, index4, index5, index6, index7,
index8, index9, index10, index11, index12, index13, index14;
/** The intuple. */
protected int[] intuple;
/** The generalization hierarchies. */
protected int[][][] map;
/** The outindices. */
protected int outindex0;
/** The outindices. */
protected int outindex1;
/** The outindices. */
protected int outindex10;
/** The outindices. */
protected int outindex11;
/** The outindices. */
protected int outindex12;
/** The outindices. */
protected int outindex13;
/** The outindices. */
protected int outindex14;
/** The outindices. */
protected int outindex2;
/** The outindices. */
protected int outindex3;
/** The outindices. */
protected int outindex4;
/** The outindices. */
protected int outindex5;
/** The outindices. */
protected int outindex6;
/** The outindices. */
protected int outindex7;
/** The outindices. */
protected int outindex8;
/** The outindices. */
protected int outindex9;
/** The outtuple. */
protected int[] outtuple;
/** The sensitive values. */
protected final int[][] otherData;
/** The snapshot. */
protected int[] snapshot;
/** The size of one snapshopt entry *. */
protected final int ssStepWidth;
/** The start index. */
protected int startIndex;
/** The stateindices. */
protected int generalizationindex0;
/** The stateindices. */
protected int generalizationindex1;
/** The stateindices. */
protected int generalizationindex10;
/** The stateindices. */
protected int generalizationindex11;
/** The stateindices. */
protected int generalizationindex12;
/** The stateindices. */
protected int generalizationindex13;
/** The stateindices. */
protected int generalizationindex14;
/** The stateindices. */
protected int generalizationindex2;
/** The stateindices. */
protected int generalizationindex3;
/** The stateindices. */
protected int generalizationindex4;
/** The stateindices. */
protected int generalizationindex5;
/** The stateindices. */
protected int generalizationindex6;
/** The stateindices. */
protected int generalizationindex7;
/** The stateindices. */
protected int generalizationindex8;
/** The stateindices. */
protected int generalizationindex9;
/** The state index array. */
protected final int[] generalizationIndexArray;
/** The states. */
protected int[] generalization;
/** The stop index. */
protected int stopIndex;
/** The transition. */
protected TransitionType transition;
/**
* Instantiates a new abstract transformer.
*
* @param data the data
* @param hierarchies the hierarchies
* @param otherData
* @param dictionarySensValue
* @param dictionarySensFreq
* @param config
*/
public AbstractTransformer(final int[][] data,
final GeneralizationHierarchy[] hierarchies,
final int[][] otherData,
final IntArrayDictionary dictionarySensValue,
final IntArrayDictionary dictionarySensFreq,
final ARXConfigurationInternal config) {
this.config = config;
this.data = data;
this.hierarchies = hierarchies;
this.otherData = otherData;
this.dictionarySensValue = dictionarySensValue;
this.dictionarySensFreq = dictionarySensFreq;
this.ssStepWidth = config.getSnapshotLength();
// Init arrays
this.dimensions = data[0].length;
int arraySizes = 15;
if (this.dimensions > arraySizes) {
arraySizes = this.dimensions;
}
generalizationIndexArray = new int[arraySizes];
columnIndexArray = new int[arraySizes];
columnMapArray = new int[arraySizes][][];
map = new int[hierarchies.length][][];
for (int i = 0; i < hierarchies.length; i++) {
map[i] = hierarchies[i].getArray();
}
// Prepare delegate
switch (config.getRequirements()) {
case ARXConfiguration.REQUIREMENT_COUNTER:
delegate = new GroupifyCounter();
break;
case ARXConfiguration.REQUIREMENT_COUNTER | ARXConfiguration.REQUIREMENT_SECONDARY_COUNTER:
delegate = new GroupifyCounterSecondaryCounter();
break;
case ARXConfiguration.REQUIREMENT_COUNTER | ARXConfiguration.REQUIREMENT_SECONDARY_COUNTER | ARXConfiguration.REQUIREMENT_DISTRIBUTION:
delegate = new GroupifyCounterSecondaryCounterDistribution();
break;
case ARXConfiguration.REQUIREMENT_COUNTER | ARXConfiguration.REQUIREMENT_DISTRIBUTION:
delegate = new GroupifyCounterDistribution();
break;
case ARXConfiguration.REQUIREMENT_DISTRIBUTION:
delegate = new GroupifyDistribution();
break;
default:
RuntimeException e = new RuntimeException("Invalid requirements: " + config.getRequirements());
throw(e);
}
}
/*
* (non-Javadoc)
*
* @see java.util.concurrent.Callable#call()
*/
@Override
public HashGroupify call() {
// clear local groupify
groupify.stateClear();
switch (transition) {
case UNOPTIMIZED:
processAll();
break;
case ROLLUP:
processGroupify();
break;
case SNAPSHOT:
processSnapshot();
break;
default:
break;
}
return groupify;
}
/**
* Inits the.
*
* @param projection
* the projection
* @param state
* the state
* @param groupify
* the groupify
* @param source
* the source
* @param snapshot
* the snapshot
* @param transition
* the transition
* @param startIndex
* the start index
* @param stopIndex
* the stop index
* @param bucket
* the bucket
* @param element
* the element
* @param buffer
* the buffer
*/
public void init(final long projection,
final int[] state,
final HashGroupify groupify,
final HashGroupify source,
final int[] snapshot,
final TransitionType transition,
final int startIndex,
final int stopIndex,
final int bucket,
final HashGroupifyEntry element,
final int[][] buffer) {
this.buffer = buffer;
this.startIndex = startIndex;
this.stopIndex = stopIndex;
this.element = element;
this.bucket = bucket;
this.generalization = state;
this.transition = transition;
int index = 0;
for (int i = 0; i < dimensions; i++) {
if ((projection & (1L << i)) == 0) {
generalizationIndexArray[index] = state[i];
columnIndexArray[index] = i;
columnMapArray[index] = hierarchies[i].getArray();
index++;
}
}
// Store groupify
this.groupify = groupify;
// this.groupify.clear();
// Store snapshot
this.snapshot = snapshot;
// Store values
index0 = columnIndexArray[0];
index1 = columnIndexArray[1];
index2 = columnIndexArray[2];
index3 = columnIndexArray[3];
index4 = columnIndexArray[4];
index5 = columnIndexArray[5];
index6 = columnIndexArray[6];
index7 = columnIndexArray[7];
index8 = columnIndexArray[8];
index9 = columnIndexArray[9];
index10 = columnIndexArray[10];
index11 = columnIndexArray[11];
index12 = columnIndexArray[12];
index13 = columnIndexArray[13];
index14 = columnIndexArray[14];
// Store values
outindex0 = columnIndexArray[0];
outindex1 = columnIndexArray[1];
outindex2 = columnIndexArray[2];
outindex3 = columnIndexArray[3];
outindex4 = columnIndexArray[4];
outindex5 = columnIndexArray[5];
outindex6 = columnIndexArray[6];
outindex7 = columnIndexArray[7];
outindex8 = columnIndexArray[8];
outindex9 = columnIndexArray[9];
outindex10 = columnIndexArray[10];
outindex11 = columnIndexArray[11];
outindex12 = columnIndexArray[12];
outindex13 = columnIndexArray[13];
outindex14 = columnIndexArray[14];
// Store values
generalizationindex0 = generalizationIndexArray[0];
generalizationindex1 = generalizationIndexArray[1];
generalizationindex2 = generalizationIndexArray[2];
generalizationindex3 = generalizationIndexArray[3];
generalizationindex4 = generalizationIndexArray[4];
generalizationindex5 = generalizationIndexArray[5];
generalizationindex6 = generalizationIndexArray[6];
generalizationindex7 = generalizationIndexArray[7];
generalizationindex8 = generalizationIndexArray[8];
generalizationindex9 = generalizationIndexArray[9];
generalizationindex10 = generalizationIndexArray[10];
generalizationindex11 = generalizationIndexArray[11];
generalizationindex12 = generalizationIndexArray[12];
generalizationindex13 = generalizationIndexArray[13];
generalizationindex14 = generalizationIndexArray[14];
// Store values
idindex0 = columnMapArray[0];
idindex1 = columnMapArray[1];
idindex2 = columnMapArray[2];
idindex3 = columnMapArray[3];
idindex4 = columnMapArray[4];
idindex5 = columnMapArray[5];
idindex6 = columnMapArray[6];
idindex7 = columnMapArray[7];
idindex8 = columnMapArray[8];
idindex9 = columnMapArray[9];
idindex10 = columnMapArray[10];
idindex11 = columnMapArray[11];
idindex12 = columnMapArray[12];
idindex13 = columnMapArray[13];
idindex14 = columnMapArray[14];
}
/**
* Update out indices.
*
* @param activecolumns
* the activecolumns
* @param projection
* the projection
*/
public void updateOutIndices(final int[] activecolumns, final long projection) {
// Make sure all 15 indices are set
final int[] outindices2 = new int[15];
int outcount = 0;
for (int i = 0; i < activecolumns.length; i++) {
if ((projection & (1L << activecolumns[i])) == 0) {
outindices2[outcount++] = i;
}
}
// Copy
outindex0 = outindices2[0];
outindex1 = outindices2[1];
outindex2 = outindices2[2];
outindex3 = outindices2[3];
outindex4 = outindices2[4];
outindex5 = outindices2[5];
outindex6 = outindices2[6];
outindex7 = outindices2[7];
outindex8 = outindices2[8];
outindex9 = outindices2[9];
outindex10 = outindices2[10];
outindex11 = outindices2[11];
outindex12 = outindices2[12];
outindex13 = outindices2[13];
outindex14 = outindices2[14];
}
/**
* Process complete input dataset.
*/
protected abstract void processAll();
/**
* Process groupify.
*/
protected abstract void processGroupify();
/**
* Process snapshot.
*/
protected abstract void processSnapshot();
}