/* * 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.define; import java.util.List; import org.deidentifier.arx.gui.Controller; import org.deidentifier.arx.gui.model.Model; import org.deidentifier.arx.gui.model.ModelEvent; import org.deidentifier.arx.gui.model.ModelEvent.ModelPart; import org.deidentifier.arx.gui.resources.Resources; import org.deidentifier.arx.gui.view.SWTUtil; import org.deidentifier.arx.gui.view.def.IView; import org.deidentifier.arx.metric.Metric; import org.deidentifier.arx.metric.Metric.AggregateFunction; import org.deidentifier.arx.metric.MetricConfiguration; import org.deidentifier.arx.metric.MetricDescription; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; /** * This view displays settings regarding the utility metrics. * * @author Fabian Prasser */ public class ViewUtilityMeasures implements IView { /** Static settings. */ private static final int LABEL_HEIGHT = 20; /** Static settings. */ private static final List<MetricDescription> METRICS = Metric.list(); /** Static settings. */ private static final String[] LABELS = getLabels(METRICS); /** * Returns a list of names of all available metrics. * * @param metrics * @return */ private static String[] getLabels(List<MetricDescription> metrics) { String[] labels = new String[metrics.size()]; for (int i = 0; i < metrics.size(); i++) { labels[i] = metrics.get(i).getName(); } return labels; } /** Controller. */ private final Controller controller; /** Model. */ private Model model; /** View. */ private Combo comboMetric; /** View. */ private Composite root; /** View. */ private Button monotonicVariant; /** View. */ private Combo comboMicroaggregation; /** View. */ private Combo comboAggregate; /** * Creates a new instance. * * @param parent * @param controller * @param folder */ public ViewUtilityMeasures(final Composite parent, final Controller controller) { this.controller = controller; this.controller.addListener(ModelPart.MODEL, this); this.controller.addListener(ModelPart.METRIC, this); this.root = build(parent); } @Override public void dispose() { controller.removeListener(this); } @Override public void reset() { comboMetric.select(0); comboMicroaggregation.select(0); monotonicVariant.setSelection(false); SWTUtil.disable(root); } @Override public void update(final ModelEvent event) { if (event.part == ModelPart.MODEL) { model = (Model) event.data; // Ensure backwards compatibility with older project files Metric<?> metric = model.getInputConfig().getMetric(); if (metric != null) { for (int i = 0; i < METRICS.size(); i++) { if (METRICS.get(i).isInstance(metric)) { comboMetric.select(i); break; } } } updateControls(); } if (event.part == ModelPart.INPUT || event.part == ModelPart.METRIC) { updateControls(); } } /** * Builds the component * @param parent * @return */ private Composite build(final Composite parent) { final Composite mBase = new Composite(parent, SWT.NONE); mBase.setLayout(GridLayoutFactory.swtDefaults().numColumns(4).create()); // Create metric combo final Label mLabel = new Label(mBase, SWT.PUSH); mLabel.setText(Resources.getMessage("CriterionDefinitionView.32")); //$NON-NLS-1$ GridData d2 = new GridData(); d2.heightHint = LABEL_HEIGHT; d2.minimumHeight = LABEL_HEIGHT; d2.grabExcessVerticalSpace = true; d2.verticalAlignment = GridData.CENTER; mLabel.setLayoutData(d2); comboMetric = new Combo(mBase, SWT.READ_ONLY); GridData d30 = SWTUtil.createFillHorizontallyGridData(); d30.horizontalSpan = 3; d30.verticalAlignment = GridData.CENTER; d30.grabExcessVerticalSpace = true; comboMetric.setLayoutData(d30); comboMetric.setItems(LABELS); comboMetric.select(0); comboMetric.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent arg0) { if (comboMetric.getSelectionIndex() != -1) { MetricDescription metric = METRICS.get(comboMetric.getSelectionIndex()); if (metric != null && model != null) { model.setMetricDescription(metric); controller.update(new ModelEvent(this, ModelPart.METRIC, model.getMetricDescription())); updateControls(); } } } }); // Create monotonicity button final Label mLabel2 = new Label(mBase, SWT.PUSH); mLabel2.setText(Resources.getMessage("CriterionDefinitionView.67")); //$NON-NLS-1$ GridData d22 = new GridData(); d22.heightHint = LABEL_HEIGHT; d22.minimumHeight = LABEL_HEIGHT; d22.grabExcessVerticalSpace = true; d22.verticalAlignment = GridData.CENTER; mLabel2.setLayoutData(d22); monotonicVariant = new Button(mBase, SWT.CHECK); monotonicVariant.setText(Resources.getMessage("CriterionDefinitionView.68")); //$NON-NLS-1$ monotonicVariant.setSelection(false); monotonicVariant.setEnabled(false); monotonicVariant.setLayoutData(GridDataFactory.swtDefaults().span(3, 1).grab(false, true).align(GridData.BEGINNING, GridData.CENTER).create()); monotonicVariant.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent arg0) { model.getMetricConfiguration().setMonotonic(monotonicVariant.getSelection()); controller.update(new ModelEvent(this, ModelPart.METRIC, model.getMetricDescription())); } }); // Create microaggreation combo final Label mLabel4 = new Label(mBase, SWT.PUSH); mLabel4.setText(Resources.getMessage("CriterionDefinitionView.90")); //$NON-NLS-1$ GridData d24 = new GridData(); d24.heightHint = LABEL_HEIGHT; d24.minimumHeight = LABEL_HEIGHT; d24.grabExcessVerticalSpace = true; d24.verticalAlignment = GridData.CENTER; mLabel4.setLayoutData(d24); comboMicroaggregation = new Combo(mBase, SWT.READ_ONLY); comboMicroaggregation.setItems(new String[]{ Resources.getMessage("CriterionDefinitionView.124"), // Ignore Resources.getMessage("CriterionDefinitionView.125"), // MSE Resources.getMessage("CriterionDefinitionView.126") // IL }); comboMicroaggregation.select(0); comboMicroaggregation.setEnabled(false); GridData d33 = SWTUtil.createFillHorizontallyGridData(); d33.horizontalSpan = 3; d33.verticalAlignment = GridData.CENTER; d33.grabExcessVerticalSpace = true; comboMicroaggregation.setLayoutData(d33); comboMicroaggregation.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent arg0) { switch (comboMicroaggregation.getSelectionIndex()) { case 0: model.getInputConfig().setUseUtilityBasedMicroaggregation(false); break; case 1: model.getInputConfig().setUseUtilityBasedMicroaggregation(true); model.getInputConfig().setUseUtilityBasedMicroaggregationMeanSquaredError(true); break; case 2: model.getInputConfig().setUseUtilityBasedMicroaggregation(true); model.getInputConfig().setUseUtilityBasedMicroaggregationMeanSquaredError(false); break; } controller.update(new ModelEvent(this, ModelPart.METRIC, model.getMetricDescription())); } }); // Create monotonicity button final Label mLabel3 = new Label(mBase, SWT.PUSH); mLabel3.setText(Resources.getMessage("CriterionDefinitionView.72")); //$NON-NLS-1$ GridData d23 = new GridData(); d23.heightHint = LABEL_HEIGHT; d23.minimumHeight = LABEL_HEIGHT; d23.grabExcessVerticalSpace = true; d23.verticalAlignment = GridData.CENTER; mLabel3.setLayoutData(d23); comboAggregate = new Combo(mBase, SWT.READ_ONLY); GridData d31 = SWTUtil.createFillHorizontallyGridData(); d31.horizontalSpan = 3; d31.grabExcessVerticalSpace = true; d31.verticalAlignment = GridData.CENTER; comboAggregate.setLayoutData(d31); comboAggregate.setEnabled(false); comboAggregate.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent arg0) { String selected = comboAggregate.getItem(comboAggregate.getSelectionIndex()); for (AggregateFunction function : model.getMetricDescription().getSupportedAggregateFunctions()) { if (function.toString().equals(selected)) { model.getMetricConfiguration().setAggregateFunction(function); controller.update(new ModelEvent(this, ModelPart.METRIC, model.getMetricDescription())); } } } }); return mBase; } /** * This method updates the view */ private void updateControls(){ // Check if (this.model == null) { return; } // Configure MetricConfiguration config = this.model.getMetricConfiguration(); MetricDescription description = this.model.getMetricDescription(); // Check if (config == null || description == null) { reset(); return; } // Disable redrawing this.root.setRedraw(false); // Monotonicity if (!description.isMonotonicVariantSupported()) { this.monotonicVariant.setSelection(false); } else { this.monotonicVariant.setSelection(config.isMonotonic()); } // Set - TODO: Creating a temporary instance is such an ugly hack boolean isAbleToHandleMicroaggregation = description.createInstance(config).isAbleToHandleMicroaggregation(); boolean isUtilityBasedMicroaggregation = this.model.getInputConfig().isUtilityBasedMicroaggregation(); boolean isUtilityBasedMicroaggregationUseMeanSquaredError = this.model.getInputConfig().isUtilityBasedMicroaggregationUseMeanSquaredError(); if (isAbleToHandleMicroaggregation && isUtilityBasedMicroaggregation) { if (isUtilityBasedMicroaggregationUseMeanSquaredError) { this.comboMicroaggregation.select(1); } else { this.comboMicroaggregation.select(2); } } else { this.comboMicroaggregation.select(0); } // Aggregate function this.comboAggregate.removeAll(); int index = 0; int selected = -1; for (AggregateFunction function : description.getSupportedAggregateFunctions()) { comboAggregate.add(function.toString()); if (function.toString().equals(config.getAggregateFunction().toString())) { selected = index; } index++; } if (selected != -1) { this.comboAggregate.select(selected); } // Enable everything SWTUtil.enable(this.root); // Disable some components if (this.comboAggregate.getItemCount() == 0) { this.comboAggregate.add(Resources.getMessage("ViewMetric.0")); //$NON-NLS-1$ this.comboAggregate.select(0); this.comboAggregate.setEnabled(false); } this.monotonicVariant.setEnabled(description.isMonotonicVariantSupported()); this.comboMicroaggregation.setEnabled(isAbleToHandleMicroaggregation); // Redraw this.root.setRedraw(true); } }