/* * 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(); }