// ============================================================================ // // Copyright (C) 2006-2012 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.designer.core.ui.editor.cmd; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.gef.commands.Command; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PlatformUI; import org.talend.core.GlobalServiceRegister; import org.talend.core.model.components.IODataComponent; import org.talend.core.model.components.IODataComponentContainer; import org.talend.core.model.metadata.ColumnNameChanged; import org.talend.core.model.metadata.IMetadataColumn; import org.talend.core.model.metadata.IMetadataTable; import org.talend.core.model.metadata.MetadataToolHelper; import org.talend.core.model.process.EConnectionType; import org.talend.core.model.process.EParameterFieldType; import org.talend.core.model.process.IConnection; import org.talend.core.model.process.IConnectionCategory; import org.talend.core.model.process.IElementParameter; import org.talend.core.model.process.IExternalData; import org.talend.core.model.process.IExternalNode; import org.talend.core.model.process.INode; import org.talend.core.model.process.INodeConnector; import org.talend.core.service.IXmlMapService; import org.talend.designer.core.i18n.Messages; import org.talend.designer.core.model.components.EParameterName; import org.talend.designer.core.model.components.EmfComponent; import org.talend.designer.core.ui.editor.connections.Connection; import org.talend.designer.core.ui.editor.nodes.Node; import org.talend.designer.core.ui.editor.process.Process; import org.talend.designer.core.ui.editor.properties.controllers.ColumnListController; import org.talend.designer.core.ui.views.CodeView; import org.talend.designer.core.ui.views.properties.ComponentSettings; /** * Command that will change the datas stored for an external node. * * $Id: ExternalNodeChangeCommand.java 86388 2012-06-27 10:08:36Z hwang $ * */ public class ExternalNodeChangeCommand extends Command { private Node node; private IExternalData oldExternalData; private List<IMetadataTable> oldMetaDataList; private IExternalData newExternalData; private List<IMetadataTable> newMetaDataList; private Map<Connection, IODataComponent> connectionsToDelete; private List<ChangeMetadataCommand> metadataOutputChanges = new ArrayList<ChangeMetadataCommand>(); private Map<Connection, IMetadataTable> metadataInputChanges = new HashMap<Connection, IMetadataTable>(); private Map<Connection, Boolean> metadataInputWasRepository = new HashMap<Connection, Boolean>(); private IODataComponentContainer inAndOut; private Boolean propagate; private boolean forTemlate; private boolean isMetaLanguage = false; @SuppressWarnings("unchecked") public ExternalNodeChangeCommand(Node node, IExternalNode externalNode, boolean... bs) { if (bs.length > 0) { this.isMetaLanguage = bs[0]; } this.node = node; this.inAndOut = externalNode.getIODataComponents(); this.oldExternalData = node.getExternalData(); oldMetaDataList = node.getMetadataList(); newExternalData = externalNode.getExternalData(); newMetaDataList = externalNode.getMetadataList(); init(); } @SuppressWarnings("unchecked") public ExternalNodeChangeCommand(Node node, IExternalNode externalNode, IExternalData oldExternalData, boolean... bs) { if (bs.length > 0) { this.isMetaLanguage = bs[0]; } this.node = node; this.inAndOut = externalNode.getIODataComponents(); this.oldExternalData = oldExternalData; oldMetaDataList = node.getMetadataList(); newExternalData = externalNode.getExternalData(); newMetaDataList = externalNode.getMetadataList(); init(); } private void init() { connectionsToDelete = new HashMap<Connection, IODataComponent>(); for (IODataComponent dataComponent : inAndOut.getOuputs()) { IConnection connection = dataComponent.getConnection(); boolean metadataExists = false; for (IMetadataTable metadata : newMetaDataList) { if (connection.getMetadataTable().getTableName().equals(metadata.getTableName())) { metadataExists = true; } } if (!metadataExists && (connection instanceof Connection)) { connectionsToDelete.put((Connection) connection, dataComponent); } } for (Connection connection : (List<Connection>) node.getIncomingConnections()) { String schemaType = (String) connection.getSource().getPropertyValue(EParameterName.SCHEMA_TYPE.getName()); if (schemaType != null) { if (schemaType.equals(EmfComponent.REPOSITORY)) { String metaRepositoryName = (String) connection.getSource().getPropertyValue( EParameterName.REPOSITORY_SCHEMA_TYPE.getName()); IMetadataTable repositoryMetadata = MetadataToolHelper.getMetadataFromRepository(metaRepositoryName); if (repositoryMetadata == null) { connection.getSource().setPropertyValue(EParameterName.SCHEMA_TYPE.getName(), EmfComponent.BUILTIN); } else { repositoryMetadata = repositoryMetadata.clone(); repositoryMetadata.setTableName(connection.getSource().getUniqueName()); if (!repositoryMetadata.sameMetadataAs(connection.getMetadataTable())) { connection.getSource().setPropertyValue(EParameterName.SCHEMA_TYPE.getName(), EmfComponent.BUILTIN); } } } } } setLabel(Messages.getString("ExternalNodeChangeCommand.modifaicationFrom") + node.getUniqueName()); //$NON-NLS-1$ } private void refreshCodeView() { IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); IViewPart view = page.findView(CodeView.ID); if (view != null) { CodeView codeView = (CodeView) view; codeView.refresh(); } } private boolean getPropagate() { if (propagate == null) { propagate = MessageDialog .openQuestion( new Shell(), Messages.getString("ExternalNodeChangeCommand.propagate"), Messages.getString("ExternalNodeChangeCommand.propagateMessage")); //$NON-NLS-1$ //$NON-NLS-2$ } return propagate; } private void propagateInput() { for (Connection connection : (List<Connection>) node.getIncomingConnections()) { if (connection.getLineStyle().hasConnectionCategory(IConnectionCategory.DATA)) { IODataComponent currentIO = inAndOut.getDataComponent(connection); currentIO.setColumnOption(IMetadataColumn.OPTIONS_NONE); if (currentIO.hasChanged()) { IMetadataTable metadata = inAndOut.getTable(connection); INode sourceNode = currentIO.getSource(); sourceNode.metadataOutputChanged(currentIO, currentIO.getName()); // It's better to clone, because will change that, if apply, bug 13325 // IMetadataTable oldMetadata = connection.getMetadataTable().clone(); IMetadataTable newMetadata = metadata.clone(); currentIO.setTable(newMetadata); String schemaType = (String) connection.getSource().getPropertyValue(EParameterName.SCHEMA_TYPE.getName()); if (schemaType != null) { // if there is a SCHEMA_TYPE, then switch it to BUILT_IN if REPOSITORY is set. if (schemaType.equals(EmfComponent.REPOSITORY)) { connection.getSource().setPropertyValue(EParameterName.SCHEMA_TYPE.getName(), EmfComponent.BUILTIN); metadataInputWasRepository.put(connection, Boolean.TRUE); } } // for bug 9849 List<IMetadataColumn> listColumns = connection.getMetadataTable().getListColumns(); boolean empty = listColumns.isEmpty(); // before is empty List<IMetadataColumn> newListColumns = newMetadata.getListColumns(); List<ColumnNameChanged> columnNameChangeds = new ArrayList<ColumnNameChanged>(); int size = listColumns.size(); int newSize = newListColumns.size(); if (newSize < size) { size = newSize; } for (int i = 0; i < size; i++) { IMetadataColumn metadataColumn = listColumns.get(i); IMetadataColumn newMetadataColumn = newListColumns.get(i); if (metadataColumn != null && newMetadataColumn != null) { String oldLabel = metadataColumn.getLabel(); String newLabel = newMetadataColumn.getLabel(); if (oldLabel != null && !oldLabel.equals(newLabel)) { columnNameChangeds.add(new ColumnNameChanged(oldLabel, newLabel)); } } } connection.getMetadataTable().setListColumns(newListColumns); ColumnListController.updateColumnList(sourceNode, columnNameChangeds, false); if (empty) { // trace init connection.initTraceParamters(); } } } } } @Override public void execute() { propagateInput(); // bug 0020749 if (!oldMetaDataList.isEmpty() && !newMetaDataList.isEmpty() && !oldMetaDataList.get(0).sameMetadataAs(newMetaDataList.get(0))) { node.setPropertyValue(EParameterName.SCHEMA_TYPE.getName(), EmfComponent.BUILTIN); } metadataOutputChanges.clear(); List<IConnection> initTraceList = new ArrayList<IConnection>(); for (IConnection connection : node.getOutgoingConnections()) { if (connection.getLineStyle().hasConnectionCategory(IConnectionCategory.DATA)) { IODataComponent dataComponent = inAndOut.getDataComponent(connection); if (!connection.getMetadataTable().sameMetadataAs(dataComponent.getTable())) { IMetadataTable table = connection.getMetadataTable(); if (table == null || table.getListColumns().isEmpty()) { initTraceList.add(connection); } boolean openDialog = false; if (isForTemlate()) { openDialog = true; } else { openDialog = getPropagate(); } if (openDialog) { IElementParameter schemaParam = null; if (connection != null) { IMetadataTable connTable = connection.getMetadataTable(); IMetadataTable dataTable = dataComponent.getTable(); for (IElementParameter param : ((Node) connection.getTarget()).getElementParameters()) { if (param.getFieldType().equals(EParameterFieldType.SCHEMA_TYPE) && param.getContext().equals(connection.getConnectorName())) { schemaParam = param; break; } } if (schemaParam != null) { ChangeMetadataCommand cmd = new ChangeMetadataCommand(connection.getTarget(), schemaParam, connTable, dataTable); cmd.execute(true); metadataOutputChanges.add(cmd); } for (IElementParameter param : ((Node) connection.getSource()).getElementParameters()) { if (param.getFieldType().equals(EParameterFieldType.SCHEMA_TYPE) && param.getContext().equals(connection.getConnectorName())) { schemaParam = param; break; } } if (schemaParam != null) { ChangeMetadataCommand cmd = new ChangeMetadataCommand(connection.getSource(), schemaParam, connTable, dataTable); cmd.execute(true); metadataOutputChanges.add(cmd); } } } else { // no matter propagate or not the metadata change will be propagate to xmlmap emf data final Node target = (Node) connection.getTarget(); if (target != null && target.getExternalNode() != null) { if (GlobalServiceRegister.getDefault().isServiceRegistered(IXmlMapService.class)) { final IXmlMapService service = (IXmlMapService) GlobalServiceRegister.getDefault().getService( IXmlMapService.class); if (service.isXmlMapComponent(target.getExternalNode())) { IODataComponent output = new IODataComponent(connection, dataComponent.getTable()); target.metadataInputChanged(output, connection.getUniqueName()); } } } } } if (connection instanceof Connection) { ((Connection) connection).updateName(); } } } node.setExternalData(newExternalData); /* * It's better to clone, because will change that, if apply, bug 13325 */ // node.setExternalData(newExternalData.clone()); //should test later. List<IMetadataTable> cloneNewMetadata = new ArrayList<IMetadataTable>(); if (newMetaDataList != null) { for (IMetadataTable t : newMetaDataList) { cloneNewMetadata.add(t.clone(true)); } } node.setMetadataList(cloneNewMetadata); // init trace for (IConnection conn : initTraceList) { if (conn instanceof Connection) { ((Connection) conn).initTraceParamters(); } } for (Connection connection : connectionsToDelete.keySet()) { connection.disconnect(); INode prevNode = connection.getSource(); INodeConnector nodeConnectorSource, nodeConnectorTarget; nodeConnectorSource = prevNode.getConnectorFromType(connection.getLineStyle()); nodeConnectorSource.setCurLinkNbOutput(nodeConnectorSource.getCurLinkNbOutput() - 1); INode nextNode = connection.getTarget(); nodeConnectorTarget = nextNode.getConnectorFromType(connection.getLineStyle()); nodeConnectorTarget.setCurLinkNbInput(nodeConnectorTarget.getCurLinkNbInput() - 1); inAndOut.getOuputs().remove(connectionsToDelete.get(connection)); } ((Process) node.getProcess()).checkProcess(); if (!isMetaLanguage) { refreshCodeView(); ComponentSettings.switchToCurComponentSettingsView(); } } @Override public void undo() { for (Connection connection : (List<Connection>) node.getIncomingConnections()) { if (connection.getLineStyle().equals(EConnectionType.FLOW_MAIN) || connection.getLineStyle().equals(EConnectionType.FLOW_REF) || connection.getLineStyle().equals(EConnectionType.TABLE)) { IODataComponent currentIO = inAndOut.getDataComponent(connection); if (currentIO.hasChanged()) { // IMetadataTable metadata = inAndOut.getTable(connection); INode sourceNode = currentIO.getSource(); sourceNode.metadataOutputChanged(currentIO, currentIO.getName()); // IMetadataTable oldMetadata = connection.getMetadataTable().clone(); // currentIO.setTable(oldMetadata); // connection.getMetadataTable().setListColumns(metadata.getListColumns()); IMetadataTable oldMetadata = currentIO.getConnMetadataTable(); // currentIO.setTable(oldMetadata); connection.getMetadataTable().setListColumns(oldMetadata.getListColumns()); if (metadataInputWasRepository.get(connection) != null) { connection.getSource().setPropertyValue(EParameterName.SCHEMA_TYPE.getName(), EmfComponent.REPOSITORY); } } } } metadataInputWasRepository.clear(); node.setExternalData(oldExternalData); node.setMetadataList(oldMetaDataList); for (Connection connection : connectionsToDelete.keySet()) { connection.reconnect(); Node prevNode = (Node) connection.getSource(); INodeConnector nodeConnectorSource, nodeConnectorTarget; nodeConnectorSource = prevNode.getConnectorFromType(connection.getLineStyle()); nodeConnectorSource.setCurLinkNbOutput(nodeConnectorSource.getCurLinkNbOutput() + 1); Node nextNode = (Node) connection.getTarget(); nodeConnectorTarget = nextNode.getConnectorFromType(connection.getLineStyle()); nodeConnectorTarget.setCurLinkNbInput(nodeConnectorTarget.getCurLinkNbInput() + 1); if (connectionsToDelete.get(connection) != null) { inAndOut.getOuputs().add(connectionsToDelete.get(connection)); } } for (ChangeMetadataCommand cmd : metadataOutputChanges) { cmd.undo(); } ((Process) node.getProcess()).checkProcess(); if (!isMetaLanguage) { refreshCodeView(); } } public boolean isForTemlate() { return this.forTemlate; } public void setForTemlate(boolean forTemlate) { this.forTemlate = forTemlate; } }