Example NodeModel

The following code reads the user input through SettingsModels into the NodeModel:

Example #1

	/**
 * The node model to the demo default dialog.
 */
public class DemoNodeModel extends NodeModel {

    /**
     * The following strings are used by the dialog and the model
     * as key to store settings in the settings object.
     */

    static final String STR = "str";
    static final String INT = "int";
    static final String DBL = "dbl";
    static final String BOOL = "bool";
    static final String STRSEL = "selStr";
    static final String COLSEL = "selCol";

    /**
     * These are the members storing user settings.
     * Use the same settings model (but a new instance) as in
     * the node dialog for that value.
     */

    private final SettingsModelString m_str =
            new SettingsModelString(STR, null);

    private final SettingsModelIntegerBounded m_intBounded =
            new SettingsModelIntegerBounded(INT, 4, 1, 17);

    private final SettingsModelDouble m_dbl =
            new SettingsModelDouble(DBL, .4);

    private final SettingsModelBoolean m_bool =
            new SettingsModelBoolean(BOOL, true);

    private final SettingsModelString m_selStr =
            new SettingsModelString(STRSEL, null);

    private final SettingsModelString m_colSel =
        new SettingsModelString(COLSEL, "none");

    /** The constructor */
    DemoNodeModel() {
        super(1, 0);
    }

    [...]

    /** {@inheritDoc} */
    @Override
    protected void loadValidatedSettingsFrom(final NodeSettingsRO settings)
            throws InvalidSettingsException {
        m_bool.loadSettingsFrom(settings);
        m_dbl.loadSettingsFrom(settings);
        m_intBounded.loadSettingsFrom(settings);
        m_selStr.loadSettingsFrom(settings);
        m_str.loadSettingsFrom(settings);
        m_colSel.loadSettingsFrom(settings);
    }


    /** {@inheritDoc} */
    @Override
    protected void saveSettingsTo(final NodeSettingsWO settings) {
        m_bool.saveSettingsTo(settings);
        m_dbl.saveSettingsTo(settings);
        m_intBounded.saveSettingsTo(settings);
        m_selStr.saveSettingsTo(settings);
        m_str.saveSettingsTo(settings);
        m_colSel.saveSettingsTo(settings);
    }


    /** {@inheritDoc} */
    @Override
    protected void validateSettings(final NodeSettingsRO settings)
            throws InvalidSettingsException {
        m_bool.validateSettings(settings);
        m_dbl.validateSettings(settings);
        m_intBounded.validateSettings(settings);
        m_selStr.validateSettings(settings);
        m_str.validateSettings(settings);
        m_colSel.validateSettings(settings);
    }


    /** {@inheritDoc} */
    @Override
    protected BufferedDataTable[] execute(final BufferedDataTable[] inData,
            final ExecutionContext exec) throws Exception {

        if (m_bool.getBooleanValue()) {
            double d = m_dbl.getDoubleValue() * 2.5;
        }
        int i = m_intBounded.getIntValue();

        // i is larger than 0 and smaller than 18 (because the model used
        // is a SettingsModelIntBounded with these limits).

        if (m_selStr.getStringValue() != null) {
            m_str.setStringValue(m_colSel.getStringValue());
        }

        return new BufferedDataTable[0];
    }
}

For each component/setting value, add a member holding the corresponding SettingsModel. Use exactly the same type of SettingsModel as the component in the dialog. The SettingsModels provide load, save, and validate methods that just need to be called in the corresponding method of the NodeModel. This takes care of the saving and loading of these values and also transfers them into the dialog and the new user values back from the dialog. To access the current value in the SettingsModel, call the corresponding getter-method. SettingModels also provide a public setter-method to change their value.

If there are dependencies to check between two settings values, the validateSettings method becomes a bit more complicated because if a settings model validates one value but it does not store that value, thus you have no access to that first value you are supposed to validate against a second. If you need to check some values against each other (like, to ensure that the new minimum is smaller than the specified maximum, for example), you need to create new temporary settings models, load the new values in, read and verify them, and release the settings models at the end. Here is a code example:

Example #2

    /** {@inheritDoc} */
    @Override
    protected void validateSettings(final NodeSettingsRO settings)
            throws InvalidSettingsException {

        // create new (temp) settings models
        // (if m_min and m_max are fields of the NodeModel)

        SettingsModelInteger min =
                   m_min.createCloneWithValidatedValue(MIN, settings);
        SettingsModelInteger max =
                   m_max.createCloneWithValidatedValue(MAX, settings);

        if (min.getIntValue() >= max.getIntValue()) {
            throw new InvalidSettingsException("The specified minimum "
                   + "must be smaller than the maximum value.");
        }

        m_dbl.validateSettings(settings);
        m_intBounded.validateSettings(settings);
        m_selStr.validateSettings(settings);
        m_colSel.validateSettings(settings);
    }

With the createCloneWithValidatedValue method, create a temporary settings model with the new value from a NodeSettings object. Use this temporary object to access the new value, but make sure not to change any permanent variables in the NodeModel. Release the clone models after validateSettings finishes.

Use static create-methods to instantiate SettingsModels:

Because you need instances of identical SettingsModels in two places (in the NodeModel and the NodeDialog constructor) it is probably a good idea to implement static methods that create these instances and to then just call these methods in both places. For example, add the following method to your NodeModel:

static SettingsModelIntegerBounded createRangeSettingsModel() {
    return new SettingsModelIntegerBounded("Range", 4, 1, 17);
}

Now, your dialog constructor looks like:

addDialogComponent(new DialogComponentNumber(MyNodeModel.createRangeSettingsModel());

and the node model:

private final SettingsModelIntegerBounded m_intBounded = createRangeSettingsModel();

The code is simpler, and more importantly, it is ensured that you really use the same SettingsModels with the same parameters and same IDs.