Search in sources :

Example 21 with PortObjectSpec

use of org.knime.core.node.port.PortObjectSpec in project knime-core by knime.

the class Node method setOutPortObjects.

/**
 * Called after execute in order to put the computed result into the
 * outports. It will do a sequence of sanity checks whether the argument
 * is valid (non-null, correct type, etc.)
 * @param newOutData The computed output data
 * @param tolerateNullOutports used e.g. when loop is continued (outports may not yet be available)
 * @param tolerateDifferentSpecs used e.g. when re-executing a node (table may be different from configure)
 * @return Whether that is successful (false in case of incompatible port objects)
 */
private boolean setOutPortObjects(final PortObject[] newOutData, final boolean tolerateNullOutports, final boolean tolerateDifferentSpecs) {
    CheckUtils.checkArgumentNotNull(newOutData, "Port object array is null");
    if (newOutData.length != getNrOutPorts()) {
        throw new IndexOutOfBoundsException("Array is expected to be of " + "length " + getNrOutPorts() + ": " + newOutData.length);
    }
    // check for compatible output PortObjects
    for (int i = 0; i < newOutData.length; i++) {
        PortType thisType = m_outputs[i].type;
        if (newOutData[i] == null && !tolerateNullOutports) {
            createErrorMessageAndNotify("Output at port " + i + " is null");
            return false;
        }
        if (newOutData[i] != null) {
            if (newOutData[i] instanceof InactiveBranchPortObject) {
            // allow PO coming from inactive branch
            // TODO ensure model was skipped during configure?
            } else if (!thisType.getPortObjectClass().isInstance(newOutData[i])) {
                createErrorMessageAndNotify("Invalid output port object at port " + i);
                LOGGER.error("  (Wanted: " + thisType.getPortObjectClass().getName() + ", " + "actual: " + newOutData[i].getClass().getName() + ")");
                return false;
            }
            PortObjectSpec spec;
            try {
                spec = newOutData[i].getSpec();
            } catch (Throwable t) {
                createErrorMessageAndNotify("PortObject \"" + newOutData[i].getClass().getName() + "\" threw " + t.getClass().getSimpleName() + " on #getSpec() ", t);
                return false;
            }
            if (spec == null) {
                createErrorMessageAndNotify("Implementation Error: PortObject \"" + newOutData[i].getClass().getName() + "\" must not" + " have null spec (output port " + i + ").");
                return false;
            }
        }
    }
    for (int p = 0; p < getNrOutPorts(); p++) {
        if (newOutData[p] instanceof BufferedDataTable) {
            BufferedDataTable thisTable = (BufferedDataTable) newOutData[p];
            DataTableSpec portSpec = (DataTableSpec) (m_outputs[p].spec);
            DataTableSpec newPortSpec = thisTable.getDataTableSpec();
            if ((portSpec != null) && !tolerateDifferentSpecs) {
                if (!portSpec.equalStructure(newPortSpec)) {
                    String errorMsg = "DataSpec generated by configure does not match spec after execution.";
                    LOGGER.coding(errorMsg);
                    createErrorMessageAndNotify(errorMsg);
                }
            }
            BufferedDataTable t = thisTable;
            t.setOwnerRecursively(this);
            m_outputs[p].object = t;
            m_outputs[p].summary = t.getSummary();
            m_outputs[p].spec = newPortSpec;
        } else {
            m_outputs[p].object = newOutData[p];
            if (newOutData[p] != null) {
                m_outputs[p].spec = newOutData[p].getSpec();
                m_outputs[p].summary = newOutData[p].getSummary();
            } else {
                m_outputs[p].summary = null;
            }
        }
    }
    return true;
}
Also used : DataTableSpec(org.knime.core.data.DataTableSpec) InactiveBranchPortObject(org.knime.core.node.port.inactive.InactiveBranchPortObject) InactiveBranchPortObjectSpec(org.knime.core.node.port.inactive.InactiveBranchPortObjectSpec) PortObjectSpec(org.knime.core.node.port.PortObjectSpec) FlowVariablePortObjectSpec(org.knime.core.node.port.flowvariable.FlowVariablePortObjectSpec) PortType(org.knime.core.node.port.PortType)

Example 22 with PortObjectSpec

