Search code examples
javacastingdatarowjdesktop

Casting DataRow to Strongly-Typed DataRow


I have a class that extends DataRow:

import org.jdesktop.dataset.DataRow;

public class MainDataRow extends DataRow {
  private MainDataTable baseDataTable;

  protected MainDataRow(MainDataTable dt) {
    super(dt);
    this.baseDataTable = dt;
  }

  public int    getId()                           { return (int)    super.getValue(baseDataTable.getColId()); };
  public void   setId(int id)                     {                 super.setValue(baseDataTable.getColId(), id); };
  public int    getDelta()                        { return (int)    super.getValue(baseDataTable.getColDelta()); };
  public void   setDelta(int delta)               {                 super.setValue(baseDataTable.getColDelta(), delta); };
  public String getNombre()                       { return (String) super.getValue(baseDataTable.getColNombre()); };
  public void   setNombre(String nombre)          {                 super.setValue(baseDataTable.getColNombre(), nombre); };

Also MainDataTable extends DataTable, and returns valid columns for getColId(), getColDelta(), getColNombre().

I would like to do:

MainDataTable dt = new MainDataTable(ds);
MainDataRow dr = (MainDataRow) dt.appendRow();

But this is not possible due to a CastClassException (dt.appendRow return DataRow and MainDataRow is extending DataRow, not vice versa, so the only possibility could be something similar to DataRow dr = (DataRow) new MainDataRow(dt);).

In c++ it can be easyly achieved through DataRowBuilder, overriding NewRowFromBuilder() in MainDataTable and overriding the protected creator from DataRowBuilder in MainDataRow (Casting DataRow to Strongly-Typed DataRow: How do they do it?).

How could I do it in Java?

Edit

MainDataTable class:

public class MainDataTable extends TypedDataTable<MainDataRow> {
...
}

And TypedDataTable class:

public abstract class TypedDataTable<TypeOfRow> extends DataTable {
  protected boolean locked;

  public TypedDataTable(DataSet ds, boolean appendRowSupported) {
    super(ds);
    InitClass();
    super.setAppendRowSupported(appendRowSupported);
    locked = false;
  }

  public Object clone() {
    try {
      return super.clone();
    } catch (CloneNotSupportedException e) {
      e.printStackTrace();
      return null;
    }
  }

  @Override
  public abstract DataRow appendRow();
  @Override
  public abstract DataRow appendRowNoEvent();
  public abstract void InitVars();
  public abstract void InitClass();

  public boolean isLocked() {
    return locked;
  }

  public void setLocked(boolean locked) {
    this.locked = locked;
  }
}

Solution

  • Override appendRow() and appendRowNoEvent() in MainDataTable to return a MainDataRow

    public abstract class TypedDataTable<TypeOfRow extends DataRow> extends DataTable {
      protected boolean locked;
    
      public TypedDataTable(DataSet ds, boolean appendRowSupported) {
        super(ds);
        InitClass();
        super.setAppendRowSupported(appendRowSupported);
        locked = false;
      }
    
      public Object clone() {
        try {
          return super.clone();
        } catch (CloneNotSupportedException e) {
          e.printStackTrace();
          return null;
        }
      }
    
     @Override
     public TypeOfRow appendRowNoEvent() {
         if (appendRowSupported) {
             TypeOfRow row = createDataRow(); //<-- HERE we create a MainDataRow!!!
             rows.add(row);
             return row;
         } else {
             return null;
         }
     }
    
     @Override
     public TypeOfRow appendRow() {
          return (TypeOfRow)super.appendRow();
     }
    
      public abstract TypeOfRow createDataRow();
      public abstract void InitVars();
      public abstract void InitClass();
    
      public boolean isLocked() {
        return locked;
      }
    
      public void setLocked(boolean locked) {
        this.locked = locked;
      }
    }