Wo3 Hen3 Chan2

Wo3 Hen3 Chan2: Design

Individual data sources are abstracted with a set of interfaces found in net.sourceforge.wohenchan.convert.

The interfaces are:

The driving idea behind these interfaces is that they be as simple as possible while still generalizing functionality found in all of the underlying data sources. A secondary concern is that they be designed in such a way as to make the implementation of the requirements easy to do.

Proposal, attempt #1

While thinking about task 21232, I would like to resolve the following issues:

I woud like to propose the following means of helping deal with these issues:

  1. all methods in ConverterTableInterface have their return types changed to ConverterResultsInterface, described below.
  2. all methods on ConverterTableInterface are given an extra parameter of type ConverterListener, also described below.
  3. Deprecate and remove ConverterFactoryInterface.
  4. require all ConverterTableInterface implementations to implement a default constructor. This constructor must not block on IO or take a long time to complete.
  5. add a method init() to ConverterTableInterface which will be called in a thread and will do any long-running initialization needed (downloading files, reading in files, etc.)
  6. Temporarily, all ConverterFactoryInterface methods are moved into ConverterTableInterface. These may be deprecated later if it turns out that we only want to do status through ConverterResultsInterface
Here is a proposed contents for ConverterResultsInterface:
public interface ConverterResultsInterface
{

}
Here is a proposed contents for ConverterListener:
public interface ConverterListener
{
   /**
    * Called to inform interested parties that something happened
    * w.r.t this search.
    **/
   handleConverterEvent (ConverterEvent evt)
}

public class ConverterEvent
{
   public static class EventType
   {
      /**
       * Once this event happens, there should be no more events.
       **/
      public static EventType SEARCH_DONE;

      /**
       * this is an update to the percentage progress of the current
       * task.  Note that, as there may be more than one task involved
       * in a search, that a return of 100 here does not mean
       * SEARCH_DONE is immediately pending.  there may be more tasks.
       **/
      public static EventType PROGRESS_UPDATE;

      /**
       * the current task has changed. (e.g. "downloading unihan.txt",
       * "searching", "parsing result page", etc.);
       **/
      public static EventType TASK_CHANGE;

      /**
       * an entry has been found.
       **/
      public static EventType ENTRY_FOUND;

      /**
       * a problem or unusual condition has occured.
       **/
      public static EventType STATUS_MESSAGE;
   }

   public ConverterEvent (ConverterEntryInterface result,
                          String status,
                          String taskName,
                          int progress)
   {
   }

   public EventType getEventType()
   {
   }

   public ConverterEntryInterface getEntry()
   {
   }

   public String getStatusMessage()
   {
   }
}

This is, in essence a union of two streams -- one for ConverterEntryInterface and one for errors.

There are several possible ways to structure the streams

The reasoning behind picking the callback implementation was:

Unfortunately,

In order to try to get around some of the issues brought up above, we introduce another object:

public class ConverterCursor implements ConverterListener
{
   /**
    * blocks until there is a new log message available.  if we have
    * reached the end, throw NoSuchElementException
    **/
   public ConverterEvent getNextEvent() throws SearchFinishedException
}

This design will have to satisfy several users on both sides:

Bah. This sucks.

Proposal, attempt #2

A ConverterTableInterface:

Any input task:

The obvious mapping of this second concept to a class is as follows:
public abstract class InputTask extends Thread
{
   public void addConverterListener (ConverterListener listener)
   {
   }
}

Remove from the above proposal the idea of init()

This design will have to satisfy several users on both sides of the interface boundary: