use of org.knime.core.node.workflow.virtual.subnode.VirtualSubNodeExchange in project knime-core by knime.
the class SubNodeContainer method setVirtualOutputIntoOutport.
/**
* Copies data from virtual output node into m_outputs, notifies state listeners if not
* processing call from parent.
* @param newState State of the internal WFM to decide whether to publish ports and/or specs.
*/
@SuppressWarnings("null")
private boolean setVirtualOutputIntoOutport(final InternalNodeContainerState newState) {
// retrieve results and copy to outports
final VirtualSubNodeOutputNodeModel virtualOutNodeModel = getVirtualOutNodeModel();
final boolean isInactive = getVirtualOutNode().isInactive();
final VirtualSubNodeExchange outputExchange = virtualOutNodeModel.getOutputExchange();
// put objects into output if state of WFM is executed
boolean publishObjects = newState.isExecuted();
// publishObjects implies that output node has data or is inactive
assert !publishObjects || (isInactive || (outputExchange != null && outputExchange.getPortObjects() != null)) : String.format("output node must have data or be inactive, status: %s, inactive: %b, exhange is null: %b, " + "exchange content is null: %s", newState, isInactive, outputExchange == null, outputExchange == null ? "<invalid>" : String.valueOf(outputExchange.getPortObjects() == null));
boolean publishSpecs = (isInactive || outputExchange != null) && (newState.isConfigured() || newState.isExecuted() || newState.isExecutionInProgress());
boolean changed = false;
for (int i = 1; i < m_outputs.length; i++) {
// not publish spec: null output
// inactive output node: inactive branch port object
// otherwise: use data from output node
final PortObjectSpec spec = publishSpecs ? (isInactive ? InactiveBranchPortObjectSpec.INSTANCE : outputExchange.getPortSpecs()[i - 1]) : null;
changed = m_outputs[i].setSpec(spec) || changed;
final PortObject object = publishObjects ? (isInactive ? InactiveBranchPortObject.INSTANCE : outputExchange.getPortObjects()[i - 1]) : null;
changed = m_outputs[i].setObject(object) || changed;
}
final PortObjectSpec spec = publishSpecs ? (isInactive ? InactiveBranchPortObjectSpec.INSTANCE : FlowVariablePortObjectSpec.INSTANCE) : null;
changed = m_outputs[0].setSpec(spec) || changed;
final PortObject object = publishObjects ? (isInactive ? InactiveBranchPortObject.INSTANCE : FlowVariablePortObject.INSTANCE) : null;
changed = m_outputs[0].setObject(object) || changed;
final FlowObjectStack outgoingFlowObjectStack = getOutgoingFlowObjectStack();
// TODO API to remove variables from stack, then remove variables no longer in output node and update "changed"
if (publishObjects && !isInactive) {
for (FlowVariable f : outputExchange.getFlowVariables()) {
outgoingFlowObjectStack.push(f.cloneAndUnsetOwner());
}
} else {
// outgoing stack may be null if reset is called twice in a row (or once but no configure was called)
if (outgoingFlowObjectStack != null) {
while (!outgoingFlowObjectStack.isEmpty()) {
outgoingFlowObjectStack.pop(FlowObject.class);
}
}
}
if (changed && !m_isPerformingActionCalledFromParent) {
// updates port views
notifyStateChangeListeners(new NodeStateEvent(this));
}
return changed;
}
Aggregations