use of org.knime.core.node.port.PortObjectSpec 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;
}
Also used : DataTableSpec(org.knime.core.data.DataTableSpec) InactiveBranchPortObjectSpec(org.knime.core.node.port.inactive.InactiveBranchPortObjectSpec) DataTableSpecCreator(org.knime.core.data.DataTableSpecCreator) InactiveBranchPortObjectSpec(org.knime.core.node.port.inactive.InactiveBranchPortObjectSpec) PortObjectSpec(org.knime.core.node.port.PortObjectSpec) FlowVariablePortObjectSpec(org.knime.core.node.port.flowvariable.FlowVariablePortObjectSpec) FlowLoopContext(org.knime.core.node.workflow.FlowLoopContext)

Example 23 with PortObjectSpec

use of org.knime.core.node.port.PortObjectSpec 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;
}
Also used : DataTableSpec(org.knime.core.data.DataTableSpec) InactiveBranchPortObjectSpec(org.knime.core.node.port.inactive.InactiveBranchPortObjectSpec) InactiveBranchPortObjectSpec(org.knime.core.node.port.inactive.InactiveBranchPortObjectSpec) PortObjectSpec(org.knime.core.node.port.PortObjectSpec)

Example 24 with PortObjectSpec

use of org.knime.core.node.port.PortObjectSpec in project knime-core by knime.

the class DialogComponentColumnFilter method updateComponent.

/**
 * {@inheritDoc}
 */
@Override
protected void updateComponent() {
    // update component only if content is out of sync
    final SettingsModelFilterString filterModel = (SettingsModelFilterString) getModel();
    final Set<String> compIncl = m_columnFilter.getIncludedColumnSet();
    final Set<String> compExcl = m_columnFilter.getExcludedColumnSet();
    final boolean compKeepAll = m_columnFilter.isKeepAllSelected();
    final Set<String> modelIncl = new LinkedHashSet<String>(filterModel.getIncludeList());
    final Set<String> modelExcl = new LinkedHashSet<String>(filterModel.getExcludeList());
    final boolean modelKeepAll = filterModel.isKeepAllSelected();
    boolean update = (compIncl.size() != modelIncl.size()) || (compExcl.size() != modelExcl.size() || compKeepAll != modelKeepAll);
    if (!update) {
        // update if the current spec and the spec we last updated with
        // are different
        final PortObjectSpec currPOSpec = getLastTableSpec(m_inPortIndex);
        if (currPOSpec == null) {
            update = false;
        } else {
            if (!(currPOSpec instanceof DataTableSpec)) {
                throw new RuntimeException("Wrong type of PortObject for" + " ColumnFilterPanel, expecting DataTableSpec!");
            }
            final DataTableSpec currSpec = (DataTableSpec) currPOSpec;
            update = (!currSpec.equalStructure(m_specInFilter));
        }
    }
    if (!update) {
        // one way check, because size is equal
        update = !modelIncl.containsAll(compIncl);
    }
    if (!update) {
        // one way check, because size is equal
        update = !modelExcl.containsAll(compExcl);
    }
    if (update) {
        m_specInFilter = (DataTableSpec) getLastTableSpec(m_inPortIndex);
        if (m_specInFilter == null) {
            // the component doesn't take a null spec. Create an empty one
            m_specInFilter = new DataTableSpec();
        }
        m_columnFilter.update(m_specInFilter, filterModel.getIncludeList(), filterModel.getExcludeList(), m_inclUnknown);
        m_columnFilter.setKeepAllSelected(modelKeepAll);
    }
    // also update the enable status
    setEnabledComponents(filterModel.isEnabled());
}
Also used : LinkedHashSet(java.util.LinkedHashSet) DataTableSpec(org.knime.core.data.DataTableSpec) PortObjectSpec(org.knime.core.node.port.PortObjectSpec)

Example 25 with PortObjectSpec

use of org.knime.core.node.port.PortObjectSpec in project knime-core by knime.

the class FileNodePersistor method loadPorts.

/**
 * @noreference
 * @nooverride
 */
