use of org.knime.core.node.port.inactive.InactiveBranchPortObjectSpec in project knime-core by knime.
the class Node method getDialogPaneWithSettings.
/**
* @param inSpecs The input specs, which will be forwarded to the dialog's
* {@link NodeDialogPane#loadSettingsFrom(NodeSettingsRO,
* PortObjectSpec[])}.
* @param settings The current settings of this node. The settings object
* will also contain the settings of the outer SNC.
* @param isWriteProtected Whether write protected, see
* {@link org.knime.core.node.workflow.WorkflowManager#isWriteProtected()}.
* @return The dialog pane which holds all the settings' components. In
* addition this method loads the settings from the model into the
* dialog pane.
* @throws NotConfigurableException if the dialog cannot be opened because
* of real invalid settings or if any preconditions are not
* fulfilled, e.g. no predecessor node, no nominal column in
* input table, etc.
* @throws IllegalStateException If node has no dialog.
* @see #hasDialog()
* @since 2.6
*/
public NodeDialogPane getDialogPaneWithSettings(final PortObjectSpec[] inSpecs, final PortObject[] inData, final NodeSettingsRO settings, final boolean isWriteProtected) throws NotConfigurableException {
NodeDialogPane dialogPane = getDialogPane();
PortObjectSpec[] corrInSpecs = new PortObjectSpec[inSpecs.length - 1];
PortObject[] corrInData = new PortObject[inData.length - 1];
for (int i = 1; i < inSpecs.length; i++) {
if (inSpecs[i] instanceof InactiveBranchPortObjectSpec) {
if (!isInactiveBranchConsumer()) {
throw new NotConfigurableException("Cannot configure nodes in inactive branches.");
}
}
PortType t = getInputType(i);
if (!t.acceptsPortObjectSpec(inSpecs[i]) && !(inSpecs[i] instanceof InactiveBranchPortObjectSpec)) {
// table(!) connection)
throw new NotConfigurableException("Invalid incoming port object spec \"" + inSpecs[i].getClass().getSimpleName() + "\", expected \"" + t.getPortObjectSpecClass().getSimpleName() + "\"");
} else if (inSpecs[i] == null && BufferedDataTable.TYPE.equals(t) && !t.isOptional()) {
corrInSpecs[i - 1] = new DataTableSpec();
} else {
corrInSpecs[i - 1] = inSpecs[i];
corrInData[i - 1] = inData[i];
}
}
// the sub node virtual input node shows in its dialog all flow variables that are available to the rest
// of the subnode. It's the only case where the flow variables shown in the dialog are not the ones available
// to the node model class ...
final FlowObjectStack flowObjectStack = m_model instanceof VirtualSubNodeInputNodeModel ? ((VirtualSubNodeInputNodeModel) m_model).getSubNodeContainerFlowObjectStack() : getFlowObjectStack();
dialogPane.internalLoadSettingsFrom(settings, corrInSpecs, corrInData, flowObjectStack, getCredentialsProvider(), isWriteProtected);
if (m_model instanceof ValueControlledNode && dialogPane instanceof ValueControlledDialogPane) {
NodeSettings currentValue = new NodeSettings("currentValue");
try {
((ValueControlledNode) m_model).saveCurrentValue(currentValue);
((ValueControlledDialogPane) dialogPane).loadCurrentValue(currentValue);
} catch (Exception ise) {
final String msg = "Could not load current value into dialog: " + ise.getMessage();
if (ise instanceof InvalidSettingsException) {
LOGGER.warn(msg, ise);
} else {
LOGGER.coding(msg, ise);
}
}
}
return dialogPane;
}
use of org.knime.core.node.port.inactive.InactiveBranchPortObjectSpec in project knime-core by knime.
the class Node method configure.
/**
* Allows passing an object that may modify the specs created by the
* {@link NodeModel}, for example in case the node is wrapped and the
* output is modified.
*
* @param rawInSpecs table specs from the predecessors
* @param configureHelper object called after node model calculated output
* specs
* @return true if configure finished successfully.
* @noreference This method is not intended to be referenced by clients.
*/
public boolean configure(final PortObjectSpec[] rawInSpecs, final NodeConfigureHelper configureHelper) {
boolean success = false;
LOGGER.assertLog(NodeContext.getContext() != null, "No node context available, please check call hierarchy and fix it");
synchronized (m_configureLock) {
// reset message object
clearNodeMessageAndNotify();
// copy input port object specs, ignoring the 0-variable port:
PortObjectSpec[] inSpecs = Arrays.copyOfRange(rawInSpecs, 1, rawInSpecs.length);
// clean output spec
for (int p = 0; p < m_outputs.length; p++) {
// update data table spec
m_outputs[p].spec = null;
}
PortObjectSpec[] newOutSpec = new PortObjectSpec[getNrOutPorts() - 1];
try {
// check the inspecs against null
for (int i = 0; i < inSpecs.length; i++) {
if (inSpecs[i] == null) {
if (m_inputs[i + 1].getType().isOptional()) {
// ignore, unconnected optional input
} else {
return false;
}
// TODO: did we really need a warning here??
// throw new InvalidSettingsException(
// "Node is not executable until all predecessors "
// + "are configured and/or executed.");
}
}
// check if the node is part of a skipped branch and return
// appropriate specs without actually configuring the node.
// Note that we must also check the incoming variable port!
boolean isInactive = false;
if (!isInactiveBranchConsumer()) {
for (int i = 0; i < rawInSpecs.length; i++) {
if (rawInSpecs[i] instanceof InactiveBranchPortObjectSpec) {
isInactive = true;
break;
}
}
} else {
FlowLoopContext flc = getFlowObjectStack().peek(FlowLoopContext.class);
if (flc != null && flc.isInactiveScope()) {
isInactive = true;
}
}
if (isInactive) {
for (int j = 0; j < m_outputs.length; j++) {
m_outputs[j].spec = InactiveBranchPortObjectSpec.INSTANCE;
}
if (success) {
LOGGER.debug("Configure skipped. (" + getName() + " in inactive branch.)");
}
return true;
}
if (configureHelper != null) {
configureHelper.preConfigure();
}
// call configure model to create output table specs
// guaranteed to return non-null, correct-length array
newOutSpec = invokeNodeModelConfigure(inSpecs);
if (configureHelper != null) {
newOutSpec = configureHelper.postConfigure(inSpecs, newOutSpec);
}
// find out if we are in the middle of executing a loop and this is a LoopEnd node
boolean isIntermediateRunningLoop = false;
if (isModelCompatibleTo(LoopEndNode.class)) {
if ((getLoopContext() != null) && !getPauseLoopExecution()) {
FlowLoopContext flc = m_model.getFlowObjectStack().peek(FlowLoopContext.class);
if ((flc != null) && (flc.getIterationIndex() > 0)) {
// don't treat first iteration as "in the middle":
isIntermediateRunningLoop = true;
}
}
}
if (!isIntermediateRunningLoop) {
// update data table specs
for (int p = 0; p < newOutSpec.length; p++) {
m_outputs[p + 1].spec = newOutSpec[p];
}
} else {
// on the loop end node (avoids costly configure calls on remainder of workflow).
for (int p = 0; p < newOutSpec.length; p++) {
if (newOutSpec[p] instanceof DataTableSpec) {
// remove domain before assigning spec to outputs
DataTableSpecCreator dtsCreator = new DataTableSpecCreator((DataTableSpec) newOutSpec[p]);
dtsCreator.dropAllDomains();
m_outputs[p + 1].spec = dtsCreator.createSpec();
} else {
// no domain to clean in PortObjectSpecs
m_outputs[p + 1].spec = newOutSpec[p];
}
}
}
m_outputs[0].spec = FlowVariablePortObjectSpec.INSTANCE;
success = true;
} catch (InvalidSettingsException ise) {
Throwable cause = ise.getCause();
if (cause == null) {
createWarningMessageAndNotify(ise.getMessage());
} else {
createWarningMessageAndNotify(ise.getMessage(), ise);
}
} catch (Throwable t) {
String error = "Configure failed (" + t.getClass().getSimpleName() + "): " + t.getMessage();
createErrorMessageAndNotify(error, t);
}
}
if (success) {
LOGGER.debug("Configure succeeded. (" + this.getName() + ")");
}
return success;
}
use of org.knime.core.node.port.inactive.InactiveBranchPortObjectSpec in project knime-core by knime.
the class FileNodePersistor method loadPort.
void loadPort(final Node node, final ReferencedFile portDir, final NodeSettingsRO settings, final ExecutionMonitor exec, final int portIdx, final Map<Integer, BufferedDataTable> loadTblRep, final WorkflowDataRepository dataRepository) throws IOException, InvalidSettingsException, CanceledExecutionException {
final String specClass = settings.getString("port_spec_class");
final String objectClass = loadPortObjectClassName(settings);
PortType designatedType = node.getOutputType(portIdx);
PortObjectSpec spec = null;
PortObject object = null;
// this cannot be simplified as BDT must be loaded as BDT even if
// the port type is not BDT (but general PortObject)
boolean isBDT = (BufferedDataTable.TYPE.getPortObjectClass().getName().equals(objectClass) && BufferedDataTable.TYPE.getPortObjectSpecClass().getName().equals(specClass)) || designatedType.equals(BufferedDataTable.TYPE);
// an InactiveBranchPortObjectSpec can be put into any port!
boolean isInactive = InactiveBranchPortObjectSpec.class.getName().equals(specClass);
if (isBDT && !isInactive) {
if (specClass != null && !specClass.equals(BufferedDataTable.TYPE.getPortObjectSpecClass().getName())) {
throw new IOException("Actual spec class \"" + specClass + "\", expected \"" + BufferedDataTable.TYPE.getPortObjectSpecClass().getName() + "\"");
}
if (objectClass != null && !objectClass.equals(BufferedDataTable.TYPE.getPortObjectClass().getName())) {
throw new IOException("Actual object class \"" + objectClass + "\", expected \"" + BufferedDataTable.TYPE.getPortObjectClass().getName() + "\"");
}
if (objectClass != null) {
object = loadBufferedDataTable(portDir, exec, loadTblRep, dataRepository);
((BufferedDataTable) object).setOwnerRecursively(node);
spec = ((BufferedDataTable) object).getDataTableSpec();
} else if (specClass != null) {
spec = BufferedDataTable.loadSpec(portDir);
}
} else {
object = loadPortObject(portDir, settings, exec, dataRepository).orElse(null);
spec = object != null ? object.getSpec() : null;
}
if (spec != null) {
if (!designatedType.getPortObjectSpecClass().isInstance(spec) && !isInactive) {
throw new IOException("Actual port spec type (\"" + spec.getClass().getSimpleName() + "\") does not match designated one (\"" + designatedType.getPortObjectSpecClass().getSimpleName() + "\")");
}
}
String summary = null;
if (object != null) {
if (!designatedType.getPortObjectClass().isInstance(object) && !isInactive) {
throw new IOException("Actual port object type (\"" + object.getClass().getSimpleName() + "\") does not match designated one (\"" + designatedType.getPortObjectClass().getSimpleName() + "\")");
}
summary = settings.getString("port_object_summary", null);
if (summary == null) {
summary = object.getSummary();
}
}
setPortObjectSpec(portIdx, spec);
setPortObject(portIdx, object);
setPortObjectSummary(portIdx, summary);
}
use of org.knime.core.node.port.inactive.InactiveBranchPortObjectSpec in project knime-core by knime.
the class NodeModel method configureModel.
/**
* This function is called when something changes that could affect the
* output <code>DataTableSpec</code> elements. E.g. after a reset,
* execute, (dis-)connect, and object creation (model instantiation).
* <p>
* The function calls <code>#configure()</code> to receive the updated
* output DataTableSpecs, if the model is not executed yet. After execution
* the DataTableSpecs are simply taken from the output DataTables.
*
* @param inSpecs An array of input <code>DataTableSpec</code> elements,
* either the array or each of its elements can be
* <code>null</code>.
* @return An array where each element indicates if the outport has changed.
* @throws InvalidSettingsException if the current settings don't go along
* with the table specs
*/
final PortObjectSpec[] configureModel(final PortObjectSpec[] inSpecs) throws InvalidSettingsException {
assert inSpecs.length == getNrInPorts();
setWarningMessage(null);
PortObjectSpec[] copyInSpecs = new PortObjectSpec[getNrInPorts()];
PortObjectSpec[] newOutSpecs;
System.arraycopy(inSpecs, 0, copyInSpecs, 0, inSpecs.length);
// Rather empty ones than null
for (int i = 0; i < copyInSpecs.length; i++) {
if (copyInSpecs[i] == null && BufferedDataTable.TYPE.equals(m_inPortTypes[i]) && !m_inPortTypes[i].isOptional()) {
// only mimic empty table for real table connections
copyInSpecs[i] = new DataTableSpec();
}
// only weak port compatibility check during connect
// (model reader can be connected to any model port)
// complain if actual types are incompatible.
Class<? extends PortObjectSpec> expected = m_inPortTypes[i].getPortObjectSpecClass();
if (// i.e. skip only "optional and not connected"
copyInSpecs[i] != null && !expected.isAssignableFrom(copyInSpecs[i].getClass()) && !(copyInSpecs[i] instanceof InactiveBranchPortObjectSpec)) {
StringBuilder b = new StringBuilder("Incompatible port spec");
if (copyInSpecs.length > 1) {
b.append(" at port ").append(i);
}
b.append(", expected: ").append(expected.getSimpleName());
b.append(", actual: ").append(copyInSpecs[i].getClass().getSimpleName());
throw new InvalidSettingsException(b.toString());
}
}
// CALL CONFIGURE
newOutSpecs = configure(copyInSpecs);
if (newOutSpecs == null) {
newOutSpecs = new PortObjectSpec[getNrOutPorts()];
}
// check output object spec length
if (newOutSpecs.length != getNrOutPorts()) {
m_logger.error("Output spec-array length invalid: " + newOutSpecs.length + " <> " + getNrOutPorts());
newOutSpecs = new PortObjectSpec[getNrOutPorts()];
}
return newOutSpecs;
}
use of org.knime.core.node.port.inactive.InactiveBranchPortObjectSpec in project knime-core by knime.
the class FileNodePersistor method loadPort.
void loadPort(final Node node, final ReferencedFile portDir, final NodeSettingsRO settings, final ExecutionMonitor exec, final int portIdx, final Map<Integer, BufferedDataTable> loadTblRep, final HashMap<Integer, ContainerTable> tblRep, final FileStoreHandlerRepository fileStoreHandlerRepository) throws IOException, InvalidSettingsException, CanceledExecutionException {
final String specClass = settings.getString("port_spec_class");
final String objectClass = loadPortObjectClassName(settings);
PortType designatedType = node.getOutputType(portIdx);
PortObjectSpec spec = null;
PortObject object = null;
// this cannot be simplified as BDT must be loaded as BDT even if
// the port type is not BDT (but general PortObject)
boolean isBDT = (BufferedDataTable.TYPE.getPortObjectClass().getName().equals(objectClass) && BufferedDataTable.TYPE.getPortObjectSpecClass().getName().equals(specClass)) || designatedType.equals(BufferedDataTable.TYPE);
// an InactiveBranchPortObjectSpec can be put into any port!
boolean isInactive = InactiveBranchPortObjectSpec.class.getName().equals(specClass);
if (isBDT && !isInactive) {
if (specClass != null && !specClass.equals(BufferedDataTable.TYPE.getPortObjectSpecClass().getName())) {
throw new IOException("Actual spec class \"" + specClass + "\", expected \"" + BufferedDataTable.TYPE.getPortObjectSpecClass().getName() + "\"");
}
if (objectClass != null && !objectClass.equals(BufferedDataTable.TYPE.getPortObjectClass().getName())) {
throw new IOException("Actual object class \"" + objectClass + "\", expected \"" + BufferedDataTable.TYPE.getPortObjectClass().getName() + "\"");
}
if (objectClass != null) {
object = loadBufferedDataTable(portDir, exec, loadTblRep, tblRep, fileStoreHandlerRepository);
((BufferedDataTable) object).setOwnerRecursively(node);
spec = ((BufferedDataTable) object).getDataTableSpec();
} else if (specClass != null) {
spec = BufferedDataTable.loadSpec(portDir);
}
} else {
object = loadPortObject(portDir, settings, exec, fileStoreHandlerRepository).orElse(null);
spec = object != null ? object.getSpec() : null;
}
if (spec != null) {
if (!designatedType.getPortObjectSpecClass().isInstance(spec) && !isInactive) {
throw new IOException("Actual port spec type (\"" + spec.getClass().getSimpleName() + "\") does not match designated one (\"" + designatedType.getPortObjectSpecClass().getSimpleName() + "\")");
}
}
String summary = null;
if (object != null) {
if (!designatedType.getPortObjectClass().isInstance(object) && !isInactive) {
throw new IOException("Actual port object type (\"" + object.getClass().getSimpleName() + "\") does not match designated one (\"" + designatedType.getPortObjectClass().getSimpleName() + "\")");
}
summary = settings.getString("port_object_summary", null);
if (summary == null) {
summary = object.getSummary();
}
}
setPortObjectSpec(portIdx, spec);
setPortObject(portIdx, object);
setPortObjectSummary(portIdx, summary);
}
Aggregations