6 Replies Latest reply: Oct 8, 2010 5:03 PM by 796440 RSS

    Create empty interface implementation object refference

    802645
      Hi
      I have an Interface:
      import java.util.Vector;
      import net.sourceforge.floggy.persistence.Persistable;
      
      public interface Table extends Persistable {
      
          static final char DELIMITER_CHAR = ';';
          //public static boolean hasCounter;
      
          public String getUniqueDescription();
      
          public String getRecordAsListed();
      
          public String getFieldFromIndex(int index);
      
          public void setFieldFromIndex(String data, int index);
      
          public String getCSVstring();
      
          public String getCSVstringWithQuotes();
      
          public void setFromCSV(String[] csv);
      
          public void setFromFormItems(Vector items);
      }
      This interface is implemented by several Persistable classes.
      The following method in an another class is used to load up a Table reference from the recordset (aka RMS)
      ...
      private Table table;
      
          public void loadRecord() {
              if (isRecordSelected()) {
                  try {
                      table = null;
                      table = (Table) objectset.get(recordsList.getSelectedIndex());
                       ...
                  } catch (FloggyException fe) {
                      ...
                  }
              }
          }
      The problem is when I want to "save to a Table"
      When I didn't use an interface the case was as simple as:
      private Table table;
      
           public void newRecord() {
      table = new tblClient();
      table.setCode(getTxtCode().getString());
      ...
      pm.save(table);
           }
      Where tblClient was a Persistable class.

      Now that tblClients implements Table and I want to handle the records using the interface to create reusable code regardless of the persistable class'es fields, I have a problem.
      I can't instantiate an Interface as:
      table = new Table();
      So if table is null I get "java.lang.IllegalArgumentException: The persistable object cannot be null!"
      What can I do to overcome that issue?

      I thought of creating an empty class implementing Table so as I am able to refer to the empty class implementing the interface to be able to set fields and save it.

      PS. I used an Interface instead of an abstract class because the Persistable classes already extend another class.

      Edited by: Dimitrios on Oct 7, 2010 4:43 PM
        • 1. Re: Create empty interface implementation object refference
          796440
          So, without interfaces, when someone calls your code
          doSomething(table);
          your doSomething method looks like
          public void doSomething(Table table) {
            if (table == null) {
              table = new Table();
            }
          
            // do real work with table
          }
          So the first question is, does it really make sense to do it that way? That is, is null a valid value to have at that point, with the meaning being "just create any old Table on the fly, don't worry about what's in it, and use that"? If that really is valid in terms of what that code's job is, then fine. If not, though, then you should be throwing IllegalArgumentException or NullPointerException. Don't try to "handle" bad input by doing something meaningless. This will hold whether you use an interface or just a concrete class.

          Now, if it really is valid, appropriate, and meaningful for null to mean "just whip up whatever table you want and use it," then you'll need to provide an implementation that suits that. Maybe its an anonymous inner class that does nothing. Maybe it's a named class like "DummyTable" that does just what your plain old Table class did before.

          Presumably you're not just defining an interface for its own sake. You want to define a type--Table--and that type can have multiple different implementations. And either some third party is providing those various implementations, or you're creating various implementations of your own to meet your varying table needs, yes?
          • 2. Re: Create empty interface implementation object refference
            802645
            Excuse me, I left the method definition out of the code. Corrected it now.
            Both newRecord and loadRecord don't check if table is null. newRecord explicitly assigns a new object reference and loadRecord gets a table reference from the objectset.
            Since I can't instantiate Table as it is an interface, how do I set a reference to an object if I want to add a new record before any was loaded?

            In other words how can I replace table = new Table();

            I created a dummy class that implements the interface's methods (with empty implementations actually, returning empty String when needed), but doesn't seem to work.

            PS. The scenario I describe is valid. The table being used is defined with a .classForName(). So any class that implements Table would do.

            I wrote the interface to be able to handle all tables' "data" from a single fragment of code, to be able to reuse it and maintain it better. And you are right I am using this to "abstract" from the different class members and handle each implementation differently.

            Thank you for your response.
            • 3. Re: Create empty interface implementation object refference
              796440
              I guess I don't understand your problem. Either you are creating a Table in your code or you're getting one from somewhere else. Either way, regardless of whether Table is an interface or a class, there must be some concrete class that IS-A Table, somewhere. Whether it's simply your Table class as-is, or some ConcreteTableImpl implements Table. Whatever is currently creating a plain old concrete Table can switch from:
              Table t = new Table();
              to
              Table t = new ConcreteTableImpl();
              • 4. Re: Create empty interface implementation object refference
                796440
                Dimitrios wrote:
                doesn't seem to work.
                "Doesn't work" carries no useful information.

                Provide an accurate [url http://sscce.org]SSCCE that demonstrates the previous situation--with the concrete Table class--and one that demonstrates what you're trying to do now, and explain clearly what exactly "doesn't work" means in this situation. Don't include any code that's not related to the structural issues at hand. If you have to create 3 or 4 completely new, dummy classes, that's fine, as long as they show the relationships of these classes and interfaces. For instance, if your current Table class/interface has 10 public methods, your SSCCE can have just 1, unless you need to, say, explicitly show the difference between a couple of different methods.

                Edited by: jverd on Oct 7, 2010 5:10 PM
                • 5. Re: Create empty interface implementation object refference
                  802645
                  Sorry about "doesn't seem to work" I was reworking the code trying to make it work.

                  So:

                  I had some Classes that all implemented Persistable:
                  import net.sourceforge.floggy.persistence.Persistable;
                  
                  public class tblClient implements Persistable{
                  
                      //private int ID;
                      private String Code;
                      private String Fullname;
                      private String JobTitle;
                      private String Address;
                      ...
                  
                      public void setFieldFromIndex(String data, int index) {
                              switch (index) {
                                  case 0: this.Code = data;break;
                                  case 1:this.Fullname = data;break;
                                  case 2:this.Address = data;break;
                  ...
                              }
                      }
                      public String getCode() {
                          return Code;
                      }
                  
                      public void setCode(String Code) {
                          this.Code = Code;
                      }
                  ... //Getters and Setters for all other class members
                  import net.sourceforge.floggy.persistence.Persistable;
                  
                  public class tblTransportName implements Persistable {
                  
                      private String Name;
                      private int fKind;
                  ...
                  
                      public void setFieldFromIndex(String data, int index) {
                              switch (index) {
                                  case 0: this.Name = data;break;
                                  case 1:this.fKind = data;break;
                  ...
                              }
                      }
                  
                      public String getName() {
                          return Name;
                      }
                      public void setName(String Name){
                          this.Name = Name;
                      }
                  
                  ... //Getters and Setters for all other class members
                      public boolean saveRecord() {
                   ...
                  PersistableManager pm = PersistableManager.getInstance();
                  Table table = new tblCLient();
                  
                                              table.setCode(getTxtCode().getString());
                                              table.setFullname(getTxtFullname().getString());
                                              table.setJobTitle(getTxtJobTitle().getString());
                                              table.setAddress(getTxtAddress().getString());
                    
                                      int id = pm.save(table);
                                      return true;
                              } catch (FloggyException e) {
                                      e.printStackTrace();
                                      return false;
                              }
                      }
                      public boolean saveRecord() {
                  
                          try {
                   ...
                  PersistableManager pm = PersistableManager.getInstance();
                  Table table = new tblTransportNames();
                              table.setName(getTxtName().getString());
                              table.setKindFromString(getChkKind().getString(getChkKind().getSelectedIndex()).substring(0, 1));
                  
                              int id = pm.save(table);
                              return true;
                          } catch (FloggyException e) {
                              switchDisplayable(null, new Alert("ΣΦΑΛΜΑ", "Αναφορά Σφάλματος: " + e, null, AlertType.ERROR));
                              e.printStackTrace();
                              return false;
                          }
                      }
                  So for each persistable class I want to "save" to I have different code which makes it very hard to maintain given that most of the code is the same except from the classes' object instantiation and fields assignement.

                  NOW!
                  I want to abstract the code to save record so it can be used to "save" to ANY persistable class.
                  To accomplish that, I created an interface (Table) that abstracts methods to get / set each persistable class'es fields without having specific getters / setters for each class. To accomplish this I use Arrays, Vectors, Hashmaps, etc. This solves the
                              table.setName(getTxtName().getString());
                              table.setKindFromString(getChkKind().getString(getChkKind().getSelectedIndex()).substring(0, 1));
                  part of the problem. It is well tested and works well.

                  HOWEVER I have no idea how to instantiate a new class to use the methods in it as I can't instantiate an Interface, so I can't do Table table = new Table();
                  When "loading data" I have no problem using
                   table = (Table) objectset.get(recordsList.getSelectedIndex()); 
                  This also works.

                  The problem is when I want to create a new record and save it.
                  Saving it is solved (as described above).
                  What I cannot accomplish is create a new record (instantiate a new class to pass in the objects to save that is).

                  I created a dummy class EmptyClass so I use
                  Table table = new EmptyTable();
                  import net.sourceforge.floggy.persistence.Persistable;
                  
                  public class EmptyTable implements Persistable, Table {
                  
                  
                      public String getUniqueDescription() {
                          return "";
                      }
                  
                      public String getRecordAsListed() {
                          return "";
                      }
                  
                      public String getFieldFromIndex(int index) {
                          return "";
                      }
                  
                      public void setFieldFromIndex(String data, int index) {
                      }
                  
                      public String getCSVstring() {
                          return "";
                      }
                  
                      public String getCSVstringWithQuotes() {
                          return "";
                      }
                  
                      public void setFromCSV(String[] csv) {
                      }
                  
                      public void setFromFormItems(Vector items) {
                      }
                  }
                  The problem is when I try to set a tblClient's field using setFieldFromIndex and save it, it doesn't save it, without throwing any exception. I find out it doesn't work when I try to load the record, which hasn't been saved.

                  The point is setFieldFromIndex doens't work because it is not implemented in EmptyTable. Even if I did implemented it somehow it could not know the fields that would be present in tblClients.
                  I think that this way, it is never going to work.

                  boldLoading works because:*bold*
                      public void initRecords() {
                          try {
                  ...
                  PersistableManager pm = PersistableManager.getInstance();
                  private Class tableModel;
                  ....
                  tableModel = Class.forName("tblClients");
                              objectset = pm.find(tableModel, filterRecords, sortRecords);
                              if (objectset.size() > 0) {
                                  for (int i = 0; i < objectset.size(); i++) {
                                      table = (Table) objectset.get(i);
                                      recordsList.append(table.getRecordAsListed(), null);
                                  }
                                  ...
                              } else {
                                  DisplayManager.setCurrent(new Alert("ΕΙΔΟΠΟΙΗΣΗ", "Δεν υπάρχουν ή δεν βρέθηκαν εγγραφές σύμφωνα με τα κριτήρια.", null, AlertType.INFO));
                              }
                          } catch (FloggyException fe) {
                              new ErrorLog(fe);
                          } 
                      }
                  In the previous code the class to be searched is passed as a class (using reflection).
                  I guess the problem would be solved if I could just do:
                  Table table = new Class.forName("tblClients");
                  BUT I CAN'T!!
                  Is there a way to implement this with some equivalent code?
                  Reflection in j2me only has classForName and getClass (Damn!!!)

                  UPDATE:
                  I want to hit my head on a WALL!!!
                  It's so simple
                          try {
                              //        table = new EmptyTable();
                              table = (Table) ( tableModel.newInstance() );
                          } catch (IllegalAccessException ex) {
                              ex.printStackTrace();
                          } catch (InstantiationException ex) {
                              ex.printStackTrace();
                          }
                  Should work even without casting.
                  Problem seems solved!
                  I got to pissed off by the absence of Reflection that I forgot the basics. (You can kick me in the butt now!).

                  Edited by: Dimitrios on Oct 8, 2010 2:58 PM
                  • 6. Re: Create empty interface implementation object refference
                    796440
                    Sorry, but there's no way I'm gonna read all that. Good luck though!