// ============================================================================
//
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package org.talend.dataquality.record.linkage.ui.section;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeMap;
import org.apache.commons.lang.StringUtils;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.talend.core.model.metadata.builder.connection.MetadataColumn;
import org.talend.dataquality.PluginConstant;
import org.talend.dataquality.analysis.Analysis;
import org.talend.dataquality.indicators.columnset.BlockKeyIndicator;
import org.talend.dataquality.indicators.columnset.RecordMatchingIndicator;
import org.talend.dataquality.record.linkage.grouping.MatchGroupResultConsumer;
import org.talend.dataquality.record.linkage.ui.composite.chart.MatchRuleDataChart;
import org.talend.dataquality.record.linkage.ui.composite.utils.MatchRuleAnlaysisUtils;
import org.talend.dataquality.record.linkage.ui.i18n.internal.DefaultMessagesImpl;
import org.talend.dataquality.record.linkage.utils.MatchAnalysisConstant;
import org.talend.dq.analysis.AnalysisRecordGroupingUtils;
import org.talend.dq.analysis.match.ExecuteMatchRuleHandler;
import org.talend.utils.sugars.TypedReturnCode;
/**
* created by zshen on Aug 26, 2013 Detailled comment
*
*/
abstract public class AbstractMatchKeyWithChartTableSection extends AbstractMatchAnaysisTableSection {
/**
* the computation starts 500ms after the user has changed the value.
*/
private static final int DELAY_RUN_GROUP_LESS_THEN = 500;
private List<RunModifyTimerTask> taskList = new ArrayList<RunModifyTimerTask>();
protected MatchRuleDataChart matchRuleChartComp = null;
private List<Object[]> tableResult = null;
private TreeMap<Object, Long> groupSize2groupFrequency = null;
/**
* DOC zshen AbstractMatchKeyWithChartTableSection constructor comment.
*
* @param form
* @param parent
* @param style
* @param toolkit
* @param analysis
*/
public AbstractMatchKeyWithChartTableSection(ScrolledForm form, Composite parent, int style, FormToolkit toolkit,
Analysis analysis) {
super(form, parent, style, toolkit, analysis);
}
/**
* DOC zshen Comment method "createHideGroupComposite".
*
* @param chartComposite
*/
protected void createHideGroupComposite(Composite chartComposite) {
GridData gridData;
Composite toolComp = toolkit.createComposite(chartComposite, SWT.NONE);
gridData = new GridData(GridData.FILL_HORIZONTAL);
toolComp.setLayoutData(gridData);
GridLayout gridLayout = new GridLayout(3, false);
toolComp.setLayout(gridLayout);
Label lessText = new Label(toolComp, SWT.NONE);
lessText.setText(DefaultMessagesImpl.getString("AbstractMatchKeyWithChartTableSection.hide_groups")); //$NON-NLS-1$
// create a spinner with min value 1 and max value
final Spinner lessSpin = new Spinner(toolComp, SWT.BORDER);
lessSpin.setMinimum(1);
lessSpin.setMaximum(Integer.MAX_VALUE);
lessSpin.setTextLimit(9);
lessSpin.setSelection(PluginConstant.HIDDEN_GROUP_LESS_THAN_DEFAULT);
lessSpin.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
Long currentRunTime = System.currentTimeMillis();
if (taskList.size() > 0) {
RunModifyTimerTask oldRunTask = taskList.get(0);
if (currentRunTime - oldRunTask.getTaskRunTime() < DELAY_RUN_GROUP_LESS_THEN) {
oldRunTask.cancel();
taskList.clear();
}
}
// run current after 500ms
RunModifyTimerTask runModifyTimerTask = new RunModifyTimerTask(currentRunTime, lessSpin.getText().trim());
new Timer().schedule(runModifyTimerTask, DELAY_RUN_GROUP_LESS_THEN);
taskList.add(runModifyTimerTask);
}
});
Label lessText2 = new Label(toolComp, SWT.NONE);
lessText2.setText(DefaultMessagesImpl.getString("AbstractMatchKeyWithChartTableSection.items")); //$NON-NLS-1$
}
class RunModifyTimerTask extends TimerTask {
Long taskRunTime = 0l;
/**
* Getter for taskRunTime.
*
* @return the taskRunTime
*/
public Long getTaskRunTime() {
return this.taskRunTime;
}
private String text;
public RunModifyTimerTask(Long runTime, String text) {
this.taskRunTime = runTime;
this.text = text;
}
/*
* (non-Javadoc)
*
* @see java.util.TimerTask#run()
*/
@Override
public void run() {
Display.getDefault().syncExec(new Runnable() {
@Override
public void run() {
if (matchRuleChartComp != null) {
int oldValue = matchRuleChartComp.getTimes();
int times = StringUtils.isEmpty(text) ? 1 : Integer.parseInt(text);
matchRuleChartComp.setTimes(times);
matchRuleChartComp.refresh();
listeners.firePropertyChange(MatchAnalysisConstant.HIDE_GROUPS, oldValue, times);
}
// when run this, it means 500ms later,so we can clear the cache.
taskList.clear();
}
});
}
}
protected TypedReturnCode<RecordMatchingIndicator> computeMatchResult() {
TypedReturnCode<RecordMatchingIndicator> rc = new TypedReturnCode<RecordMatchingIndicator>(false);
final Object[] IndicatorList = MatchRuleAnlaysisUtils.getNeedIndicatorFromAna(analysis);
final RecordMatchingIndicator recordMatchingIndicator = EcoreUtil.copy((RecordMatchingIndicator) IndicatorList[0]);
BlockKeyIndicator blockKeyIndicator = EcoreUtil.copy((BlockKeyIndicator) IndicatorList[1]);
ExecuteMatchRuleHandler execHandler = new ExecuteMatchRuleHandler();
MatchGroupResultConsumer matchResultConsumer = createMatchGroupResultConsumer(recordMatchingIndicator);
// Set match key schema to the record matching indicator.
MetadataColumn[] completeColumnSchema = AnalysisRecordGroupingUtils.getCompleteColumnSchema(columnMap);
String[] colSchemaString = new String[completeColumnSchema.length];
int idx = 0;
for (MetadataColumn metadataCol : completeColumnSchema) {
colSchemaString[idx++] = metadataCol.getName();
}
recordMatchingIndicator.setMatchRowSchema(colSchemaString);
recordMatchingIndicator.reset();
TypedReturnCode<MatchGroupResultConsumer> execute = execHandler.execute(columnMap, recordMatchingIndicator, matchRows,
blockKeyIndicator, matchResultConsumer);
if (!execute.isOk()) {
rc.setMessage(DefaultMessagesImpl.getString(
"RunAnalysisAction.failRunAnalysis", analysis.getName(), execute.getMessage())); //$NON-NLS-1$
return rc;
} else {
if (execute.getObject().getFullMatchResult() == null) {
return rc;
}
// TDQ-9741, the "chart" result must be stored for hiding group(not compute again)
tableResult = execute.getObject().getFullMatchResult();
groupSize2groupFrequency = recordMatchingIndicator.getGroupSize2groupFrequency();
}
rc.setOk(true);
rc.setObject(recordMatchingIndicator);
return rc;
}
protected List<Object[]> getTableResult() {
return tableResult;
}
protected TreeMap<Object, Long> getChartResult() {
return groupSize2groupFrequency;
}
/**
* DOC zhao Comment method "initRecordMatchIndicator".
*
* @param columnMap
* @return
*/
private MatchGroupResultConsumer createMatchGroupResultConsumer(final RecordMatchingIndicator recordMatchingIndicator) {
MatchGroupResultConsumer matchResultConsumer = new MatchGroupResultConsumer(true) {
/*
* (non-Javadoc)
*
* @see org.talend.dataquality.record.linkage.grouping. MatchGroupResultConsumer#handle(java.lang.Object)
*/
@Override
public void handle(Object row) {
recordMatchingIndicator.handle(row);
addOneRowOfResult(row);
}
};
return matchResultConsumer;
}
}