Map<FlowElementInput, FlowElementInput> unifiedInputs = Maps.create();
Map<FlowElementOutput, FlowElementOutput> unifiedOutputs = Maps.create();
// find originals
for (Map.Entry<FlowElement, FlowElement> entry : elementMapping.entrySet()) {
FlowElement orig = entry.getKey();
FlowElement dest = entry.getValue();
assert orig.getIdentity().equals(orig.getIdentity());
FlowElement unified;
if (unifier.containsKey(orig.getIdentity()) == false) {
unified = dest;
unifier.put(orig.getIdentity(), unified);
} else {
unified = unifier.get(orig.getIdentity());
LOG.debug("Unify {} -> {}", dest, unified);
}
unifiedElements.put(dest, unified);
List<FlowElementInput> srcInput = orig.getInputPorts();
List<FlowElementInput> dstInput = dest.getInputPorts();
List<FlowElementInput> uniInput = unified.getInputPorts();
assert srcInput.size() == uniInput.size();
for (int i = 0, n = srcInput.size(); i < n; i++) {
if (inputMapping.containsKey(srcInput.get(i))) {
inputMapping.put(srcInput.get(i), uniInput.get(i));
unifiedInputs.put(dstInput.get(i), uniInput.get(i));
}
}
List<FlowElementOutput> srcOutput = orig.getOutputPorts();
List<FlowElementOutput> dstOutput = dest.getOutputPorts();
List<FlowElementOutput> uniOutput = unified.getOutputPorts();
assert srcOutput.size() == uniOutput.size();
for (int i = 0, n = srcOutput.size(); i < n; i++) {
if (outputMapping.containsKey(srcOutput.get(i))) {
outputMapping.put(srcOutput.get(i), uniOutput.get(i));
unifiedOutputs.put(dstOutput.get(i), uniOutput.get(i));
}
}
}
// reconnect inputs
for (Map.Entry<FlowElement, FlowElement> entry : elementMapping.entrySet()) {
FlowElement elem = entry.getValue();
FlowElement unified = unifiedElements.get(elem);
assert unified != null;
if (elem != unified) {
List<FlowElementInput> srcInput = elem.getInputPorts();
List<FlowElementInput> uniInput = unified.getInputPorts();
assert srcInput.size() == uniInput.size();
for (int i = 0, n = srcInput.size(); i < n; i++) {
FlowElementInput srcPort = srcInput.get(i);
FlowElementInput uniPort = uniInput.get(i);
for (PortConnection conn : srcPort.getConnected()) {
FlowElementOutput opposite = unifiedOutputs.get(conn.getUpstream());
assert opposite != null;
PortConnection.connect(opposite, uniPort);
}
srcPort.disconnectAll();
}
}
}
// reconnect outputs
for (FlowElement elem : elementMapping.values()) {
FlowElement unified = unifiedElements.get(elem);
assert unified != null;
if (elem != unified) {
List<FlowElementOutput> srcOutput = elem.getOutputPorts();
List<FlowElementOutput> uniOutput = unified.getOutputPorts();
assert srcOutput.size() == uniOutput.size();
for (int i = 0, n = srcOutput.size(); i < n; i++) {
FlowElementOutput srcPort = srcOutput.get(i);
FlowElementOutput uniPort = uniOutput.get(i);
for (PortConnection conn : srcPort.getConnected()) {
FlowElementInput opposite = unifiedInputs.get(conn.getDownstream());
assert opposite != null;
PortConnection.connect(uniPort, opposite);
}
srcPort.disconnectAll();
}
}
}
// delete unified
for (Map.Entry<FlowElement, FlowElement> entry : elementMapping.entrySet()) {
FlowElement elem = entry.getValue();
FlowElement unified = unifiedElements.get(elem);
assert unified != null;
entry.setValue(unified);
}
this.elements = Sets.from(elementMapping.values());