/*
* 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.data;
import com.carrotsearch.hppc.ObjectIntOpenHashMap;
/**
* A dictionary mapping integers to strings for different dimensions.
*
* @author Fabian Prasser
* @author Florian Kohlmayer
*/
public class Dictionary {
/** The resulting array mapping dimension->integer->string. */
private final String[][] mapping;
/** Map used when building the dictionary. */
private ObjectIntOpenHashMap<String>[] maps;
/**
* Instantiates a new dictionary.
*
* @param dimensions
* the dimensions
*/
@SuppressWarnings("unchecked")
public Dictionary(final int dimensions) {
maps = new ObjectIntOpenHashMap[dimensions];
mapping = new String[dimensions][];
for (int i = 0; i < dimensions; i++) {
maps[i] = new ObjectIntOpenHashMap<String>();
}
}
/**
* Definalizes the dictionary
*/
@SuppressWarnings("unchecked")
public void definalizeAll() {
// Re-instantiate maps
maps = new ObjectIntOpenHashMap[mapping.length];
for (int i = 0; i < maps.length; i++) {
maps[i] = new ObjectIntOpenHashMap<String>();
}
// Add from mapping
for (int i = 0; i < mapping.length; i++) {
if (mapping[i] != null) {
for (int j = 0; j < mapping[i].length; j++) {
maps[i].put(mapping[i][j], j);
}
}
}
// Remove mapping
for (int i = 0; i < mapping.length; i++) {
mapping[i] = null;
}
}
/**
* Finalizes all dimensions.
*/
public void finalizeAll() {
for (int i = 0; i < maps.length; i++) {
mapping[i] = new String[maps[i].size()];
final Object[] keys = maps[i].keys;
final int[] values = maps[i].values;
final boolean[] allocated = maps[i].allocated;
for (int j = 0; j < allocated.length; j++) {
if (allocated[j]) {
mapping[i][values[j]] = (String) keys[j];
}
}
}
maps = null;
}
/**
* Returns the mapping array.
*
* @return
*/
public String[][] getMapping() {
return mapping;
}
/**
* Returns the number of dimensions in the dictionary.
*
* @return
*/
public int getNumDimensions() {
return mapping.length;
}
/**
* Returns the number of unique values contained before finalizing the
* dictionary.
*
* @param dimension
* @return
*/
public int getNumUniqueUnfinalizedValues(final int dimension) {
return maps[dimension].size();
}
/**
* Returns the registered value if present, null otherwise.
*
* @param dimension
* @param string
* @return
*/
public Integer probe(final int dimension, final String string) {
if (maps[dimension].containsKey(string)) {
return maps[dimension].lget();
} else {
return null;
}
// return maps[dimension].get(string);
}
/**
* Registers a new string at the dictionary.
*
* @param dimension
* the dimension
* @param string
* the string
* @return the int
*/
public int register(final int dimension, final String string) {
// Prepare
ObjectIntOpenHashMap<String> map = maps[dimension];
int size = map.size();
// Return or store
if (map.putIfAbsent(string, size)) {
return size;
} else {
return map.lget();
}
}
/**
* Merges this dictionary with another dictionary.
*
* @param targetDimension
* @param dictionary
* @param sourceDimension
*/
public void registerAll(final int targetDimension,
final Dictionary dictionary,
final int sourceDimension) {
final String[] vals = dictionary.mapping[sourceDimension];
for (int id = 0; id < vals.length; id++) {
maps[targetDimension].put(vals[id], id);
}
}
}