/*
* 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.utility;
import org.deidentifier.arx.AttributeType.Hierarchy;
import org.deidentifier.arx.DataHandle;
import org.deidentifier.arx.aggregates.StatisticsBuilderInterruptible;
import org.deidentifier.arx.aggregates.StatisticsFrequencyDistribution;
import org.deidentifier.arx.gui.Controller;
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.impl.common.ComponentTable;
import org.deidentifier.arx.gui.view.impl.common.async.Analysis;
import org.deidentifier.arx.gui.view.impl.common.async.AnalysisContext;
import org.deidentifier.arx.gui.view.impl.common.async.AnalysisManager;
import org.deidentifier.arx.gui.view.impl.common.table.CTConfiguration;
import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
/**
* This view displays a frequency distribution.
*
* @author Fabian Prasser
*/
public class ViewStatisticsDistributionTable extends ViewStatistics<AnalysisContextDistribution> {
/** Internal stuff. */
private ComponentTable table;
/** Internal stuff. */
private AnalysisManager manager;
/**
* Creates a new instance.
*
* @param parent
* @param controller
* @param target
* @param reset
*/
public ViewStatisticsDistributionTable(final Composite parent,
final Controller controller,
final ModelPart target,
final ModelPart reset) {
super(parent, controller, target, reset, true);
this.manager = new AnalysisManager(parent.getDisplay());
}
@Override
public LayoutUtility.ViewUtilityType getType() {
return LayoutUtility.ViewUtilityType.HISTOGRAM_TABLE;
}
@Override
protected Control createControl(Composite parent) {
// Configure table
CTConfiguration config = new CTConfiguration(parent, CTConfiguration.STYLE_TABLE);
config.setHorizontalAlignment(SWT.CENTER);
config.setCellSelectionEnabled(false);
config.setColumnSelectionEnabled(false);
config.setRowSelectionEnabled(false);
config.setColumnHeaderLayout(CTConfiguration.COLUMN_HEADER_LAYOUT_FILL_EQUAL);
config.setRowHeaderLayout(CTConfiguration.ROW_HEADER_LAYOUT_DEFAULT);
this.table = new ComponentTable(parent, SWT.NONE, config);
return this.table.getControl();
}
@Override
protected AnalysisContextDistribution createViewConfig(AnalysisContext context) {
return new AnalysisContextDistribution(context);
}
@Override
protected void doReset() {
if (this.manager != null) {
this.manager.stop();
}
this.table.clear();
setStatusEmpty();
}
@Override
protected void doUpdate(AnalysisContextDistribution context) {
// The statistics builder
final StatisticsBuilderInterruptible builder = context.handle.getStatistics().getInterruptibleInstance();
final Hierarchy hierarchy = context.context.getHierarchy(context.context.getData(), context.attribute);
final DataHandle handle = context.handle;
final int column = handle.getColumnIndexOf(context.attribute);
// Create an analysis
Analysis analysis = new Analysis(){
private boolean stopped = false;
private StatisticsFrequencyDistribution distribution;
@Override
public int getProgress() {
return 0;
}
@Override
public void onError() {
setStatusEmpty();
}
@Override
public void onFinish() {
// Check
if (stopped || !isEnabled()) {
return;
}
// Now update the table
table.setData(new IDataProvider() {
public int getColumnCount() {
return 2;
}
public Object getDataValue(int arg0, int arg1) {
return arg0 == 0 ? distribution.values[arg1] : SWTUtil.getPrettyString(distribution.frequency[arg1]*100d)+"%"; //$NON-NLS-1$
}
public int getRowCount() {
return distribution.values.length;
}
public void setDataValue(int arg0, int arg1, Object arg2) {
/* Ignore */
}
}, new String[] { Resources.getMessage("ViewStatisticsDistributionTable.2"), Resources.getMessage("ViewStatisticsDistributionTable.3") }); //$NON-NLS-1$ //$NON-NLS-2$
setStatusDone();
}
@Override
public void onInterrupt() {
if (!isEnabled()) {
setStatusEmpty();
} else {
setStatusWorking();
}
}
@Override
public void run() throws InterruptedException {
// Timestamp
long time = System.currentTimeMillis();
// Perform work
this.distribution = builder.getFrequencyDistribution(column, hierarchy);
// Our users are patient
while (System.currentTimeMillis() - time < MINIMAL_WORKING_TIME && !stopped){
Thread.sleep(10);
}
}
@Override
public void stop() {
builder.interrupt();
this.stopped = true;
}
};
this.manager.start(analysis);
}
/**
* Is an analysis running
*/
protected boolean isRunning() {
return manager != null && manager.isRunning();
}
}