Better to use ColumnRearrager ?

I have implemented a node which adds data to the input table by reading a file (configured by the user). I have to parse the file to say how many columns will be added and which data type they will have.

It looked pretty 'complicated' to me to create a new SingleCellFactory for each column I want to add and I could not contribute something usefull to the getCell-method, as I don't know the new content.

What I did instead to create the output specs:

private DataTableSpec createOutSpec(DataTableSpec inSpec) {

        List<DataColumnSpec> cSpecs = new ArrayList<DataColumnSpec>();

        // collect all columns from the incoming table
        for(DataColumnSpec curSpec : inSpec) cSpecs.add(curSpec);

        // add all layout columns (later containing the layout data)
        for(... list of new column names and their data types ...) {
            DataColumnSpecCreator dcsc = new DataColumnSpecCreator(...current column name, ... current data type ...);

        return new DataTableSpec(inSpec.getName(), (DataColumnSpec[]) cSpecs.toArray(new DataColumnSpec[cSpecs.size()]));

In the execute-method:

BufferedDataContainer con = exec.createDataContainer(createOutSpec(inSpec));

for(DataRow curRow : inTable) {

DataRow extendRow = curRow;
for(... list of new column names and their data types ...) {
                extendRow = AppendedColumnRow(extendRow, ... new cell ...);



Is it a bad style to do it this way? It works so far... Just want to know whether it might result in some kind of bad performance or other problems...

The ColumnRearranger is the fastest way of adding new columns using an AppendedColumnRow will duplicate existing data.

Instead of using several SingleCellFactories you should use an implementation of the CellFactory interface that returns an array of DataCells (which are the columns). If you don't know the content for the getCell method during configure this is not a problem, that is the case in many node using the ColumnRearranger. The getCells is only called during execute so it doesn't hurt if information is missing at this stage.

Okay, so I will try to change it again.

In case of multiple columns, I would have to use an implementation of the AbstractCellFactory, right?

How do I create the content of the new columns then? I don't find a good example... maybe you can point to the implementation of certain KNIME node where I can have a look how to do it...

did my last message arrive? (it was reported as spam again.)

I still don't know how to fill new columns with content... I tried to put the code I used in execute before in the getCells()-method of an AbstractCellFactory but I cannot access model settings there. And I don't know how to handle exceptions (I wanted to allow double and int columns but in the execute method, I checked if the value is a whole number or not and threw an exception. But if I migrate it into the getCells() method, I cannot throw that Exception anymore.

I'm pretty confused and the simple examples I found do not really help me.

If you search for subclasses of the CellFactory interface or the AbstractCellFactory class (use F4 in Eclipse on the interface name), you will find lots of examples.

If you need access to the model settings you either need to implement you cell factory as an inner class of the model or pass the required settings in the constructor of the "external" cell factory.

If you want the node to fail when an exception occurs, you have to throw a RuntimeException in getCells (you can nest the original exception in a RuntimeException using the appropriate constructor). But probably it's better to insert missing values instead and issue warnings.

Thanks a lot for your help.

But probably it's better to insert missing values instead and issue warnings.

And how would I generate a warning from the CellFactory?

The last question was a stupid one, no? I can use the logger to throw a warning...

The NodeLogger can be used to report DEBUG, WARN, INFO and ERROR messages within the KNIME Console. If you want to show a warning at the node (yellow triangle) use NodeModel#setWarningMessage(String).