/* * 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; import java.io.Serializable; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * This class encapsulates a generalization scheme * @author Fabian Prasser */ public class DataGeneralizationScheme implements Serializable, Cloneable { /** * A specific generalization degree * @author Fabian Prasser * */ public static enum GeneralizationDegree implements Serializable { NONE(0d), LOW(0.2d), LOW_MEDIUM(0.4d), MEDIUM(0.5d), MEDIUM_HIGH(0.6d), HIGH(0.8d), COMPLETE(1d); /** Factor*/ private final double factor; /** * Constructor * @param factor */ private GeneralizationDegree(double factor) { this.factor = factor; } /** * Returns the factor * @return */ protected double getFactor() { return this.factor; } } /** SVUID*/ private static final long serialVersionUID = -5402090022629905154L; /** * Creates a new data generalization scheme * @return */ public static DataGeneralizationScheme create() { return new DataGeneralizationScheme(null, null); } /** * Creates a new data generalization scheme * @param data * @return */ public static DataGeneralizationScheme create(Data data) { return new DataGeneralizationScheme(data, null); } /** * Creates a new data generalization scheme * @param data * @param degree * @return */ public static DataGeneralizationScheme create(Data data, GeneralizationDegree degree) { return new DataGeneralizationScheme(data, degree); } /** * Creates a new data generalization scheme * @param degree * @return */ public static DataGeneralizationScheme create(GeneralizationDegree degree) { return new DataGeneralizationScheme(null, degree); } /** Degrees */ private Map<String, GeneralizationDegree> degrees = new HashMap<String, GeneralizationDegree>(); /** Levels */ private Map<String, Integer> levels = new HashMap<String, Integer>(); /** Degree */ private GeneralizationDegree degree = null; /** Data */ private Set<String> attributes; /** * Creates a new instance * @param data * @param degree */ private DataGeneralizationScheme(Data data, GeneralizationDegree degree) { if (data != null) { this.attributes = new HashSet<String>(); for (int i=0; i<data.getHandle().getNumColumns(); i++) { this.attributes.add(data.getHandle().getAttributeName(i)); } } else { this.attributes = null; } this.degree = degree; } /** * Clone method */ public DataGeneralizationScheme clone() { DataGeneralizationScheme result = new DataGeneralizationScheme(null, null); result.degrees = new HashMap<String, GeneralizationDegree>(this.degrees); result.degree = this.degree; result.levels = new HashMap<String, Integer>(this.levels); result.attributes = this.attributes != null ? new HashSet<String>(this.attributes) : null; return result; } /** * Defines a specific generalization degree * @param degree * @return */ public DataGeneralizationScheme generalize(GeneralizationDegree degree) { this.degree = degree; return this; } /** * Defines a specific generalization degree * @param attribute * @param degree * @return */ public DataGeneralizationScheme generalize(String attribute, GeneralizationDegree degree) { check(attribute); this.degrees.put(attribute, degree); return this; } /** * Defines a specific generalization level * @param attribute * @param level * @return */ public DataGeneralizationScheme generalize(String attribute, int level) { check(attribute); if (level < 0) { throw new IllegalArgumentException("Invalid generalization level: " + level); } this.levels.put(attribute, level); return this; } /** * Returns the overall generalization degree, if any * @return */ public GeneralizationDegree getGeneralizationDegree() { return this.degree; } /** * Returns a generalization level as defined by this class * @param attribute * @param definition * @return */ public int getGeneralizationLevel(String attribute, DataDefinition definition) { int result = 0; if (definition.isHierarchyAvailable(attribute)) { if (this.levels.containsKey(attribute)) { result = this.levels.get(attribute); } else if (this.degrees.containsKey(attribute)) { result = (int) Math.round( (this.degrees.get(attribute).getFactor() * (double) definition.getMaximumGeneralization(attribute))); } else if (this.degree != null) { result = (int) Math.round(this.degree.getFactor() * (double) definition.getMaximumGeneralization(attribute)); } } result = Math.max(result, definition.getMinimumGeneralization(attribute)); result = Math.min(result, definition.getMaximumGeneralization(attribute)); return result; } /** * Checks the given attribute * @param attribute */ private void check(String attribute) { if (attributes != null && !attributes.contains(attribute)) { throw new IllegalArgumentException("Unknown attribute: " + attribute); } } }