// ============================================================================
//
// 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.action.actions;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.navigator.CommonViewer;
import org.eclipse.ui.part.ISetSelectionTarget;
import org.talend.commons.exception.BusinessException;
import org.talend.core.model.properties.Item;
import org.talend.core.model.properties.Property;
import org.talend.core.model.repository.ERepositoryObjectType;
import org.talend.core.model.repository.IRepositoryViewObject;
import org.talend.cwm.db.connection.ConnectionUtils;
import org.talend.dataprofiler.core.CorePlugin;
import org.talend.dataprofiler.core.PluginConstant;
import org.talend.dataprofiler.core.exception.ExceptionFactory;
import org.talend.dataprofiler.core.exception.ExceptionHandler;
import org.talend.dataprofiler.core.i18n.internal.DefaultMessagesImpl;
import org.talend.dataprofiler.core.ui.action.actions.handle.ActionHandleFactory;
import org.talend.dataprofiler.core.ui.action.actions.handle.IDuplicateHandle;
import org.talend.dataprofiler.core.ui.utils.RepNodeUtils;
import org.talend.dataprofiler.core.ui.views.resources.IRepositoryObjectCRUDAction;
import org.talend.dataquality.properties.TDQFileItem;
import org.talend.dq.helper.PropertyHelper;
import org.talend.dq.helper.RepositoryNodeHelper;
import org.talend.dq.nodes.AnalysisRepNode;
import org.talend.dq.nodes.AnalysisSubFolderRepNode;
import org.talend.dq.nodes.DBConnectionRepNode;
import org.talend.dq.nodes.ReportRepNode;
import org.talend.dq.nodes.ReportSubFolderRepNode;
import org.talend.dq.nodes.SysIndicatorDefinitionRepNode;
import org.talend.repository.model.IRepositoryNode;
import org.talend.repository.model.RepositoryNode;
import org.talend.resource.EResourceConstant;
/**
* DOC bZhou class global comment. Detailled comment
*/
public class DuplicateAction extends org.talend.core.repository.ui.actions.DuplicateAction {
private IRepositoryNode[] nodeArray = new IRepositoryNode[0];
private IRepositoryObjectCRUDAction repositoryObjectCRUD = RepNodeUtils.getRepositoryObjectCRUD();
private Logger log = Logger.getLogger(DuplicateAction.class);
public DuplicateAction(IRepositoryNode[] nodeArray) {
super();
this.nodeArray = nodeArray;
}
/*
* (non-Javadoc)
*
* @see org.talend.repository.ui.actions.AContextualAction#doRun()
*/
@Override
protected void doRun() {
repositoryObjectCRUD.refreshDQViewForRemoteProject();
// ADD msjian TDQ-7006 2013-7-24: after refresh get the selection to check.
if (!repositoryObjectCRUD.isSelectionAvailable()) {
repositoryObjectCRUD.showWarningDialog();
return;
}
// TDQ-7006~
try {
String newLabel = null;
Item lastDuplicateItem = null;
for (final IRepositoryNode node : nodeArray) {
IRepositoryViewObject viewObject = node.getObject();
validateOriginalObject(viewObject);
final IDuplicateHandle handle = ActionHandleFactory.getInstance().createDuplicateHandle(node);
if (handle != null) {
// MOD msjian TDQ-4672 2012-2-17: modified the check duplicate name method
String initLabel = generateInitialLabel(node);
InputDialog dialog = createInputNewNameDialog(node, initLabel);
// TDQ-4672~
if (dialog.open() == Window.OK) {
newLabel = dialog.getValue().trim();
lastDuplicateItem = handle.duplicateItem(viewObject.getProperty().getItem(), newLabel);
}
} else {
// if can not find the related handler for the current node, log it and continue for others
log.error(DefaultMessagesImpl.getString("DuplicateAction.HandleNull", node.getLabel()));//$NON-NLS-1$
}
}
// if the user select cancel, the item will be null, then no need to refresh.
if (lastDuplicateItem != null) {
CorePlugin.getDefault().refreshWorkSpace();
// show the last new success duplicated one as selected on the repository view.
selectAndReveal(newLabel, lastDuplicateItem);
}
} catch (BusinessException e) {
ExceptionHandler.process(e, Level.FATAL);
}
}
private InputDialog createInputNewNameDialog(final IRepositoryNode node, String initLabel) {
return new InputDialog(
CorePlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(),
DefaultMessagesImpl.getString("DuplicateAction.InputDialog"), DefaultMessagesImpl.getString("DuplicateAction.InpurtDesc"), initLabel, //$NON-NLS-1$ //$NON-NLS-2$
new IInputValidator() {
public String isValid(String newText) {
// ADD msjian TDQ-7579: fix the name can not be empty
if (PluginConstant.EMPTY_STRING.equals(newText.trim())) {
return DefaultMessagesImpl.getString("DuplicateAction.LabelEmpty"); //$NON-NLS-1$
}
// TDQ-7579~
// MOD msjian TDQ-7218 2013-5-31: when dulicate a system indicator, should check
// whether exist in UDI.
ERepositoryObjectType contentType = node.getContentType();
if (node instanceof SysIndicatorDefinitionRepNode) {
contentType = ERepositoryObjectType.TDQ_USERDEFINE_INDICATORS;
}
if (PropertyHelper.existDuplicateName(newText.trim(), null, contentType)) {
return DefaultMessagesImpl.getString("DuplicateAction.LabelExists"); //$NON-NLS-1$
}
// TDQ-7218~
return null;
}
});
}
private void validateOriginalObject(IRepositoryViewObject viewObject) throws BusinessException {
if (viewObject == null || viewObject.getProperty() == null || viewObject.getProperty().getItem() == null) {
BusinessException createBusinessException = ExceptionFactory.getInstance().createBusinessException(
DefaultMessagesImpl.getString("DuplicateAction.ObjectNull")); //$NON-NLS-1$
throw createBusinessException;
}
}
/**
* DOC msjian Comment method "generateInitialLabel".
*
* check the duplicate name by node.
*
* @param node
* @return
*/
private String generateInitialLabel(IRepositoryNode node) {
String initNameValue = "Copy_of_" + node.getLabel(); //$NON-NLS-1$
ERepositoryObjectType type = node.getContentType();
if (!PropertyHelper.existDuplicateName(initNameValue, null, type)) {
return initNameValue;
} else {
char j = 'a';
String temp = initNameValue;
while (PropertyHelper.existDuplicateName(temp, null, type)) {
if (j <= 'z') {
temp = initNameValue + "_" + (j++) + ""; //$NON-NLS-1$ //$NON-NLS-2$
}
}
return temp;
}
}
/**
* DOC bZhou Comment method "selectAndReveal".
*
* Selects and reveals the newly added resource in all parts of the active workbench window's active page.
*
* @param newLabel
*
* @param duplicateObject
* @throws BusinessException
*/
private void selectAndReveal(String newLabel, Item duplicateItem) throws BusinessException {
IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
IWorkbenchPage page = workbenchWindow.getActivePage();
IWorkbenchPart activePart = page.getActivePart();
RepositoryNode recursiveFind = null;
recursiveFind = getSelctionNode(newLabel, duplicateItem.getProperty());
if (recursiveFind != null) {
if (recursiveFind instanceof AnalysisRepNode || recursiveFind instanceof AnalysisSubFolderRepNode
|| recursiveFind instanceof ReportRepNode || recursiveFind instanceof ReportSubFolderRepNode) {
CorePlugin.getDefault().refreshDQView(RepositoryNodeHelper.findNearestSystemFolderNode(recursiveFind));
} else {
CorePlugin.getDefault().refreshDQView(recursiveFind.getParent());
refreshHiveConnectionParent(recursiveFind);
}
// MOD qiongli TDQ-5391 Avoid 'recursiveFind' to casue NPE .
if (activePart instanceof ISetSelectionTarget) {
ISelection selection = new StructuredSelection(recursiveFind);
((ISetSelectionTarget) activePart).selectReveal(selection);
}
}
}
/**
* if the duplicate hive connection has its related hadoop cluster, need to refresh it.
*
* @param recursiveFind
*/
private void refreshHiveConnectionParent(RepositoryNode recursiveFind) {
if (recursiveFind instanceof DBConnectionRepNode) {
String hcId = ConnectionUtils.getHadoopClusterIDOfHive(recursiveFind.getObject());
if (!StringUtils.isBlank(hcId)) {
IRepositoryNode HClusterFolderNode = RepositoryNodeHelper.getMetadataFolderNode(EResourceConstant.HADOOP_CLUSTER);
List<IRepositoryNode> children = HClusterFolderNode.getChildren();
for (IRepositoryNode hcluster : children) {
if (StringUtils.equals(hcId, hcluster.getId())) {
CorePlugin.getDefault().refreshDQView(hcluster);
break;
}
}
}
}
}
private RepositoryNode getSelctionNode(String newLabel, Property property) throws BusinessException {
RepositoryNode recursiveFind = null;
if (property != null) {
if (property.getItem() instanceof TDQFileItem) {
// if the model element is null, means that it is a file item.
recursiveFind = findNodeForTDQFileItem(newLabel);
} else {
// find the related node by the model element
recursiveFind = RepositoryNodeHelper.recursiveFind(property);
}
}
if (recursiveFind == null) {
BusinessException createBusinessException = ExceptionFactory.getInstance().createBusinessException(
DefaultMessagesImpl.getString("DuplicateAction.NodeNull", newLabel));//$NON-NLS-1$
throw createBusinessException;
}
RepositoryNode parent = recursiveFind.getParent();
CommonViewer dqCommonViewer = RepositoryNodeHelper.getDQCommonViewer();
if (dqCommonViewer != null && !dqCommonViewer.getExpandedState(parent)) {
dqCommonViewer.setExpandedState(parent, true);
}
return recursiveFind;
}
private RepositoryNode findNodeForTDQFileItem(String label) {
IRepositoryNode librariesFolderNode = RepositoryNodeHelper.getLibrariesFolderNode(EResourceConstant.SOURCE_FILES);
List<? extends RepositoryNode> childrenList = RepositoryNodeHelper.getSourceFileRepNodes(librariesFolderNode, true);
RepositoryNode node = findNodeInList(label, childrenList);
if (node == null) {
librariesFolderNode = RepositoryNodeHelper.getLibrariesFolderNode(EResourceConstant.JRXML_TEMPLATE);
List<? extends RepositoryNode> childrenList2 = RepositoryNodeHelper.getJrxmlFileRepNodes(librariesFolderNode, true);
node = findNodeInList(label, childrenList2);
}
return node;
}
private RepositoryNode findNodeInList(String label, List<? extends RepositoryNode> childrenList) {
// MOD msjian TDQ-4830 2012-5-25: fixed a NPE and should consider the subfolder
if (childrenList != null && childrenList.size() > 0) {
for (RepositoryNode node : childrenList) {
if (label != null && label.equals(node.getLabel())) {
return node;
}
}
}
return null;
}
}