// ============================================================================ // // 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.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.MessageDialogWithToggle; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.PlatformUI; 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.RecordMatchingIndicator; import org.talend.dataquality.record.linkage.genkey.BlockingKeyHandler; import org.talend.dataquality.record.linkage.ui.composite.AbsMatchAnalysisTableComposite; import org.talend.dataquality.record.linkage.ui.composite.BlockingKeyTableComposite; import org.talend.dataquality.record.linkage.ui.composite.chart.BlockingKeyDataChart; import org.talend.dataquality.record.linkage.ui.composite.tableviewer.sorter.KeyDefinitionTableViewerSorter; 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.dataquality.rules.BlockKeyDefinition; import org.talend.dataquality.rules.KeyDefinition; import org.talend.dataquality.rules.MatchRuleDefinition; import org.talend.utils.sugars.ReturnCode; /** * created by zshen on Aug 6, 2013 Detailled comment * */ public class BlockingKeySection extends AbstractMatchAnaysisTableSection { private BlockingKeyDataChart blockingKeyDataChart = null; public AbsMatchAnalysisTableComposite<BlockKeyDefinition> tableComposite = null; /** * DOC zshen BlockingKeySection constructor comment. * * @param parent * @param style * @param toolkit */ public BlockingKeySection(final ScrolledForm form, Composite parent, int style, FormToolkit toolkit, Analysis analysis) { super(form, parent, style, toolkit, analysis); } /* * (non-Javadoc) * * @see org.talend.dataquality.record.linkage.ui.section.AbstractMatchTableSection#getSectionName() */ @Override protected String getSectionName() { return MatchAnalysisConstant.BlOCKING_KEY_SECTION_NAME; } @Override protected Composite createSubContent(Composite sectionClient) { Composite ruleComp = toolkit.createComposite(sectionClient, SWT.NONE); GridData data = new GridData(GridData.FILL_BOTH); ruleComp.setLayoutData(data); GridLayout gridLayout = new GridLayout(1, true); gridLayout.marginWidth = 0; gridLayout.marginHeight = 0; ruleComp.setLayout(gridLayout); tableComposite = createTableComposite(ruleComp); tableComposite.addPropertyChangeListener(this); tableComposite.setAddColumn(isAddColumn()); tableComposite.setLayout(gridLayout); tableComposite.setLayoutData(data); if (columnMap != null) { ArrayList<MetadataColumn> columnList = new ArrayList<MetadataColumn>(); columnList.addAll(columnMap.keySet()); tableComposite.setColumnList(columnList); } tableComposite.createContent(); tableComposite.serViewerSorter(new KeyDefinitionTableViewerSorter<BlockKeyDefinition>(getBlockKeyDefinitionList())); initTableInput(); return ruleComp; } protected BlockingKeyTableComposite createTableComposite(Composite parent) { return new BlockingKeyTableComposite(parent, SWT.NO_FOCUS); } /** * DOC zhao Comment method "initTableInput". */ private void initTableInput() { tableComposite.setInput(getBlockKeyDefinitionList()); } protected List<BlockKeyDefinition> getBlockKeyDefinitionList() { return getMatchRuleDefinition().getBlockKeys(); } protected MatchRuleDefinition getMatchRuleDefinition() { RecordMatchingIndicator recordMatchingIndicator = MatchRuleAnlaysisUtils.getRecordMatchIndicatorFromAna(analysis); return recordMatchingIndicator.getBuiltInMatchRuleDefinition(); } /* * (non-Javadoc) * * @see * org.talend.dataquality.record.linkage.ui.section.AbstractMatchTableSection#createSubChart(org.eclipse.swt.widgets * .Composite) */ @Override protected void createSubChart(Composite sectionClient) { Composite blockComp = toolkit.createComposite(sectionClient, SWT.NONE); GridLayout tableLayout = new GridLayout(1, Boolean.TRUE); blockComp.setLayout(tableLayout); GridData gridData = new GridData(GridData.FILL_BOTH); blockComp.setLayoutData(gridData); blockingKeyDataChart = new BlockingKeyDataChart(blockComp, new HashMap<String, List<String[]>>()); } /* * (non-Javadoc) * * @see org.talend.dataquality.record.linkage.ui.section.AbstractMatchTableSection#RefreshChart() */ @Override public void refreshChart() { if (getBlockKeyDefinitionList().size() <= 0) { MessageDialogWithToggle .openError( PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), DefaultMessagesImpl.getString("BlockingKeySection.RefreshChartError"), DefaultMessagesImpl.getString("BlockingKeySection.NoBlockKey")); //$NON-NLS-1$ //$NON-NLS-2$ return; } ReturnCode checkResultStatus = checkResultStatus(); if (!checkResultStatus.isOk()) { if (checkResultStatus.getMessage() != null && !checkResultStatus.getMessage().equals(StringUtils.EMPTY)) { MessageDialogWithToggle.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), DefaultMessagesImpl.getString("BlockingKeySection.RefreshChartError"), checkResultStatus.getMessage()); //$NON-NLS-1$ } return; } listeners.firePropertyChange(MatchAnalysisConstant.NEED_REFRESH_DATA, true, false); BlockingKeyHandler executeGenerateBlockingAction = computeResult(); if (executeGenerateBlockingAction.getResultDataList().size() == 0) { return; } blockingKeyDataChart.refresh(executeGenerateBlockingAction.getResultDatas()); MatchRuleAnlaysisUtils.refreshDataTable(analysis, executeGenerateBlockingAction.getResultDataList()); executeGenerateBlockingAction.getResultDatas().clear(); } /** * DOC zshen Comment method "computeRusult". <br> * TODO Handle the return value: return the result directly instead of action instance. * * @return */ protected BlockingKeyHandler computeResult() { List<Map<String, String>> blockingKeyData = MatchRuleAnlaysisUtils .blockingKeyDataConvert((List<KeyDefinition>) tableComposite.getInput()); Map<String, String> colName2IndexMap = new HashMap<String, String>(); for (MetadataColumn metaCol : columnMap.keySet()) { colName2IndexMap.put(metaCol.getName(), columnMap.get(metaCol)); } BlockingKeyHandler executeGenerateBlockingAction = new BlockingKeyHandler(blockingKeyData, colName2IndexMap); if (hasBlockingKey()) { executeGenerateBlockingAction.setInputData(matchRows); executeGenerateBlockingAction.run(); } return executeGenerateBlockingAction; } /** * DOC zshen Comment method "hasBlockingKey". * * @return */ private boolean hasBlockingKey() { List<KeyDefinition> inputElement = (List<KeyDefinition>) tableComposite.getInput(); if (inputElement.size() > 0) { return true; } return false; } public boolean createBlockingKey(String columnName) { return tableComposite.addKeyDefinition(columnName, getBlockKeyDefinitionList()); } public void removeBlockingKey(String columnName) { tableComposite.removeKeyDefinition(columnName, getBlockKeyDefinitionList()); } public void removeBlockingKey(BlockKeyDefinition blockKeyDef) { tableComposite.removeKeyDefinition(blockKeyDef, getBlockKeyDefinitionList()); } public void removeAllBlockingKey() { getBlockKeyDefinitionList().clear(); redrawnSubTableContent(); } /* * (non-Javadoc) * * @see * org.talend.dataquality.record.linkage.ui.section.AbstractMatchAnaysisTableSection#isKeyDefinitionAdded(java.lang * .String) */ @Override public Boolean isKeyDefinitionAdded(String columnName) { Boolean isAdded = Boolean.FALSE; RecordMatchingIndicator recordMatchingIndicator = MatchRuleAnlaysisUtils.getRecordMatchIndicatorFromAna(analysis); List<BlockKeyDefinition> keyDefs = recordMatchingIndicator.getBuiltInMatchRuleDefinition().getBlockKeys(); for (KeyDefinition keyDef : keyDefs) { // the key's name can NOT be same, the column can be same if (StringUtils.equals(columnName, keyDef.getName())) { isAdded = Boolean.TRUE; break; } } return isAdded; } /* * (non-Javadoc) * * @see org.talend.dataquality.record.linkage.ui.section.AbstractMatchAnaysisTableSection#addTableItem() */ @Override public void addTableItem() { this.createBlockingKey(StringUtils.EMPTY); listeners.firePropertyChange(MatchAnalysisConstant.ISDIRTY_PROPERTY, true, false); } /* * (non-Javadoc) * * @see org.talend.dataquality.record.linkage.ui.section.AbstractMatchAnaysisTableSection#removeTableItem() */ @Override public void removeTableItem() { boolean success = false; ISelection selectItems = tableComposite.getSelectItems(); if (selectItems instanceof StructuredSelection) { Iterator<BlockKeyDefinition> iterator = ((StructuredSelection) selectItems).iterator(); while (iterator.hasNext()) { BlockKeyDefinition next = iterator.next(); removeBlockingKey(next); success = true; } if (success) { listeners.firePropertyChange(MatchAnalysisConstant.ISDIRTY_PROPERTY, true, false); listeners.firePropertyChange(MatchAnalysisConstant.MATCH_RULE_TAB_SWITCH, true, false); } } } /* * (non-Javadoc) * * @see org.talend.dataquality.record.linkage.ui.section.AbstractMatchAnaysisTableSection#moveUpTableItem() */ @Override public void moveUpTableItem() { ISelection selectItems = tableComposite.getSelectItems(); if (selectItems instanceof StructuredSelection) { if (selectItems.isEmpty()) { return; } List<BlockKeyDefinition> currentElements = getMatchRuleDefinition().getBlockKeys(); List<BlockKeyDefinition> blockKeyDefinitionlist = ((StructuredSelection) selectItems).toList(); for (int index = 0; index < blockKeyDefinitionlist.size(); index++) { if (!isSameWithCurrentModel(currentElements.get(index), blockKeyDefinitionlist.get(index))) { continue; } BlockKeyDefinition next = blockKeyDefinitionlist.get(index); tableComposite.moveUpKeyDefinition(next, currentElements); } tableComposite.selectAllItem(((StructuredSelection) selectItems).toList()); } } /** * /* (non-Javadoc) * * @see org.talend.dataquality.record.linkage.ui.section.AbstractMatchAnaysisTableSection#moveDownTableItem() */ @Override public void moveDownTableItem() { ISelection selectItems = tableComposite.getSelectItems(); if (selectItems instanceof StructuredSelection) { if (selectItems.isEmpty()) { return; } List<BlockKeyDefinition> currentElements = getMatchRuleDefinition().getBlockKeys(); List<BlockKeyDefinition> blockKeyDefinitionlist = ((StructuredSelection) selectItems).toList(); for (int index = blockKeyDefinitionlist.size() - 1; 0 <= index; index--) { if (!isSameWithCurrentModel(currentElements.get(currentElements.size() - blockKeyDefinitionlist.size() + index), blockKeyDefinitionlist.get(index))) { continue; } BlockKeyDefinition next = blockKeyDefinitionlist.get(index); tableComposite.moveDownKeyDefinition(next, currentElements); } tableComposite.selectAllItem(((StructuredSelection) selectItems).toList()); } } /** * get all columns which is selected as blocking key * * @return */ public List<String> getSelectedColumnAsBlockKeys() { List<String> keyColumns = new ArrayList<String>(); RecordMatchingIndicator recordMatchingIndicator = MatchRuleAnlaysisUtils.getRecordMatchIndicatorFromAna(analysis); List<BlockKeyDefinition> keyDefs = recordMatchingIndicator.getBuiltInMatchRuleDefinition().getBlockKeys(); if (keyDefs.size() > 0) { for (KeyDefinition keydef : keyDefs) { keyColumns.add(keydef.getColumn()); } } return keyColumns; } /** * if overwrite: need to delete all current keyss, and insert the keys according to the parameter:matchRule; else: * only add the keys in the parameter matchrule, to the current keys. * * @param matchRule * @param overwrite */ public void importMatchRule(MatchRuleDefinition matchRule, boolean overwrite) { if (overwrite) { // clear current keys this.removeAllBlockingKey(); } List<String> conflictKeys = new ArrayList<String>(); for (BlockKeyDefinition blockKey : matchRule.getBlockKeys()) { if (!overwrite && isKeyDefinitionAdded(blockKey.getName())) { // if conflict with current ones, do not import conflictKeys.add(blockKey.getName()); continue; } BlockKeyDefinition blockKeyDefinition = EcoreUtil.copy(blockKey); setColumnValueIfMatch(blockKeyDefinition); tableComposite.addKeyDefinition(blockKeyDefinition, this.getMatchRuleDefinition().getBlockKeys()); } // if there are some conflict keys, popup to let the user know if (conflictKeys.size() > 0) { StringBuffer names = new StringBuffer(); for (String name : conflictKeys) { names.append(name); names.append(PluginConstant.COMMA_STRING); } if (names.length() > 0) { names.deleteCharAt(names.lastIndexOf(PluginConstant.COMMA_STRING)); } MessageDialog.openWarning(null, DefaultMessagesImpl.getString("BlockingKeySection.conflictImport"), //$NON-NLS-1$ DefaultMessagesImpl.getString("BlockingKeySection.conflictImportKeys") + names.toString()); //$NON-NLS-1$ } } /* * (non-Javadoc) * * @see org.talend.dataquality.record.linkage.ui.section.AbstractMatchAnaysisTableSection#checkResultStatus() */ @Override public ReturnCode checkResultStatus() { ReturnCode returnCode = new ReturnCode(false); List<String> uniqueNameList = new ArrayList<String>(); List<String> duplicateNameList = new ArrayList<String>(); for (BlockKeyDefinition bdk : getBlockKeyDefinitionList()) { String currentName = bdk.getName(); if (currentName.equals(StringUtils.EMPTY)) { returnCode.setMessage(DefaultMessagesImpl.getString("BlockingKeySection.emptyKeys.message", getSectionName())); //$NON-NLS-1$ return returnCode; } if (checkColumnNameIsEmpty(bdk)) { returnCode.setMessage(DefaultMessagesImpl.getString("BlockingKeySection.emptyColumn.message", getSectionName())); //$NON-NLS-1$ return returnCode; } boolean currentNameIsDuplicate = false; for (String uniqueName : uniqueNameList) { if (currentName.equals(uniqueName)) { duplicateNameList.add(currentName); currentNameIsDuplicate = true; } } if (!currentNameIsDuplicate) { uniqueNameList.add(currentName); } } if (duplicateNameList.size() > 0) { returnCode.setMessage(DefaultMessagesImpl.getString("BlockingKeySection.duplicateKeys.message", getSectionName())); //$NON-NLS-1$ return returnCode; } else { returnCode.setOk(true); return returnCode; } } /** * DOC zshen Comment method "checkColumnName". * * @param bdk */ protected boolean checkColumnNameIsEmpty(BlockKeyDefinition bdk) { String columnName = bdk.getColumn(); if (columnName == null || columnName.equals(StringUtils.EMPTY)) { return true; } return false; } /** * * clear blocking key chart. */ @Override public void clearChart() { blockingKeyDataChart.clearChart(); } }