use of org.knime.core.node.workflow.virtual.subnode.VirtualSubNodeOutputNodeModel in project knime-core by knime.
the class SubNodeContainer method performLoadContent.
/**
* {@inheritDoc}
*/
@Override
WorkflowCopyContent performLoadContent(final SingleNodeContainerPersistor nodePersistor, final Map<Integer, BufferedDataTable> tblRep, final FlowObjectStack inStack, final ExecutionMonitor exec, final LoadResult loadResult, final boolean preserveNodeMessage) throws CanceledExecutionException {
SubNodeContainerPersistor subNodePersistor = (SubNodeContainerPersistor) nodePersistor;
WorkflowPersistor workflowPersistor = subNodePersistor.getWorkflowPersistor();
// TODO pass in a filter input stack
m_wfm.loadContent(workflowPersistor, tblRep, inStack, exec, loadResult, preserveNodeMessage);
if (workflowPersistor.isDirtyAfterLoad() || m_wfm.isDirty()) {
setDirty();
}
InternalNodeContainerState loadState = nodePersistor.getMetaPersistor().getState();
if (!m_wfm.getInternalState().equals(loadState)) {
// can happen for workflows that were exported without data;
// the same check is done by the caller (WorkflowManager#postLoad) and handled appropriately
setInternalState(m_wfm.getInternalState(), false);
}
NodeSettingsRO modelSettings = subNodePersistor.getSNCSettings().getModelSettings();
if (modelSettings != null) {
try {
loadModelSettingsIntoDialogNodes(modelSettings, false);
} catch (InvalidSettingsException e) {
final String msg = "Could not load Wrapped Metanode configuration into dialog-nodes: " + e.getMessage();
LOGGER.error(msg, e);
loadResult.addError(msg);
setDirty();
}
}
checkInOutNodesAfterLoad(subNodePersistor, loadResult);
// put data input output node if it was executed;
final NativeNodeContainer virtualOutNode = getVirtualOutNode();
LoadVersion l = nodePersistor instanceof FileSingleNodeContainerPersistor ? ((FileSingleNodeContainerPersistor) nodePersistor).getLoadVersion() : LoadVersion.V3010;
if (l.isOlderThan(LoadVersion.V3010) && virtualOutNode.getInternalState().isExecuted()) {
VirtualSubNodeOutputNodeModel outNodeModel = getVirtualOutNodeModel();
PortObject[] outputData = new PortObject[virtualOutNode.getNrInPorts()];
m_wfm.assembleInputData(getVirtualOutNodeID(), outputData);
outNodeModel.postLoadExecute(ArrayUtils.removeAll(outputData, 0));
// allow node to receive the internal held objects so that the next save operation also persists the
// array of internal held objects - otherwise we get strange errors with nodes saved in 2.x, then loaded
// and saved in 3.1+ (and converted ... although unmodified)
getVirtualOutNode().getNode().assignInternalHeldObjects(outputData, null, getVirtualOutNode().createExecutionContext(), new PortObject[0]);
}
setVirtualOutputIntoOutport(m_wfm.getInternalState());
m_wfmStateChangeListener = createAndAddStateListener();
getInPort(0).setPortName("Variable Inport");
getOutPort(0).setPortName("Variable Outport");
getVirtualInNode().addNodeStateChangeListener(new RefreshPortNamesListener());
getVirtualOutNode().addNodeStateChangeListener(new RefreshPortNamesListener());
refreshPortNames();
return null;
}
use of org.knime.core.node.workflow.virtual.subnode.VirtualSubNodeOutputNodeModel 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;
}
use of org.knime.core.node.workflow.virtual.subnode.VirtualSubNodeOutputNodeModel in project knime-core by knime.
the class SubNodeContainer method checkInOutNodesAfterLoad.
/**
* Fixes in- and output nodes after loading (in case they don't exist or have errors).
*/
private void checkInOutNodesAfterLoad(final SubNodeContainerPersistor subNodePersistor, final LoadResult loadResult) {
/* Fix output node */
NodeID virtualOutID = getVirtualOutNodeID();
// non null in case not is not present of of wrong type
String error = null;
// settings of previous node if present or null
NodeSettings outputSettings = null;
// assigned with node insertion, used for node placement
Pair<int[], int[]> minMaxCoordinates;
if (m_wfm.containsNodeContainer(virtualOutID)) {
NodeContainer virtualOutNC = m_wfm.getNodeContainer(virtualOutID);
if (virtualOutNC instanceof NativeNodeContainer) {
NodeModel virtualOutModel = ((NativeNodeContainer) virtualOutNC).getNodeModel();
if (!(virtualOutModel instanceof VirtualSubNodeOutputNodeModel)) {
// this is very likely a missing node (placeholder)
error = String.format("Virtual output node is not of expected type (expected %s, actual %s)", VirtualSubNodeOutputNodeModel.class.getName(), virtualOutModel.getClass().getName());
try {
NodeSettings temp = new NodeSettings("temp");
m_wfm.saveNodeSettings(virtualOutID, temp);
outputSettings = temp;
} catch (InvalidSettingsException ise) {
// silently ignore; this is minor given that the node is not there.
}
}
} else {
error = String.format("Virtual output node with ID %s is not a native node", virtualOutID);
}
} else {
error = String.format("Virtual output node with ID %s does not exist", virtualOutID);
}
if (error != null) {
minMaxCoordinates = getMinMaxCoordinates();
m_virtualOutNodeIDSuffix = addVirtualOutNode(Output.getPortTypesNoFlowVariablePort(m_outputs), minMaxCoordinates).getIndex();
error = error.concat(String.format(" - creating new instance (ID %s)", m_virtualOutNodeIDSuffix));
loadResult.addError(error);
if (outputSettings != null) {
try {
m_wfm.loadNodeSettings(getVirtualOutNodeID(), outputSettings);
} catch (InvalidSettingsException e) {
// again, ignore as the node was missing, which is much more critical
}
}
}
/* Fix input node */
NodeID virtualInID = getVirtualInNodeID();
// non null in case not is not present of of wrong type
error = null;
// settings of previous node if present or null
NodeSettings inputSettings = null;
if (m_wfm.containsNodeContainer(virtualInID)) {
NodeContainer virtualInNC = m_wfm.getNodeContainer(virtualInID);
if (virtualInNC instanceof NativeNodeContainer) {
NodeModel virtualInModel = ((NativeNodeContainer) virtualInNC).getNodeModel();
if (!(virtualInModel instanceof VirtualSubNodeInputNodeModel)) {
// this is very likely a missing node (placeholder)
error = String.format("Virtual input node is not of expected type (expected %s, actual %s)", VirtualSubNodeInputNodeModel.class.getName(), virtualInModel.getClass().getName());
try {
NodeSettings temp = new NodeSettings("temp");
m_wfm.saveNodeSettings(virtualInID, temp);
inputSettings = temp;
} catch (InvalidSettingsException ise) {
// silently ignore; this is minor given that the node is not there.
}
}
} else {
error = String.format("Virtual input node with ID %s is not a native node", virtualInID);
}
} else {
error = String.format("Virtual input node with ID %s does not exist", virtualInID);
}
if (error != null) {
minMaxCoordinates = getMinMaxCoordinates();
// skip flow var port
PortType[] inportTypes = new PortType[getNrInPorts() - 1];
for (int i = 1; i < getNrInPorts(); i++) {
inportTypes[i - 1] = getInPort(i).getPortType();
}
m_virtualInNodeIDSuffix = addVirtualInNode(inportTypes, minMaxCoordinates).getIndex();
error = error.concat(String.format(" - creating new instance (ID %s)", m_virtualInNodeIDSuffix));
loadResult.addError(error);
if (inputSettings != null) {
try {
m_wfm.loadNodeSettings(getVirtualInNodeID(), inputSettings);
} catch (InvalidSettingsException e) {
// again, ignore as the node was missing, which is much more critical
}
}
}
}
use of org.knime.core.node.workflow.virtual.subnode.VirtualSubNodeOutputNodeModel in project knime-core by knime.
the class SubNodeContainer method getXMLDescription.
/* -------------------- NodeContainer info properties -------------- */
@SuppressWarnings("rawtypes")
/**
* {@inheritDoc}
*/
@Override
public Element getXMLDescription() {
VirtualSubNodeInputNodeModel inNode = getVirtualInNodeModel();
VirtualSubNodeOutputNodeModel outNode = getVirtualOutNodeModel();
String description = inNode.getSubNodeDescription();
String sDescription;
if (StringUtils.isEmpty(description)) {
sDescription = "";
} else {
sDescription = StringUtils.split(description, ".\n")[0];
sDescription = StringUtils.abbreviate(sDescription, 200);
}
String[] inPortNames = inNode.getPortNames();
String[] inPortDescriptions = inNode.getPortDescriptions();
String[] outPortNames = outNode.getPortNames();
String[] outPortDescriptions = outNode.getPortDescriptions();
Map<NodeID, DialogNode> nodes = m_wfm.findNodes(DialogNode.class, false);
List<String> optionNames = new ArrayList<String>();
List<String> optionDescriptions = new ArrayList<String>();
for (DialogNode dialogNode : nodes.values()) {
DialogNodeRepresentation representation = dialogNode.getDialogRepresentation();
if (representation instanceof QuickFormRepresentation) {
optionNames.add(((QuickFormRepresentation) representation).getLabel());
optionDescriptions.add(((QuickFormRepresentation) representation).getDescription());
}
}
try {
// Document
Document doc = NodeDescription.getDocumentBuilderFactory().newDocumentBuilder().getDOMImplementation().createDocument("http://knime.org/node2012", "knimeNode", null);
// knimeNode
Element knimeNode = doc.getDocumentElement();
knimeNode.setAttribute("type", "Unknown");
knimeNode.setAttribute("icon", "subnode.png");
// name
Element name = doc.createElement("name");
knimeNode.appendChild(name);
name.appendChild(doc.createTextNode(getName()));
// shortDescription
Element shortDescription = doc.createElement("shortDescription");
knimeNode.appendChild(shortDescription);
addText(shortDescription, sDescription, NO_DESCRIPTION_SET);
// fullDescription
Element fullDescription = doc.createElement("fullDescription");
knimeNode.appendChild(fullDescription);
// intro
Element intro = doc.createElement("intro");
fullDescription.appendChild(intro);
addText(intro, description, NO_DESCRIPTION_SET + "\nIn order to set a description browse the input node " + "contained in the Wrapped Metanode and change its configuration.");
// option
for (int i = 0; i < optionNames.size(); i++) {
Element option = doc.createElement("option");
fullDescription.appendChild(option);
option.setAttribute("name", optionNames.get(i));
addText(option, optionDescriptions.get(i), "");
}
// ports
Element ports = doc.createElement("ports");
knimeNode.appendChild(ports);
// inPort
for (int i = 0; i < inPortNames.length; i++) {
Element inPort = doc.createElement("inPort");
ports.appendChild(inPort);
inPort.setAttribute("index", "" + i);
inPort.setAttribute("name", inPortNames[i]);
String defaultText = NO_DESCRIPTION_SET;
if (i == 0) {
defaultText += "\nChange this label by browsing the input node contained in the Wrapped Metanode " + "and changing its configuration.";
}
addText(inPort, inPortDescriptions[i], defaultText);
}
// outPort
for (int i = 0; i < outPortNames.length; i++) {
Element outPort = doc.createElement("outPort");
ports.appendChild(outPort);
outPort.setAttribute("index", "" + i);
outPort.setAttribute("name", outPortNames[i]);
String defaultText = NO_DESCRIPTION_SET;
if (i == 0) {
defaultText += "\nChange this label by browsing the output node contained in the Wrapped Metanode " + "and changing its configuration.";
}
addText(outPort, outPortDescriptions[i], defaultText);
}
return new NodeDescription27Proxy(doc).getXMLDescription();
} catch (ParserConfigurationException | DOMException | XmlException e) {
LOGGER.warn("Could not generate Wrapped Metanode description", e);
}
return null;
}
Aggregations