/*
* 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.gui.view.impl.wizard;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import org.deidentifier.arx.AttributeType.Hierarchy;
import org.deidentifier.arx.DataType;
import org.deidentifier.arx.DataType.ARXOrderedString;
import org.deidentifier.arx.DataType.DataTypeWithRatioScale;
import org.deidentifier.arx.aggregates.HierarchyBuilder;
import org.deidentifier.arx.aggregates.HierarchyBuilder.Type;
import org.deidentifier.arx.aggregates.HierarchyBuilderIntervalBased;
import org.deidentifier.arx.aggregates.HierarchyBuilderOrderBased;
import org.deidentifier.arx.gui.resources.Resources;
/**
* The base model for the wizard.
*
* @author Fabian Prasser
* @param <T>
*/
public class HierarchyWizardModel<T> {
/** Var. */
private Type type;
/** Var. */
private HierarchyWizardModelOrder<T> orderModel;
/** Var. */
private HierarchyWizardModelIntervals<T> intervalModel;
/** Var. */
private HierarchyWizardModelRedaction<T> redactionModel;
/** Var. */
private final DataType<T> dataType;
/** Var. */
private final String[] data;
/**
* Creates a new instance for the given data type.
*
* @param dataType
* @param locale
* @param data
*/
public HierarchyWizardModel(DataType<T> dataType, Locale locale, String[] data){
// Store
this.data = data;
this.dataType = dataType;
// Sort input data
this.sort(this.getDataType());
// Create models
orderModel = new HierarchyWizardModelOrder<T>(dataType, locale, getOrderData());
if (dataType instanceof DataTypeWithRatioScale){
if (data.length > 1 || data[0] != DataType.NULL_VALUE) {
intervalModel = new HierarchyWizardModelIntervals<T>(dataType, data);
}
}
redactionModel = new HierarchyWizardModelRedaction<T>(dataType, data);
// Propose a dedicated type of builder
if (equals(dataType, DataType.DATE)) {
this.type = intervalModel != null ? Type.INTERVAL_BASED : Type.ORDER_BASED;
} else if (equals(dataType, DataType.DECIMAL)) {
this.type = intervalModel != null ? Type.INTERVAL_BASED : Type.ORDER_BASED;
} else if (equals(dataType, DataType.INTEGER)) {
this.type = intervalModel != null ? Type.INTERVAL_BASED : Type.ORDER_BASED;
} else if (equals(dataType, DataType.ORDERED_STRING)) {
this.type = Type.ORDER_BASED;
} else if (equals(dataType, DataType.STRING)) {
this.type = Type.REDACTION_BASED;
}
}
/**
* Returns the current builder.
*
* @param serializable
* @return
* @throws Exception
*/
public HierarchyBuilder<T> getBuilder(boolean serializable) throws Exception {
if (type == Type.INTERVAL_BASED) {
return intervalModel.getBuilder(serializable);
} else if (type == Type.REDACTION_BASED) {
return redactionModel.getBuilder(serializable);
} else if (type == Type.ORDER_BASED) {
return orderModel.getBuilder(serializable);
} else {
throw new IllegalArgumentException(Resources.getMessage("HierarchyWizardModel.0")); //$NON-NLS-1$
}
}
/**
* Returns the data type.
*
* @return
*/
public DataType<T> getDataType() {
return this.dataType;
}
/**
* Returns the current hierarchy.
*
* @return
*/
public Hierarchy getHierarchy() {
if (type == Type.INTERVAL_BASED) {
return intervalModel.getHierarchy();
} else if (type == Type.REDACTION_BASED) {
return redactionModel.getHierarchy();
} else if (type == Type.ORDER_BASED) {
return orderModel.getHierarchy();
} else {
throw new RuntimeException(Resources.getMessage("HierarchyWizardModel.1")); //$NON-NLS-1$
}
}
/**
* Returns the model of the interval-based builder.
*
* @return
*/
public HierarchyWizardModelIntervals<T> getIntervalModel() {
return intervalModel;
}
/**
* Returns the model of the order-based builder.
*
* @return
*/
public HierarchyWizardModelOrder<T> getOrderModel() {
return orderModel;
}
/**
* Returns the model of the redaction-based builder.
*
* @return
*/
public HierarchyWizardModelRedaction<T> getRedactionModel() {
return redactionModel;
}
/**
* Returns the type.
*
* @return
*/
public Type getType(){
return this.type;
}
/**
* Updates the model with a new specification.
*
* @param builder
* @throws IllegalArgumentException
*/
public void parse(HierarchyBuilder<T> builder) throws IllegalArgumentException{
if (builder.getType() == Type.INTERVAL_BASED) {
if (intervalModel != null){
this.intervalModel.parse((HierarchyBuilderIntervalBased<T>)builder);
this.type = Type.INTERVAL_BASED;
}
} else if (builder.getType() == Type.ORDER_BASED) {
this.orderModel.parse((HierarchyBuilderOrderBased<T>)builder);
this.type = Type.ORDER_BASED;
} else if (builder.getType() == Type.REDACTION_BASED) {
this.redactionModel.parse(builder);
this.type = Type.REDACTION_BASED;
} else {
throw new IllegalArgumentException(Resources.getMessage("HierarchyWizardModel.2")); //$NON-NLS-1$
}
}
/**
* Sets the type.
*
* @param type
*/
public void setType(Type type){
if (type != this.type) {
this.type = type;
}
}
/**
* Simple comparison of data types.
*
* @param type
* @param other
* @return
*/
private boolean equals(DataType<?> type, DataType<?> other){
return type.getDescription().getLabel().equals(other.getDescription().getLabel());
}
/**
* Returns data for the order-based builder.
*
* @return
*/
private String[] getOrderData(){
if (dataType instanceof ARXOrderedString){
ARXOrderedString os = (ARXOrderedString)dataType;
List<String> elements = os.getElements();
if (elements != null && !elements.isEmpty()) {
return elements.toArray(new String[elements.size()]);
}
}
return data;
}
/**
* Sort.
*
* @param <U>
* @param type
* @return successful, or not
*/
protected <U> boolean sort(final DataType<U> type) {
try {
Arrays.sort(this.data, new Comparator<String>(){
@Override public int compare(String o1, String o2) {
try {
return type.compare(o1, o2);
} catch (NumberFormatException | ParseException e) {
throw new RuntimeException(e);
}
}
});
return true;
} catch (Exception e) {
return false;
}
}
}