// ============================================================================
//
// 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.dataprofiler.core.ui.editor.preview;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.TreeSet;
import org.eclipse.emf.common.util.EList;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Display;
import org.talend.core.model.metadata.builder.connection.Connection;
import org.talend.cwm.helper.ColumnHelper;
import org.talend.cwm.helper.SwitchHelpers;
import org.talend.dataprofiler.core.i18n.internal.DefaultMessagesImpl;
import org.talend.dataprofiler.core.ui.utils.TOPChartUtils;
import org.talend.dataprofiler.service.utils.ValueAggregator;
import org.talend.dataquality.analysis.Analysis;
import org.talend.dataquality.indicators.columnset.ColumnSetMultiValueIndicator;
import org.talend.dq.analysis.explore.MultiColumnSetValueExplorer;
import org.talend.dq.helper.SqlExplorerUtils;
import org.talend.utils.collections.MultiMapHelper;
import org.talend.utils.collections.MultipleKey;
import org.talend.utils.collections.ValueAggregate;
import orgomg.cwm.objectmodel.core.ModelElement;
/**
* created by yyin on 2014-12-17 Detailled comment
*
*/
public class DatasetUtils {
public static final String SPACE_STRING = " "; //$NON-NLS-1$
public static Map<Integer, Object> getQueryMap(final Map<String, ValueAggregator> xyzMap,
final ColumnSetMultiValueIndicator indicator, ModelElement column, Analysis analysis) {
Map<Integer, Object> queryMap = new HashMap<Integer, Object>();
EList<ModelElement> nominalList = indicator.getNominalColumns();
Iterator<String> iterator = xyzMap.keySet().iterator();
while (iterator.hasNext()) {
final String seriesKey = iterator.next();
final ValueAggregator valueAggregator = xyzMap.get(seriesKey);
Iterator<Entry<MultipleKey, Double[]>> keyValueMap = valueAggregator.getKeyValueMap();
int index = 0;
while (keyValueMap.hasNext()) {
Entry<MultipleKey, Double[]> next = keyValueMap.next();
final String queryString = MultiColumnSetValueExplorer.getInstance().getQueryStirng(column, analysis,
nominalList, seriesKey, next.getKey().toString());
queryMap.put(Integer.valueOf(index++), createSelectAdapter(queryString, column, analysis));
}
}
return queryMap;
}
/**
* DOC yyin Comment method "getGanttQueryMap".
*
* @param createGannttDatasets
* @param indicator
* @param column
* @param analysis
* @return
*/
public static Map<Integer, Object> getGanttQueryMap(Map<String, DateValueAggregate> gannttMap,
ColumnSetMultiValueIndicator indicator, ModelElement column, Analysis analysis) {
Map<Integer, Object> ganttQueryMap = new HashMap<Integer, Object>();
Iterator<String> iterator = gannttMap.keySet().iterator();
EList<ModelElement> nominalList = indicator.getNominalColumns();
int index = 0;
while (iterator.hasNext()) {
final String seriesKey = iterator.next();
final DateValueAggregate valueAggregator = gannttMap.get(seriesKey);
Iterator<MultipleKey> keyValueMap = valueAggregator.getKeyValueMap();
while (keyValueMap.hasNext()) {
MultipleKey next = keyValueMap.next();
final String seriesLabel = next.toString();
final String queryString = MultiColumnSetValueExplorer.getInstance().getQueryStirng(column, analysis,
nominalList, seriesKey, seriesLabel);
ganttQueryMap.put(index++, createSelectAdapter(queryString, column, analysis));
}
}
return ganttQueryMap;
}
private static SelectionAdapter createSelectAdapter(final String sql, final ModelElement column, final Analysis analysis) {
return new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
Connection tdDataProvider = SwitchHelpers.CONNECTION_SWITCH.doSwitch(analysis.getContext()
.getConnection());
String query = sql;
@SuppressWarnings("deprecation")
String editorName = ColumnHelper.getColumnSetOwner(column).getName();
SqlExplorerUtils.getDefault().runInDQViewer(tdDataProvider, query, editorName);
}
});
}
};
}
/**
* DOC scorreia Comment method "createXYZDatasets".
*
* @param indicator
* @param numericColumn a numeric column which is in the list of numeric column of the indicator
* @return a series of datasets for the given numeric column
*/
public static Map<String, ValueAggregator> createXYZDatasets(ColumnSetMultiValueIndicator indicator,
ModelElement numericColumn) {
final EList<ModelElement> nominalColumns = indicator.getNominalColumns();
final EList<ModelElement> numericColumns = indicator.getNumericColumns();
final EList<String> numericFunctions = indicator.getNumericFunctions();
final int indexOfNumericCol = numericColumns.indexOf(numericColumn);
assert indexOfNumericCol != -1;
final int nbNumericFunctions = numericFunctions.size();
assert nbNumericFunctions == 3 : DefaultMessagesImpl.getString("ChartDatasetFactory.expect"); //$NON-NLS-1$
final List<Object[]> listRows = indicator.getListRows();
final int nbNominalColumns = nominalColumns.size();
return fillDataset(nominalColumns, listRows, nbNominalColumns + nbNumericFunctions * indexOfNumericCol);
}
public static Map<String, DateValueAggregate> createGanttDatasets(ColumnSetMultiValueIndicator indicator,
ModelElement dateColumn) {
final EList<ModelElement> nominalColumns = indicator.getNominalColumns();
final EList<ModelElement> dateColumns = indicator.getDateColumns();
final EList<String> dateFunctions = indicator.getDateFunctions();
final int indexOfDateCol = dateColumns.indexOf(dateColumn);
assert indexOfDateCol != -1;
final int nbDateFunctions = dateFunctions.size();
assert nbDateFunctions >= 2 : DefaultMessagesImpl.getString("ChartDatasetFactory.expect"); //$NON-NLS-1$
final List<Object[]> listRows = indicator.getListRows();
final int nbNominalColumns = nominalColumns.size();
return fillGanttDataset(nominalColumns, listRows, nbNominalColumns + nbDateFunctions * indexOfDateCol);
}
/**
* Method "fillDataset" fills in the data sets.
*
* @param nominalColumns the nominal columns
* @param listRows the rows (=result set)
* @param firstNumericColumnIdx the index of the first numeric column
* @return a map [key -> aggregated values] where identifies a level of aggregation
*/
private static Map<String, ValueAggregator> fillDataset(final List<ModelElement> nominalColumns,
final List<Object[]> listRows, final int firstNumericColumnIdx) {
Map<String, ValueAggregator> valueAggregators = new HashMap<String, ValueAggregator>();
int xPos = firstNumericColumnIdx;
int yPos = firstNumericColumnIdx + 1;
int zPos = firstNumericColumnIdx + 2;
for (int i = nominalColumns.size(); i > 0; i--) {
String key = createKey(nominalColumns, i);
// ADD msjian 2011-5-30 17479: Excel Odbc connection can not run well on the correlation analysis
if (null != listRows) {
for (Object[] row : listRows) {
final Object xobj = row[xPos];
final Double xValue = xobj != null ? Double.valueOf(String.valueOf(xobj)) : null;
final Object yobj = row[yPos];
final Double yValue = yobj != null ? Double.valueOf(String.valueOf(yobj)) : null;
final Object zobj = row[zPos];
final Double zValue = zobj != null ? Double.valueOf(String.valueOf(zobj)) : null;
ValueAggregator valueAggregator = valueAggregators.get(key);
if (valueAggregator == null) {
valueAggregator = new ValueAggregator();
valueAggregators.put(key, valueAggregator);
}
MultipleKey multipleKey = new MultipleKey(row, i);
valueAggregator.addValue(multipleKey, new Double[] { xValue, yValue, zValue });
}
}
}
return valueAggregators;
}
/**
*
*/
private static Map<String, DateValueAggregate> fillGanttDataset(final EList<ModelElement> nominalColumns,
final List<Object[]> listRows, final int firstDateColumnIdx) {
Map<String, DateValueAggregate> valueAggregators = new TreeMap<String, DateValueAggregate>();
int minPos = firstDateColumnIdx;
int maxPos = firstDateColumnIdx + 1;
for (int i = nominalColumns.size(); i > 0; i--) {
String key = createKey(nominalColumns, i);
// ADD msjian 2011-5-30 17479: Excel Odbc connection can not run well on the correlation analysis
if (null != listRows) {
for (Object[] row : listRows) {
final Object minObj = row[minPos];
final Date minDate = minObj != null ? (Date) minObj : null;
final Object maxobj = row[maxPos];
final Date maxDate = maxobj != null ? (Date) maxobj : null;
DateValueAggregate valueAggregator = valueAggregators.get(key);
if (valueAggregator == null) {
valueAggregator = new DateValueAggregate();
valueAggregators.put(key, valueAggregator);
}
MultipleKey multipleKey = new MultipleKey(row, i);
valueAggregator.addValue(multipleKey, new Date[] { minDate, maxDate });
}
}
}
return valueAggregators;
}
/**
* Method "createKey" creates a key with the concatenation of the values of the first n columns of the given list.
*
* @param nominalColumns
* @param n
* @return a key
*/
private static String createKey(List<ModelElement> nominalColumns, int n) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < n; i++) {
builder.append(nominalColumns.get(i).getName()).append(SPACE_STRING);
}
return builder.toString();
}
/**
* DOC scorreia ValueAggregator class global comment. Detailled comment
*/
/**
*
*/
public static class DateValueAggregate extends ValueAggregate<MultipleKey, Date> {
private Map<String, List<String>> seriesKeyToLabel = new HashMap<String, List<String>>();
/**
* Method "getLabels". Must not be called before the {@link #addSeriesToXYZDataset(DefaultXYZDataset, String)}
* method.
*
* @param seriesKey
* @return the label for each item of the dataset
*/
public List<String> getLabels(String seriesKey) {
return seriesKeyToLabel.get(seriesKey);
}
public Iterator<MultipleKey> getKeyValueMap() {
TreeSet<MultipleKey> treeSet = new TreeSet<MultipleKey>(keyToVal.keySet());
return treeSet.iterator();
}
public Date[] getValueByKey(MultipleKey key) {
return keyToVal.get(key);
}
@Override
public void addValue(MultipleKey key, Date[] values) {
assert values.length == 2; // expect only min date and max date functions
Date[] dates = keyToVal.get(key);
if (dates == null) {
dates = new Date[values.length];
// fill in with nulls
Arrays.fill(dates, null);
}
Date min = values[0];
Date max = values[1];
if (min == null || max == null) {
nullResults.add(key);
return;
}
Date prevMinDate = dates[0];
Date prevMaxDate = dates[1];
dates[0] = (prevMinDate == null || min.before(prevMinDate)) ? min : prevMinDate;
dates[1] = (prevMaxDate == null || max.after(prevMaxDate)) ? max : prevMaxDate;
keyToVal.put(key, dates);
}
/**
* Method "addSeriesToXYZDataset" adds a new series of data to the given dataset.
*
* @param dataset a dataset
* @param keyOfDataset the series key of the data series
*/
public void addSeriesToGanttDataset(Object ganttDataset, String keyOfDataset) {
Object series = TOPChartUtils.getInstance().createTaskSeries(keyOfDataset);
int i = 0;
for (MultipleKey key : new TreeSet<MultipleKey>(keyToVal.keySet())) {
final Date[] date = keyToVal.get(key);
TOPChartUtils.getInstance().addTaskToTaskSeries(series, key.toString(), date);
MultiMapHelper.addUniqueObjectToListMap(keyOfDataset, key.toString(), this.seriesKeyToLabel);
}
TOPChartUtils.getInstance().addSeriesToCollection(ganttDataset, series);
}
}
}