Search in sources :

Example 56 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 57 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 58 with PortObjectSpec

use of org.knime.core.node.port.PortObjectSpec 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;
}
Also used : VirtualSubNodeExchange(org.knime.core.node.workflow.virtual.subnode.VirtualSubNodeExchange) PortObjectSpec(org.knime.core.node.port.PortObjectSpec) FlowVariablePortObjectSpec(org.knime.core.node.port.flowvariable.FlowVariablePortObjectSpec) InactiveBranchPortObjectSpec(org.knime.core.node.port.inactive.InactiveBranchPortObjectSpec) VirtualSubNodeOutputNodeModel(org.knime.core.node.workflow.virtual.subnode.VirtualSubNodeOutputNodeModel) FlowVariablePortObject(org.knime.core.node.port.flowvariable.FlowVariablePortObject) InactiveBranchPortObject(org.knime.core.node.port.inactive.InactiveBranchPortObject) PortObject(org.knime.core.node.port.PortObject)

Example 59 with PortObjectSpec

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

the class WorkflowManager method configureSingleNodeContainer.

/**
 * Configure a SingleNodeContainer.
 *
 * @param snc node to be configured
 * @param keepNodeMessage Whether to keep previously set node messages (important during load sometimes)
 * @return true if the configuration did change something.
 */
