Testing for ComplexNumberCell type

I am trying to test whether a DataCell is a ComplexNumberCell or not. In my unit tests I set the Cell Type to ComplexNumberCell.TYPE, and I have no problems asking if my cell type is contained in my list of "writeable" cell types.:

 DataType type = inSpec.getColumnSpec(cellIndex).getType();
  if (!writeableTypes.contains(type)) {

However, when I look at the DataTableSpec from a Rename node which has changed a double into a complex I don't see "ComplexNumberCell" listed as the type, and instead a long string "Non-native [interface org.knime.core.data.BoundedValue,...", and my test fails . Is this a bug, or do I need to be doing the comparison in a different way?

Hi Joe,

the short answer: your check is wrong. Type compatibility should be checked using DataType#isCompatible(SomeDataValue.class) method, not just plain equality on DataTypes.

Your test whether a DataCell is a ComplexNumberCell or not, should actually be of no interest (not that I want to tell you what you should be interested in). You should rather ask whether a DataCell (or the cells in a column) can represent itself as (isCompatibleTo) ComplexNumberVALUE. If so, you can safely typecast any cell, which is not cell.isMissing(), as ComplexNumberValue.

The types that are part of core KNIME (DoubleCell, IntCell, ComplexNumberCell, etc...) implement all DataValues, to which they can represent itself loss-free. As such DoubleCell and IntCell also implement ComplexNumberValue (you can typecast those cells) and they will return you as real part the double (or the underlying int in an IntCell) and as imaginary part 0.0

Regarding the rename node: When you choose to change the type of a column, whose type is DoubleCell.TYPE, to e.g. ComplexNumberValue, then you don't actually change the content of the column (it will still contain DoubleCells) but you just modify the type associated with the column. It is changed to have ComplexNumberValue as its preferred value (which is sometimes of great interest in case the new preferred value has a dedicated renderer or comparator - which is then used in downstream nodes). This new type is said to be "non-native" as it is not derived from an actual cell implementation but is artificially created. The new type will be compatible to the exact same XXXValues as the old type, though the old type and the new one won't be equal.

Does it make sense? What do you try to do in your node implementation? Maybe I can be of concrete help if I know what you try to accomplish.


Hi Bernd,
I knew about the "isCompatable()" testing, but I need to be a bit more anal.

I am writing the data block in an SDFile, so I want to be able to write StringCells, but I don't want to write an SdfCell (in the middle of the datablock it will cause no end to trouble). For completeness I was going to allow CompexNumberCells, although I don't have a use case for it. I can recode my test to use a hierarchy of "isCompatable"s to this end, it just seemed less elegant at the time.


I see, this is then a counterexample of when you don't want to have these type hierarchies. You want to make sure that something is a string and only a string. Still, testing on equality of the DataType (in this case StringCell.TYPE) is risky as you potentially miss out on other types that are (plain) strings. One scenario is that we (or you) decide on having a StringBlobCell (for very large Strings), which implements the same value interfaces but has a different cell implementation (which is suited to be handled more efficiently). StringBlobCell is ok in the data block but another SdfCell is not.

The only solution I see so far is to do

DataType columnType = ...
boolean isOk = typeInColumn.isASuperTypeOf(StringCell.TYPE) 
               && StringCell.TYPE.isASuperTypeOf(typeInColumn);

The two method calls on DataType#isASuperTypeOf(DataType) ensure that both types are mutual compatible. (It's like checking equals except for the preferred value test).

Not very elegant - but it should be correct.

One more comment: Even if the above test evaluates to true, it may be that the column contains SdfCells. Imagine if the user concatenates two tables, whereby the first table contains a column called "A" and is of type StringCell.TYPE and the second table also contains "A" but with a SdfCell.TYPE. If you then concatenate these two tables, the common super type of StringCell.TYPE and SdfCell.TYPE is used ... which is a StringCell.TYPE.

... only for the sake of completeness. There is no absolute guarantee.

Hi Bernd,

Correctness wins out over elegance in my book. Thanks for the code snippet, it should improve the robustness of our nodes.