package org.talend.designer.core.ui.editor.jobletcontainer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.talend.core.GlobalServiceRegister;
import org.talend.core.model.metadata.IMetadataTable;
import org.talend.core.model.process.IConnection;
import org.talend.core.model.process.IElement;
import org.talend.core.model.process.IElementParameter;
import org.talend.core.model.process.INode;
import org.talend.core.model.process.INodeConnector;
import org.talend.core.model.process.IProcess;
import org.talend.core.model.process.IProcess2;
import org.talend.core.ui.IJobletProviderService;
import org.talend.designer.core.DesignerPlugin;
import org.talend.designer.core.model.components.EParameterName;
import org.talend.designer.core.ui.editor.cmd.JobletConnectionReconnectCommand;
import org.talend.designer.core.ui.editor.connections.Connection;
import org.talend.designer.core.ui.editor.nodecontainer.NodeContainer;
import org.talend.designer.core.ui.editor.nodes.Node;
import org.talend.designer.core.ui.preferences.TalendDesignerPrefConstants;
public class JobletContainer extends NodeContainer {
public static final String UPDATE_JOBLET_CONTENT = "UPDATE_JOBLET_CONTENT"; //$NON-NLS-1$
public static final String UPDATE_JOBLET_DATA = "UPDATE_JOBLET_DATA"; //$NON-NLS-1$
public static final String UPDATE_JOBLET_CONNECTIONS = "UPDATE_JOBLET_CONNECTIONS"; //$NON-NLS-1$
public static final String UPDATE_JOBLET_TITLE_COLOR = "UPDATE_JOBLET_TITLE_COLOR"; //$NON-NLS-1$
public static final String UPDATE_JOBLET_DISPLAY = "UPDATE_JOBLET_DISPLAY"; //$NON-NLS-1$
protected List<Node> nodes = new ArrayList<Node>();
private List<NodeContainer> nodeContainers = new ArrayList<NodeContainer>();
private IProcess2 process;
private Node node;
private Rectangle jobletRectangle;
private int changeWidth;
private int changeHeight;
private boolean hasChange;
private boolean needchangeLock = true;
protected List<IElement> jobletElements = new ArrayList<IElement>();
public JobletContainer(Node node) {
super(node);
this.node = node;
}
/**
* Getter for process.
*
* @return the process
*/
public IProcess2 getProcess() {
if (process == null) {
IProcess iPro = node.getComponent().getProcess();
if (iPro instanceof IProcess2) {
return (IProcess2) iPro;
}
}
return this.process;
}
public Rectangle getJobletUnion(Rectangle jobletNodeRec, Rectangle rect) {
// if (rect == null || rect.isEmpty())
// return new Rectangle(this);
Rectangle union = new Rectangle(jobletNodeRec.x, jobletNodeRec.y, 0, 0);
union.width = Math.max(jobletNodeRec.x + jobletNodeRec.width, rect.x + rect.width) - union.x;
union.height = Math.max(jobletNodeRec.y + jobletNodeRec.height, rect.y + rect.height) - union.y;
return union;
}
/**
* DOC hwang Comment method "getJobletContainerRectangle".
*
* @return
*/
public Rectangle getJobletContainerRectangle() {
Rectangle totalRectangle = null;
boolean collapsed = isCollapsed();
if (!collapsed && nodeContainers.size() > 0) {
Rectangle jobletNodeRec = this.node.getNodeContainer().getNodeContainerRectangle();
for (NodeContainer container : nodeContainers) {
Rectangle curRect = container.getNodeContainerRectangle();
// if (container.getNode().isDesignSubjobStartNode()) {
// totalRectangle = curRect.getCopy();
// } else {
if (totalRectangle == null) {
totalRectangle = curRect.getCopy();
} else {
totalRectangle = totalRectangle.getUnion(curRect);
}
// }
}
// totalRectangle.setLocation(jobletNodeRec.getLocation());
} else if (node != null) {
NodeContainer container = node.getNodeContainer();
Rectangle curRect = container.getNodeContainerRectangle();
if (collapsed) {
totalRectangle = curRect.getCopy();
} else {
if (totalRectangle == null) {
totalRectangle = curRect.getCopy();
} else {
totalRectangle = totalRectangle.getUnion(curRect);
}
}
}
if (totalRectangle == null) {
return null;
}
if (jobletRectangle != null) {
if ((Math.abs(jobletRectangle.width - totalRectangle.width) != 0) || this.nodeContainers.size() == 1) {
changeWidth = Math.abs(jobletRectangle.width - totalRectangle.width);
}
if ((Math.abs(jobletRectangle.height - totalRectangle.height) != 0) || this.nodeContainers.size() == 1) {
changeHeight = Math.abs(jobletRectangle.height - totalRectangle.height);
}
}
jobletRectangle = totalRectangle.getCopy();
return totalRectangle;
}
public int getChangeWidth() {
return this.changeWidth;
}
public int getChangeHeight() {
return this.changeHeight;
}
public boolean isReadonly() {
return true;
}
@SuppressWarnings("unchecked")
public Node getJobletStartNode() {
if (getProcess() != null) {
if (getProcess().getSubjobContainers().size() > 0) {
String subjobStartUniqueName = (String) getProcess().getSubjobContainers().get(0)
.getPropertyValue(EParameterName.UNIQUE_NAME.getName());
if (getProcess() != null && (List<Node>) getProcess().getGraphicalNodes() != null) {
for (Node node : (List<Node>) getProcess().getGraphicalNodes()) {
if (node.getUniqueName() != null && node.getUniqueName().equals(subjobStartUniqueName)) {
return node;
}
}
}
}
} else if (node != null) {
return node;
}
return null;
}
@Override
public void setPropertyValue(String id, Object value) {
if (id.equals(EParameterName.COLLAPSED.getName())) {
// outputs.clear();
for (IConnection conn : node.getOutgoingConnections()) {
outputs.add(conn);
}
// inputs.clear();
for (IConnection conn : node.getIncomingConnections()) {
inputs.add(conn);
}
if (needchangeLock) {
if (!((Boolean) value)) {
IJobletProviderService service = (IJobletProviderService) GlobalServiceRegister.getDefault().getService(
IJobletProviderService.class);
if (service != null) {
service.lockJoblet(this.getNode());
}
} else {
IJobletProviderService service = (IJobletProviderService) GlobalServiceRegister.getDefault().getService(
IJobletProviderService.class);
if (service != null) {
service.unlockJoblet(node, true);
}
}
}
needchangeLock = true;
refreshJobletNodes(false, (Boolean) value);
if (!canCollapse()) {
Shell shell = Display.getCurrent().getActiveShell();
MessageDialog dlg = new MessageDialog(new Shell(shell), "ERROR", null, "Please attach connection!",
MessageDialog.QUESTION, new String[] { IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL }, 0);
dlg.open();
return;
}
super.setPropertyValue(id, value);
updateSubjobContainer();
transferLocation(false);
refreshJobletConnections();
fireStructureChange(EParameterName.COLLAPSED.getName(), this);
} else {
super.setPropertyValue(id, value);
}
}
public void updateJobletNodes(boolean update) {
// TDI-18915:no need "if(!isCollapsed()){}" here since it is only called in UpdateJobletNodeCommand and can not
// update the joblet NodeContainer in job when modify the joblet
refreshJobletNodes(update, isCollapsed());
updateSubjobContainer();
transferLocation(update);
refreshJobletConnections();
}
public void refreshJobletNodes(boolean update, boolean coll) {
if (!coll || update) {
JobletUtil util = new JobletUtil();
IProcess jobletProcess = this.getNode().getComponent().getProcess();
Set<IConnection> conns = new HashSet<IConnection>();
List<? extends INode> jobletNodes = jobletProcess.getGraphicalNodes();
boolean lockByOther = false;
if (jobletProcess instanceof IProcess2) {
lockByOther = util.lockByOthers(((IProcess2) jobletProcess).getProperty().getItem());
}
// List<NodeContainer> temList = new ArrayList<NodeContainer>(nodeContainers);
for (NodeContainer nc : nodeContainers) {
if (this.node.getProcess() instanceof IProcess2) {
((IProcess2) this.node.getProcess()).removeUniqueNodeName(nc.getNode().getUniqueName());
}
}
nodeContainers.clear();
jobletElements.clear();
// boolean canAdd = false;
// boolean canRemove = false;
for (INode inode : jobletNodes) {
// canAdd = util.canAdd(temList, inode);
if ((inode instanceof Node)) {
Node temNode = (Node) inode;
// if (canAdd) {
conns.addAll(temNode.getIncomingConnections());
conns.addAll(temNode.getOutgoingConnections());
Node jnode = util.cloneNode(temNode, this.node.getProcess(), lockByOther);
NodeContainer nodeContainer = util.cloneNodeContainer(temNode.getNodeContainer(), jnode);
jnode.setJobletnode(this.node);
jnode.setJoblet_unique_name(temNode.getUniqueName());
this.nodeContainers.add(nodeContainer);
this.jobletElements.add(jnode);
this.jobletElements.add(jnode.getNodeLabel());
this.jobletElements.add(jnode.getNodeError());
this.jobletElements.add(jnode.getNodeProgressBar());
// } else if (update) {
// for (NodeContainer nodeC : nodeContainers) {
// if (nodeC.getNode().getJoblet_unique_name().equals(temNode.getUniqueName())) {
// util.updateNode(nodeC.getNode(), temNode);
// break;
// }
// }
// }
}
}
// temList = new ArrayList<NodeContainer>(nodeContainers);
// for (NodeContainer nodeCon : temList) {
// Node temNode = nodeCon.getNode();
// canRemove = util.canDelete(jobletNodes, temNode);
// if (canRemove) {
// this.nodeContainers.remove(nodeCon);
// this.jobletElements.remove(temNode);
// this.jobletElements.remove(temNode.getNodeError());
// this.jobletElements.remove(temNode.getNodeLabel());
// this.jobletElements.remove(temNode.getNodeProgressBar());
// List<? extends IConnection> inCons = new ArrayList<IConnection>(temNode.getIncomingConnections());
// for (IConnection con : inCons) {
// con.getTarget().removeInput(con);
// }
// List<? extends IConnection> outCons = new ArrayList<IConnection>(temNode.getOutgoingConnections());
// for (IConnection con : outCons) {
// con.getTarget().removeOutput(con);
// }
// }
// }
for (Iterator<IConnection> iter = conns.iterator(); iter.hasNext();) {
IConnection con = iter.next();
String sourceName = con.getSource().getUniqueName();
String targetName = con.getTarget().getUniqueName();
Node sourceNode = null;
Node targetNode = null;
for (NodeContainer nodeC : nodeContainers) {
Node connNode = nodeC.getNode();
if (connNode.getJoblet_unique_name().equals(sourceName)) {
sourceNode = connNode;
}
if (connNode.getJoblet_unique_name().equals(targetName)) {
targetNode = connNode;
}
if (sourceNode != null && targetNode != null) {
util.cloneConnection(con, sourceNode, targetNode);
break;
}
}
}
}
}
private void transferLocation(boolean update) {
if (update) {
// do nothing
}
if (this.isCollapsed() == true) {
return;
}
if (this.nodeContainers.size() <= 0) {
return;
}
Point oragPoint = this.getNode().getLocation();
Node startNode = getJobletStartNode();
if (startNode == null) {
return;
}
Point stratPoint = startNode.getLocation();
int withe_x = oragPoint.x - stratPoint.x;
int hight_y = oragPoint.y - stratPoint.y;
for (NodeContainer nodeCon : this.nodeContainers) {
Node jobNode = nodeCon.getNode();
if (jobNode.getJoblet_unique_name().equals(startNode.getUniqueName())) {
jobNode.setLocation(oragPoint);
} else {
Point nodePoint = jobNode.getLocation();
jobNode.setLocation(new Point(nodePoint.x + withe_x, nodePoint.y + hight_y));
hasChange = true;
}
}
}
public void transferLocation(Point oldPos) {
if (this.isCollapsed() == true) {
return;
}
if (this.nodeContainers.size() <= 0) {
return;
}
Point oragPoint = this.getNode().getLocation();
Node startNode = getJobletStartNode();
if (startNode == null) {
return;
}
// Point stratPoint = startNode.getLocation();
int withe_x = oragPoint.x - oldPos.x;
int hight_y = oragPoint.y - oldPos.y;
for (NodeContainer nodeCon : this.nodeContainers) {
Node jobNode = nodeCon.getNode();
if (jobNode.getJoblet_unique_name().equals(startNode.getUniqueName())) {
jobNode.setLocation(oragPoint);
} else {
Point nodePoint = jobNode.getLocation();
jobNode.setLocation(new Point(nodePoint.x + withe_x, nodePoint.y + hight_y));
}
}
}
private void refreshJobletConnections() {
Iterator<IConnection> inIterator = inputs.iterator();
while (inIterator.hasNext()) {
IConnection conn = inIterator.next();
if (isCollapsed()) {
((Connection) conn).reconnect(conn.getSource(), this.node, conn.getLineStyle());
} else {
for (NodeContainer nodeContainer : this.nodeContainers) {
Node connNode = nodeContainer.getNode();
IElementParameter elePa = this.node.getElementParameter(connNode.getJoblet_unique_name());
if (elePa != null) {
IJobletProviderService service = (IJobletProviderService) GlobalServiceRegister.getDefault().getService(
IJobletProviderService.class);
IElementParameter elechild = null;
String uniqueName = null;
boolean isTri = service.isTriggerNode(connNode);
if (service != null && isTri) {
elechild = elePa.getChildParameters().get("COMPONENT_LIST");
uniqueName = conn.getMetaName();
} else {
elechild = elePa.getChildParameters().get("CONNECTION");
uniqueName = conn.getUniqueName();
}
if (elechild != null && elechild.getValue().equals(uniqueName)) {
List<? extends INodeConnector> connList = new JobletUtil().createConnectors(connNode,
this.getProcess());
// modify///////////////////////////////////////////////////////////////////////////////////////////////////////
List<INodeConnector> inodeConnList = new ArrayList<INodeConnector>();
inodeConnList.addAll(connList);
inodeConnList.addAll(connNode.getListConnector());
connNode.setListConnector(inodeConnList);
// connNode.getListConnector().addAll(connList);
IMetadataTable iTable = this.node.getMetadataTable(connNode.getUniqueName());
if (iTable != null && !connNode.getMetadataList().contains(iTable)) {
// connNode.getMetadataList().add(iTable);
}
JobletConnectionReconnectCommand reConnectCommand = new JobletConnectionReconnectCommand(conn);
reConnectCommand.setNewTarget(connNode);
reConnectCommand.execute();
break;
} else if (getFlowInput(inputs).size() == 1 && !isTri
&& new JobletUtil().isJobletInput(connNode, this.getProcess())) {
JobletConnectionReconnectCommand reConnectCommand = new JobletConnectionReconnectCommand(conn);
reConnectCommand.setNewTarget(connNode);
reConnectCommand.execute();
break;
}
}
}
}
}
Iterator<IConnection> outIterator = outputs.iterator();
while (outIterator.hasNext()) {
IConnection conn = outIterator.next();
if (isCollapsed()) {
((Connection) conn).reconnect(this.node, conn.getTarget(), conn.getLineStyle());
} else {
for (NodeContainer nodeContainer : this.nodeContainers) {
Node connNode = nodeContainer.getNode();
if (conn.getConnectorName().equals(connNode.getJoblet_unique_name())) {
List<? extends INodeConnector> connList = new JobletUtil().createConnectors(connNode, this.getProcess());
List<INodeConnector> inodeConnList = new ArrayList<INodeConnector>();
inodeConnList.addAll(connList);
inodeConnList.addAll(connNode.getListConnector());
connNode.setListConnector(inodeConnList);
// connNode.setListConnector(connList);
IMetadataTable iTable = this.node.getMetadataTable(connNode.getUniqueName());
if (iTable != null && !connNode.getMetadataList().contains(iTable)) {
// connNode.getMetadataList().add(iTable);
}
JobletConnectionReconnectCommand reConnectCommand = new JobletConnectionReconnectCommand(conn);
reConnectCommand.setNewSource(connNode);
reConnectCommand.execute();
// return;
}
}
}
}
}
public void updateSubjobContainer() {
fireStructureChange(UPDATE_JOBLET_CONTENT, this);
}
public void updateSubjobDisplay() {
if (!isDisplayed() && isCollapsed()) {
// if the subjob hidden and collapsed, remove the collapse status first.
setCollapsed(false);
}
fireStructureChange(UPDATE_JOBLET_DISPLAY, this);
}
/*
* (non-Javadoc)
*
* @see org.talend.core.model.process.ISubjobContainer#isDisplayed()
*/
public boolean isDisplayed() {
if (!DesignerPlugin.getDefault().getPreferenceStore().getBoolean(TalendDesignerPrefConstants.DISPLAY_SUBJOBS)) {
return false;
}
return true;// (Boolean) getPropertyValue(EParameterName.SUBJOB_DISPLAYED.getName());
}
/**
* Sets the collapsed.
*
* @param collapsed the collapsed to set
*/
public void setCollapsed(boolean collapsed) {
setPropertyValue(EParameterName.COLLAPSED.getName(), new Boolean(collapsed));
}
@Override
public List getElements() {
if (isCollapsed() || this.jobletElements.size() <= 0) {
return super.getElements();
} else {
return this.jobletElements;
}
}
public List<NodeContainer> getNodeContainers() {
return this.nodeContainers;
}
public boolean canCollapse() {
if (node.getIncomingConnections().size() > 1) {
for (NodeContainer nodeContainer : this.nodeContainers) {
Node connNode = nodeContainer.getNode();
IElementParameter elePa = this.node.getElementParameter(connNode.getJoblet_unique_name());
if (elePa != null) {
IElementParameter elechild = elePa.getChildParameters().get("CONNECTION");
if (elechild != null && (elechild.getValue() == null || "".equals(elechild.getValue()))) {
return false;
}
}
}
}
return true;
}
private Set<IConnection> getFlowInput(Set<IConnection> inputs) {
Set<IConnection> finputs = new HashSet<IConnection>();
Iterator<IConnection> ite = inputs.iterator();
while (ite.hasNext()) {
IConnection conn = ite.next();
if (!conn.getConnectorName().equals("SUBJOB_OK") && !conn.getConnectorName().equals("SUBJOB_ERROR")
&& !conn.getConnectorName().equals("COMPONENT_OK") && !conn.getConnectorName().equals("COMPONENT_ERROR")) {
finputs.add(conn);
}
}
return finputs;
}
// public Boolean isNeedLock() {
// return needLock;
// }
public void setNeedchangeLock(boolean needchangeLock) {
this.needchangeLock = needchangeLock;
}
}