The configure Method

The above described methods are only one step to check whether the node is executable with the current settings. It is also very important to check whether or not it might work with the incoming data table. This is accomplished by the configure method. The configure method is called as soon as the inport has been connected. In the small example of our numeric binner, a check is performed to see if at least one numeric column is available and if the incoming data table contains a column with the selected column name. otherwise the node is not executable. The DataTableSpec contains the required information and is passed to the configure method.

	/**
     * {@inheritDoc}
     */
    protected DataTableSpec[] configure(final DataTableSpec[] inSpecs)
            throws InvalidSettingsException {
        // first of all validate the incoming data table spec
        
        boolean hasNumericColumn = false;
        boolean containsName = false;
        for (int i = 0; i < inSpecs[IN_PORT].getNumColumns(); i++) {
            DataColumnSpec columnSpec = inSpecs[IN_PORT].getColumnSpec(i);
            // we can only work with it, if it contains  
            // at least one numeric column 
            if (columnSpec.getType().isCompatible(DoubleValue.class)) {
                // found one numeric column
                hasNumericColumn = true;
            }
            // and if the column name is set  
            // it must be contained in the data table spec
            if (m_column != null 
                    && columnSpec.getName().equals(
                    m_column.getStringValue())) {
                containsName = true;
            }
            
        }
        if (!hasNumericColumn) {
            throw new InvalidSettingsException(
                    "Input table must contain at least "
                    + "one numeric column");
        }
        
        if (!containsName) {
            throw new InvalidSettingsException(
                    "Input table contains not the column " 
                    + m_column.getStringValue() 
                    + " . Please (re-)configure the node.");
        }
        
        
        // so far the input is checked and the algorithm can work with the 
        // incoming data
        ...

Just as we rely on the incoming specification of the data, the successor nodes also require information about the data format, which is provided after execution. For this reason, a specification for the output of our node must also be created in the configure method.

	...
	// now produce the output table spec, 
    // i.e. specify the output of this node
    DataColumnSpec newColumnSpec = createOutputColumnSpec();
    // and the DataTableSpec for the appended part
    DataTableSpec appendedSpec = new DataTableSpec(newColumnSpec);
    // since it is only appended the new output spec contains both:
    // the original spec and the appended one
    DataTableSpec outputSpec = new DataTableSpec(inSpecs[IN_PORT],
            appendedSpec);
    return new DataTableSpec[]{outputSpec};
	...

Since a DataColumnSpec must be created for the newly appended column in both the configure and the execute method, the code for the creation of the DataColumnSpec is extracted in a separate method:

	private DataColumnSpec createOutputColumnSpec() {
        // we want to add a column with the number of the bin 
        DataColumnSpecCreator colSpecCreator = new DataColumnSpecCreator(
                "Bin Number", IntCell.TYPE);
        // if we know the number of bins we also know the number of possible
        // values of that new column
        DataColumnDomainCreator domainCreator = new DataColumnDomainCreator(
                new IntCell(0), new IntCell(m_numberOfBins.getIntValue() - 1));
        // and can add this domain information to the output spec
        colSpecCreator.setDomain(domainCreator.createDomain());
        // now the column spec can be created
        DataColumnSpec newColumnSpec = colSpecCreator.createSpec();
        return newColumnSpec;
    }