/*
* 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.risk;
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.model.ModelRisk.ViewRiskType;
import org.deidentifier.arx.gui.resources.Resources;
import org.deidentifier.arx.gui.view.SWTUtil;
import org.deidentifier.arx.gui.view.impl.common.ComponentRiskMonitor;
import org.deidentifier.arx.gui.view.impl.common.ComponentRiskThresholds;
import org.deidentifier.arx.gui.view.impl.common.ComponentStatusLabelProgressProvider;
import org.deidentifier.arx.gui.view.impl.common.ComponentTitledSeparator;
import org.deidentifier.arx.gui.view.impl.common.DelayedChangeListener;
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.risk.RiskEstimateBuilderInterruptible;
import org.deidentifier.arx.risk.RiskModelSampleSummary;
import org.deidentifier.arx.risk.RiskModelSampleSummary.JournalistRisk;
import org.deidentifier.arx.risk.RiskModelSampleSummary.MarketerRisk;
import org.deidentifier.arx.risk.RiskModelSampleSummary.ProsecutorRisk;
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.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
/**
* This view displays basic risk estimates.
*
* @author Fabian Prasser
*/
public class ViewRisksReIdentification extends ViewRisks<AnalysisContextRisk> {
/** View */
private static final String MESSAGE_CAPTION1 = Resources.getMessage("ViewRisksReIdentification.0"); //$NON-NLS-1$
/** View */
private static final String MESSAGE_CAPTION2 = Resources.getMessage("ViewRisksReIdentification.1"); //$NON-NLS-1$
/** View */
private static final String MESSAGE_CAPTION3 = Resources.getMessage("ViewRisksReIdentification.2"); //$NON-NLS-1$
/** View */
private static final String MESSAGE_LABEL1 = Resources.getMessage("ViewRisksReIdentification.3"); //$NON-NLS-1$
/** View */
private static final String MESSAGE_LABEL2 = Resources.getMessage("ViewRisksReIdentification.4"); //$NON-NLS-1$
/** View */
private static final String MESSAGE_LABEL3 = Resources.getMessage("ViewRisksReIdentification.5"); //$NON-NLS-1$
/** View */
private static final String MESSAGE_SHORT1 = Resources.getMessage("ViewRisksReIdentification.6"); //$NON-NLS-1$
/** View */
private static final String MESSAGE_SHORT2 = Resources.getMessage("ViewRisksReIdentification.7"); //$NON-NLS-1$
/** View */
private static final String MESSAGE_SHORT3 = Resources.getMessage("ViewRisksReIdentification.8"); //$NON-NLS-1$
/** View */
private Composite root;
/** View */
private ComponentRiskMonitor prosecutor1;
/** View */
private ComponentRiskMonitor prosecutor2;
/** View */
private ComponentRiskMonitor prosecutor3;
/** View */
private ComponentRiskMonitor journalist1;
/** View */
private ComponentRiskMonitor journalist2;
/** View */
private ComponentRiskMonitor journalist3;
/** View */
private ComponentRiskMonitor marketer1;
/** View */
private ComponentRiskThresholds riskThresholds;
/** Internal stuff. */
private AnalysisManager manager;
/**
* Creates a new instance.
*
* @param parent
* @param controller
* @param target
* @param reset
*/
public ViewRisksReIdentification(final Composite parent,
final Controller controller,
final ModelPart target,
final ModelPart reset) {
super(parent, controller, target, reset);
this.manager = new AnalysisManager(parent.getDisplay());
controller.addListener(ModelPart.ATTRIBUTE_TYPE, this);
controller.addListener(ModelPart.RISK_THRESHOLD_MAIN, this);
controller.addListener(ModelPart.RISK_THRESHOLD_DERIVED, this);
}
@Override
public void update(ModelEvent event) {
super.update(event);
if (event.part == ModelPart.ATTRIBUTE_TYPE) {
triggerUpdate();
}
if (event.part == ModelPart.RISK_THRESHOLD_MAIN) {
handleThresholdUpdateInSettings();
triggerUpdate();
}
if (event.part == ModelPart.RISK_THRESHOLD_DERIVED) {
handleThresholdUpdateInSettings();
handleThresholdUpdateInMonitors();
}
}
/**
* Handles updates of risk thresholds
*/
private void handleThresholdUpdateInMonitors() {
prosecutor1.setThreshold(super.getModel().getRiskModel().getRiskThresholdRecordsAtRisk());
prosecutor2.setThreshold(super.getModel().getRiskModel().getRiskThresholdHighestRisk());
prosecutor3.setThreshold(super.getModel().getRiskModel().getRiskThresholdSuccessRate());
journalist1.setThreshold(super.getModel().getRiskModel().getRiskThresholdRecordsAtRisk());
journalist2.setThreshold(super.getModel().getRiskModel().getRiskThresholdHighestRisk());
journalist3.setThreshold(super.getModel().getRiskModel().getRiskThresholdSuccessRate());
marketer1.setThreshold(super.getModel().getRiskModel().getRiskThresholdSuccessRate());
}
/**
* Handles updates of risk thresholds
*/
private void handleThresholdUpdateInSettings() {
if (riskThresholds != null) {
riskThresholds.setThresholdHighestRisk(super.getModel().getRiskModel().getRiskThresholdHighestRisk());
riskThresholds.setThresholdRecordsAtRisk(super.getModel().getRiskModel().getRiskThresholdRecordsAtRisk());
riskThresholds.setThresholdSuccessRate(super.getModel().getRiskModel().getRiskThresholdSuccessRate());
}
}
@Override
protected Control createControl(Composite parent) {
GridLayout layout = SWTUtil.createGridLayoutWithEqualWidth(3);
layout.marginHeight = 0;
layout.marginTop = 0;
layout.marginBottom = 0;
layout.verticalSpacing = 0;
layout.makeColumnsEqualWidth = true;
this.root = new Composite(parent, SWT.NONE);
this.root.setLayout(layout);
// Prepare
GridData separatordata = SWTUtil.createFillHorizontallyGridData(true, 3);
separatordata.verticalIndent = 0;
// Prosecutor
ComponentTitledSeparator separator = new ComponentTitledSeparator(root, SWT.NONE);
separator.setLayoutData(separatordata);
separator.setText(MESSAGE_CAPTION1);
separator.setImage(controller.getResources().getManagedImage("prosecutor.png")); //$NON-NLS-1$
prosecutor1 = new ComponentRiskMonitor(root, controller, MESSAGE_LABEL1, MESSAGE_SHORT1);
prosecutor2 = new ComponentRiskMonitor(root, controller, MESSAGE_LABEL2, MESSAGE_SHORT2);
prosecutor3 = new ComponentRiskMonitor(root, controller, MESSAGE_LABEL3, MESSAGE_SHORT3);
prosecutor1.setLayoutData(SWTUtil.createFillGridData());
prosecutor2.setLayoutData(SWTUtil.createFillGridData());
prosecutor3.setLayoutData(SWTUtil.createFillGridData());
// Journalist
separator = new ComponentTitledSeparator(root, SWT.NONE);
separator.setLayoutData(separatordata);
separator.setText(MESSAGE_CAPTION2);
separator.setImage(controller.getResources().getManagedImage("journalist.png")); //$NON-NLS-1$
journalist1 = new ComponentRiskMonitor(root, controller, MESSAGE_LABEL1, MESSAGE_SHORT1);
journalist2 = new ComponentRiskMonitor(root, controller, MESSAGE_LABEL2, MESSAGE_SHORT2);
journalist3 = new ComponentRiskMonitor(root, controller, MESSAGE_LABEL3, MESSAGE_SHORT3);
journalist1.setLayoutData(SWTUtil.createFillGridData());
journalist2.setLayoutData(SWTUtil.createFillGridData());
journalist3.setLayoutData(SWTUtil.createFillGridData());
// Marketer
separator = new ComponentTitledSeparator(root, SWT.NONE);
separator.setLayoutData(separatordata);
separator.setText(MESSAGE_CAPTION3);
separator.setImage(controller.getResources().getManagedImage("marketer.png")); //$NON-NLS-1$
marketer1 = new ComponentRiskMonitor(root, controller, MESSAGE_LABEL3, MESSAGE_SHORT3);
marketer1.setLayoutData(SWTUtil.createFillGridData());
// Slider
if (isInput()) {
GridData data = SWTUtil.createFillGridData();
data.heightHint = 30;
data.horizontalSpan = 2;
riskThresholds = new ComponentRiskThresholds(root);
riskThresholds.setLayoutData(data);
riskThresholds.addSelectionListenerThresholdHighestRisk(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent arg0) {
if (riskThresholds.getThresholdHighestRisk() != getModel().getRiskModel().getRiskThresholdHighestRisk()) {
getModel().getRiskModel().setRiskThresholdHighestRisk(riskThresholds.getThresholdHighestRisk());
controller.update(new ModelEvent(this, ModelPart.RISK_THRESHOLD_DERIVED, null));
handleThresholdUpdateInMonitors();
}
}
});
riskThresholds.addSelectionListenerThresholdHighestRisk(new DelayedChangeListener(1000) {
@Override
public void delayedEvent() {
getModel().getRiskModel().setRiskThresholdHighestRisk(riskThresholds.getThresholdHighestRisk());
controller.update(new ModelEvent(this, ModelPart.RISK_THRESHOLD_MAIN, null));
triggerUpdate();
}
});
riskThresholds.addSelectionListenerThresholdRecordsAtRisk(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent arg0) {
if (riskThresholds.getThresholdRecordsAtRisk() != getModel().getRiskModel().getRiskThresholdRecordsAtRisk()) {
getModel().getRiskModel().setRiskThresholdRecordsAtRisk(riskThresholds.getThresholdRecordsAtRisk());
controller.update(new ModelEvent(this, ModelPart.RISK_THRESHOLD_DERIVED, null));
handleThresholdUpdateInMonitors();
}
}
});
riskThresholds.addSelectionListenerThresholdSuccessRate(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent arg0) {
if (riskThresholds.getThresholdSuccessRate() != getModel().getRiskModel().getRiskThresholdSuccessRate()) {
getModel().getRiskModel().setRiskThresholdSuccessRate(riskThresholds.getThresholdSuccessRate());
controller.update(new ModelEvent(this, ModelPart.RISK_THRESHOLD_DERIVED, null));
handleThresholdUpdateInMonitors();
}
}
});
} else {
riskThresholds = null;
}
return this.root;
}
@Override
protected AnalysisContextRisk createViewConfig(AnalysisContext context) {
return new AnalysisContextRisk(context);
}
@Override
protected void doReset() {
if (this.manager != null) {
this.manager.stop();
}
setStatusEmpty();
}
@Override
protected void doUpdate(final AnalysisContextRisk context) {
// Enable/disable
final RiskEstimateBuilderInterruptible builder = getBuilder(context);
if (!this.isEnabled() || builder == null) {
if (manager != null) {
manager.stop();
}
this.setStatusEmpty();
return;
}
final Model model = super.getModel();
// Create an analysis
Analysis analysis = new Analysis() {
private boolean stopped = false;
private ProsecutorRisk prosecutor;
private JournalistRisk journalist;
private MarketerRisk marketer;
@Override
public int getProgress() {
return (int)Math.round((double)builder.getProgress());
}
@Override
public void onError() {
setStatusEmpty();
}
@Override
public void onFinish() {
if (stopped || !isEnabled()) {
return;
}
// Update thresholds
handleThresholdUpdateInSettings();
// Update views
prosecutor1.setRisk(prosecutor.getRecordsAtRisk());
prosecutor1.setThreshold(model.getRiskModel().getRiskThresholdRecordsAtRisk());
prosecutor2.setRisk(prosecutor.getHighestRisk());
prosecutor2.setThreshold(model.getRiskModel().getRiskThresholdHighestRisk());
prosecutor3.setRisk(prosecutor.getSuccessRate());
prosecutor3.setThreshold(model.getRiskModel().getRiskThresholdSuccessRate());
// Update views
journalist1.setRisk(journalist.getRecordsAtRisk());
journalist1.setThreshold(model.getRiskModel().getRiskThresholdRecordsAtRisk());
journalist2.setRisk(journalist.getHighestRisk());
journalist2.setThreshold(model.getRiskModel().getRiskThresholdHighestRisk());
journalist3.setRisk(journalist.getSuccessRate());
journalist3.setThreshold(model.getRiskModel().getRiskThresholdSuccessRate());
// Update views
marketer1.setRisk(marketer.getSuccessRate());
marketer1.setThreshold(model.getRiskModel().getRiskThresholdSuccessRate());
// Layout
root.layout();
setStatusDone();
}
@Override
public void onInterrupt() {
if (!isEnabled() || !isValid()) {
setStatusEmpty();
} else {
setStatusWorking();
}
}
@Override
public void run() throws InterruptedException {
// Timestamp
long time = System.currentTimeMillis();
// Perform work
RiskModelSampleSummary summary = builder.getSampleBasedRiskSummary(model.getRiskModel().getRiskThresholdHighestRisk());
prosecutor = summary.getProsecutorRisk();
journalist = summary.getJournalistRisk();
marketer = summary.getMarketerRisk();
// Our users are patient
while (System.currentTimeMillis() - time < MINIMAL_WORKING_TIME && !stopped) {
Thread.sleep(10);
}
}
@Override
public void stop() {
if (builder != null) builder.interrupt();
this.stopped = true;
}
};
this.manager.start(analysis);
}
@Override
protected ComponentStatusLabelProgressProvider getProgressProvider() {
return new ComponentStatusLabelProgressProvider(){
public int getProgress() {
if (manager == null) {
return 0;
} else {
return manager.getProgress();
}
}
};
}
@Override
protected ViewRiskType getViewType() {
return ViewRiskType.CELL_BASED;
}
/**
* Is an analysis running
*/
protected boolean isRunning() {
return manager != null && manager.isRunning();
}
}