private boolean configureSingleNodeContainer(final SingleNodeContainer snc, final boolean keepNodeMessage) {
    boolean configurationChanged = false;
    try (WorkflowLock lock = lock()) {
        NodeMessage oldMessage = keepNodeMessage ? snc.getNodeMessage() : NodeMessage.NONE;
        final int inCount = snc.getNrInPorts();
        NodeID sncID = snc.getID();
        NodeOutPort[] predPorts = assemblePredecessorOutPorts(sncID);
        final PortObjectSpec[] inSpecs = new PortObjectSpec[inCount];
        final FlowObjectStack[] sos = new FlowObjectStack[inCount];
        final HiLiteHandler[] hiliteHdls = new HiLiteHandler[inCount];
        // check for presence of input specs and collects inport
        // TableSpecs, FlowObjectStacks and HiLiteHandlers
        boolean allSpecsExists = true;
        for (int i = 0; i < predPorts.length; i++) {
            if (predPorts[i] != null) {
                inSpecs[i] = predPorts[i].getPortObjectSpec();
                sos[i] = predPorts[i].getFlowObjectStack();
                hiliteHdls[i] = predPorts[i].getHiLiteHandler();
                allSpecsExists &= inSpecs[i] != null;
            } else if (snc.getInPort(i).getPortType().isOptional()) {
            // optional input, which is not connected ... ignore
            } else {
                allSpecsExists = false;
            }
        }
        if (!allSpecsExists) {
            // (NodeMessage did not change -- can exit here)
            return false;
        }
        if (!canConfigureNodes()) {
            String message;
            if (snc.getParent().isComponentProjectWFM()) {
                message = "No example input data stored with component";
            } else {
                message = "Component does not have input data, execute upstream nodes first";
            }
            snc.setNodeMessage(NodeMessage.merge(oldMessage, NodeMessage.newWarning(message)));
            return false;
        }
        boolean doConfigure = false;
        // which might attempt to configure an already queued node again
        switch(snc.getInternalState()) {
            case IDLE:
            case CONFIGURED:
            case UNCONFIGURED_MARKEDFOREXEC:
            case CONFIGURED_MARKEDFOREXEC:
                doConfigure = true;
                break;
            case EXECUTINGREMOTELY:
                // grid/server) -- also these nodes will be configured() on load
                if (snc.findJobManager().canDisconnect(getExecutionJob())) {
                    // see AP-9290 -- in order to properly check we whether we are in 'loading' state we would need
                    // additional AP -- decided that this workaround will be OK as most job manager are not remote
                    doConfigure = true;
                }
                break;
            case EXECUTED:
            case EXECUTED_MARKEDFOREXEC:
                // should not happen but could if reset has worked on slightly
                // different nodes than configure, for instance.
                // FIXME: report errors again, once configure follows only ports, not nodes.
                LOGGER.debug("configure found " + snc.getInternalState() + " node: " + snc.getNameWithID());
                break;
            case PREEXECUTE:
            case POSTEXECUTE:
            case EXECUTING:
                // should not happen but could if reset has worked on slightly
                // different nodes than configure, for instance.
                LOGGER.debug("configure found " + snc.getInternalState() + " node: " + snc.getNameWithID());
                break;
            case CONFIGURED_QUEUED:
            case EXECUTED_QUEUED:
                // should not happen but could if reset has worked on slightly
                // different nodes than configure, for instance.
                LOGGER.debug("configure found " + snc.getInternalState() + " node: " + snc.getNameWithID());
                break;
            default:
                LOGGER.error("configure found weird state (" + snc.getInternalState() + "): " + snc.getNameWithID());
        }
        if (doConfigure) {
            // the stack that previously would have been propagated,
            // used to track changes
            FlowObjectStack oldFOS = snc.createOutFlowObjectStack();
            // create new FlowObjectStack
            boolean flowStackConflict = false;
            FlowObjectStack scsc;
            try {
                scsc = createAndSetFlowObjectStackFor(snc, sos);
            } catch (IllegalFlowObjectStackException e) {
                LOGGER.warn("Unable to merge flow object stacks: " + e.getMessage(), e);
                scsc = new FlowObjectStack(sncID);
                flowStackConflict = true;
            }
            snc.setCredentialsStore(m_credentialsStore);
            // update backwards reference for scopes (e.g. loops)
            if (snc.isModelCompatibleTo(ScopeEndNode.class)) {
                // if this is an END to a scope (e.g. loop), make sure it knows its head
                // (for both: active and inactive loops/scopes)
                Node sncNode = ((NativeNodeContainer) snc).getNode();
                FlowScopeContext fsc = scsc.peek(FlowScopeContext.class);
                if (fsc == null) {
                    // no head found - ignore during configure!
                    sncNode.setScopeStartNode(null);
                } else {
                    // scope/loop seems to be correctly wired - set head
                    NodeContainer headNode = m_workflow.getNode(fsc.getOwner());
                    if (headNode == null) {
                        // odd: head is not in the same workflow,
                        // ignore as well during configure
                        sncNode.setScopeStartNode(null);
                    } else {
                        // head found, let the end node know about it
                        // but only if the start and end nodes have a compatible flow scope context
                        Class<? extends FlowScopeContext> flowScopeContextClass = ((ScopeEndNode<?>) sncNode.getNodeModel()).getFlowScopeContextClass();
                        if (flowScopeContextClass.isAssignableFrom(fsc.getClass())) {
                            sncNode.setScopeStartNode(((NativeNodeContainer) headNode).getNode());
                        }
                    }
                }
            }
            // TODO think about it... happens magically
            for (int i = 0; i < inCount; i++) {
                snc.setInHiLiteHandler(i, hiliteHdls[i]);
            }
            // remember HiLiteHandler on OUTPORTS of all nodes!
            HiLiteHandler[] oldHdl = new HiLiteHandler[snc.getNrOutPorts()];
            for (int i = 0; i < oldHdl.length; i++) {
                oldHdl[i] = snc.getOutPort(i).getHiLiteHandler();
            }
            // configure node itself
            boolean outputSpecsChanged = false;
            if (flowStackConflict) {
                // can't be configured due to stack clash.
                // make sure execution from here on is canceled
                disableNodeForExecution(sncID);
                // (ought to be red with this type of error!)
                if (!snc.getInternalState().equals(IDLE)) {
                    // if not already idle make sure it is!
                    invokeResetOnSingleNodeContainer(snc);
                }
                // report the problem
                snc.setNodeMessage(NodeMessage.merge(oldMessage, NodeMessage.newError("Can't merge FlowVariable Stacks! (likely a loop problem.)")));
                // different outputs - empty ports!
                outputSpecsChanged = true;
            } else {
                outputSpecsChanged = snc.configure(inSpecs, keepNodeMessage);
            }
            // NOTE:
            // no need to clean stacks of LoopEnd nodes - done automagically
            // inside the getFlowObjectStack of the ports of LoopEnd
            // Nodes.
            // check if FlowObjectStacks have changed
            boolean stackChanged = false;
            FlowObjectStack newFOS = snc.createOutFlowObjectStack();
            stackChanged = !newFOS.equals(oldFOS);
            // check if HiLiteHandlers have changed
            boolean hiLiteHdlsChanged = false;
            for (int i = 0; i < oldHdl.length; i++) {
                HiLiteHandler hdl = snc.getOutPort(i).getHiLiteHandler();
                hiLiteHdlsChanged |= (hdl != oldHdl[i]);
            }
            configurationChanged = (outputSpecsChanged || stackChanged || hiLiteHdlsChanged);
            // and finally check if we can queue this node!
            if (snc.getInternalState().equals(UNCONFIGURED_MARKEDFOREXEC) || snc.getInternalState().equals(CONFIGURED_MARKEDFOREXEC)) {
                queueIfQueuable(snc);
            }
        }
    }
    return configurationChanged;
// we have a problem here. Subsequent metanodes with through connections
// need to be configured no matter what - they can change their state
// because 3 nodes before in the pipeline the execute state changed...
// return configurationChanged == configurationChanged;
}
Also used : HiLiteHandler(org.knime.core.node.property.hilite.HiLiteHandler) InteractiveNode(org.knime.core.node.interactive.InteractiveNode) Node(org.knime.core.node.Node) InputNode(org.knime.core.node.dialog.InputNode) DialogNode(org.knime.core.node.dialog.DialogNode) QuickFormInputNode(org.knime.core.quickform.in.QuickFormInputNode) OutputNode(org.knime.core.node.dialog.OutputNode) CredentialsNode(org.knime.core.node.workflow.CredentialsStore.CredentialsNode) MetaNodeDialogNode(org.knime.core.node.dialog.MetaNodeDialogNode) IExtensionPoint(org.eclipse.core.runtime.IExtensionPoint) PortObjectSpec(org.knime.core.node.port.PortObjectSpec)