void loadPorts(final Node node, final ExecutionMonitor exec, final NodeSettingsRO settings, final Map<Integer, BufferedDataTable> loadTblRep, final HashMap<Integer, ContainerTable> tblRep, final FileStoreHandlerRepository fileStoreHandlerRepository) throws IOException, InvalidSettingsException, CanceledExecutionException {
    final int nrOutPorts = node.getNrOutPorts();
    if (getLoadVersion().isOlderThan(FileWorkflowPersistor.LoadVersion.V200)) {
        // skip flow variables port (introduced in v2.2)
        for (int i = 1; i < nrOutPorts; i++) {
            int oldIndex = getOldPortIndex(i);
            ExecutionMonitor execPort = exec.createSubProgress(1.0 / nrOutPorts);
            exec.setMessage("Port " + oldIndex);
            PortType type = node.getOutputType(i);
            boolean isDataPort = BufferedDataTable.class.isAssignableFrom(type.getPortObjectClass());
            if (m_isConfigured) {
                PortObjectSpec spec = loadPortObjectSpec(node, settings, oldIndex);
                setPortObjectSpec(i, spec);
            }
            if (m_isExecuted) {
                PortObject object;
                if (isDataPort) {
                    object = loadBufferedDataTable(node, settings, execPort, loadTblRep, oldIndex, tblRep, fileStoreHandlerRepository);
                } else {
                    throw new IOException("Can't restore model ports of " + "old 1.x workflows. Execute node again.");
                }
                String summary = object != null ? object.getSummary() : null;
                setPortObject(i, object);
                setPortObjectSummary(i, summary);
            }
            execPort.setProgress(1.0);
        }
    } else {
        if (nrOutPorts == 1) {
            // only the mandatory flow variable port
            return;
        }
        NodeSettingsRO portsSettings = loadPortsSettings(settings);
        exec.setMessage("Reading outport data");
        for (String key : portsSettings.keySet()) {
            NodeSettingsRO singlePortSetting = portsSettings.getNodeSettings(key);
            ExecutionMonitor subProgress = exec.createSubProgress(1 / (double) nrOutPorts);
            int index = loadPortIndex(singlePortSetting);
            if (index < 0 || index >= nrOutPorts) {
                throw new InvalidSettingsException("Invalid outport index in settings: " + index);
            }
            String portDirN = singlePortSetting.getString("port_dir_location");
            if (portDirN != null) {
                ReferencedFile portDir = new ReferencedFile(getNodeDirectory(), portDirN);
                subProgress.setMessage("Port " + index);
                loadPort(node, portDir, singlePortSetting, subProgress, index, loadTblRep, tblRep, fileStoreHandlerRepository);
            }
            subProgress.setProgress(1.0);
        }
    }
}
Also used : InactiveBranchPortObjectSpec(org.knime.core.node.port.inactive.InactiveBranchPortObjectSpec) PortObjectSpec(org.knime.core.node.port.PortObjectSpec) FlowVariablePortObjectSpec(org.knime.core.node.port.flowvariable.FlowVariablePortObjectSpec) IOException(java.io.IOException) PortObject(org.knime.core.node.port.PortObject) FileStorePortObject(org.knime.core.data.filestore.FileStorePortObject) FlowVariablePortObject(org.knime.core.node.port.flowvariable.FlowVariablePortObject) PMMLPortObject(org.knime.core.node.port.pmml.PMMLPortObject) InactiveBranchPortObject(org.knime.core.node.port.inactive.InactiveBranchPortObject) ReferencedFile(org.knime.core.internal.ReferencedFile) PortType(org.knime.core.node.port.PortType)

Aggregations

PortObjectSpec (org.knime.core.node.port.PortObjectSpec)123 DataTableSpec (org.knime.core.data.DataTableSpec)91 InvalidSettingsException (org.knime.core.node.InvalidSettingsException)81 PMMLPortObjectSpec (org.knime.core.node.port.pmml.PMMLPortObjectSpec)35 DataColumnSpec (org.knime.core.data.DataColumnSpec)28 SettingsModelString (org.knime.core.node.defaultnodesettings.SettingsModelString)28 ColumnRearranger (org.knime.core.data.container.ColumnRearranger)24 FlowVariablePortObjectSpec (org.knime.core.node.port.flowvariable.FlowVariablePortObjectSpec)19 InactiveBranchPortObjectSpec (org.knime.core.node.port.inactive.InactiveBranchPortObjectSpec)18 IOException (java.io.IOException)17 PortObject (org.knime.core.node.port.PortObject)14 PMMLPortObjectSpecCreator (org.knime.core.node.port.pmml.PMMLPortObjectSpecCreator)14 DatabasePortObjectSpec (org.knime.core.node.port.database.DatabasePortObjectSpec)12 DatabaseQueryConnectionSettings (org.knime.core.node.port.database.DatabaseQueryConnectionSettings)12 InactiveBranchPortObject (org.knime.core.node.port.inactive.InactiveBranchPortObject)12 DataType (org.knime.core.data.DataType)11 FlowVariablePortObject (org.knime.core.node.port.flowvariable.FlowVariablePortObject)11 File (java.io.File)10 ArrayList (java.util.ArrayList)10 DoubleValue (org.knime.core.data.DoubleValue)10