Example 60 with PortObjectSpec

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

the class Normalizer3NodeModel method configure.

/**
 * All {@link org.knime.core.data.def.IntCell} columns are converted to {@link org.knime.core.data.def.DoubleCell}
 * columns.
 *
 * {@inheritDoc}
 */
@Override
protected PortObjectSpec[] configure(final PortObjectSpec[] inSpecs) throws InvalidSettingsException {
    DataTableSpec spec = (DataTableSpec) inSpecs[0];
    // extract selected numeric columns
    String[] columns = getIncludedComlumns(spec);
    DataTableSpec modelSpec = FilterColumnTable.createFilterTableSpec(spec, columns);
    return new PortObjectSpec[] { Normalizer2.generateNewSpec(spec, columns), modelSpec };
}
Also used : DataTableSpec(org.knime.core.data.DataTableSpec) PortObjectSpec(org.knime.core.node.port.PortObjectSpec)

Aggregations

PortObjectSpec (org.knime.core.node.port.PortObjectSpec)139 DataTableSpec (org.knime.core.data.DataTableSpec)93 InvalidSettingsException (org.knime.core.node.InvalidSettingsException)86 PMMLPortObjectSpec (org.knime.core.node.port.pmml.PMMLPortObjectSpec)35 SettingsModelString (org.knime.core.node.defaultnodesettings.SettingsModelString)30 DataColumnSpec (org.knime.core.data.DataColumnSpec)29 FlowVariablePortObjectSpec (org.knime.core.node.port.flowvariable.FlowVariablePortObjectSpec)25 IOException (java.io.IOException)24 ColumnRearranger (org.knime.core.data.container.ColumnRearranger)24 InactiveBranchPortObjectSpec (org.knime.core.node.port.inactive.InactiveBranchPortObjectSpec)24 PortObject (org.knime.core.node.port.PortObject)19 FlowVariablePortObject (org.knime.core.node.port.flowvariable.FlowVariablePortObject)16 InactiveBranchPortObject (org.knime.core.node.port.inactive.InactiveBranchPortObject)16 PMMLPortObjectSpecCreator (org.knime.core.node.port.pmml.PMMLPortObjectSpecCreator)14 FileStorePortObject (org.knime.core.data.filestore.FileStorePortObject)13 File (java.io.File)12 ArrayList (java.util.ArrayList)12 DatabasePortObjectSpec (org.knime.core.node.port.database.DatabasePortObjectSpec)12 DatabaseQueryConnectionSettings (org.knime.core.node.port.database.DatabaseQueryConnectionSettings)12 PMMLPortObject (org.knime.core.node.port.pmml.PMMLPortObject)12