Question

I have an interesting question.

I have created an interface as so; the idea is that a class which implements this interface will have to implement the TimeRangeBuilder too

import java.util.Date;

public interface TimeRange<T> extends Comparable<T> {   

    public static interface TimeRangeBuilder<T> {
        public TimeRangeBuilder<T> startDate(Date startDate);
        public TimeRangeBuilder<T> endDate(Date endDate);
        public T build();
    }

    public Date getStartDate();
    public Date getEndDate();
}

But unfortunately this isn't how it works; when I implement this interface in a concrete class; the implementation of the TimeRangeBuilder is completely optional.

To give you an idea of where I'm heading, here is my implementation class

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import ru.crystals.videoutil.utils.TimeRange;

public class VidArchive implements TimeRange<VidArchive> {
    /** date format used to convert Date objects to human-readable form for the toString() function */
    private static final DateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm:ss");

    private final byte[] bytes;
    private final String cam;
    private final Date startDate;
    private final Date endDate;
    private final String fileName;
    private final String directory;

    public static class Builder implements TimeRangeBuilder<VidArchive> {
        private byte[] bytes;
        private String cam;
        private Date startDate;
        private Date endDate;
        private String fileName;
        private String directory;

        public Builder() {}
        public Builder bytes(byte[] bytes)          { this.bytes = bytes;           return this;    }
        public Builder cam(String cam)              { this.cam = cam;               return this;    }
        @Override
        public Builder startDate(Date startDate)    { this.startDate = startDate;   return this;    }
        @Override
        public Builder endDate(Date endDate)        { this.endDate = endDate;       return this;    }
        public Builder fileName(String fileName)    { this.fileName = fileName;     return this;    }
        public Builder directory(String directory)  { this.directory = directory;   return this;    }
        @Override
        public VidArchive build()                   { return new VidArchive(this);                  }
    }

    private VidArchive(Builder builder) {
        bytes = builder.bytes;
        cam = builder.cam;
        startDate = builder.startDate;
        endDate = builder.endDate;
        fileName = builder.fileName;
        directory = builder.directory;
    }   

    public byte[] getBytes()        {   return bytes;       }
    public String getCam()          {   return cam;         }
    @Override
    public Date getStartDate()      {   return startDate;   }
    @Override
    public Date getEndDate()        {   return endDate;     }
    public String getFileName()     {   return fileName;    }
    public String getDirectory()    {   return directory;   }

    @Override
    public int compareTo(VidArchive vidArchive) {
        return startDate.compareTo(vidArchive.getStartDate());
    }

    @Override
    public String toString() {
        return DATE_FORMAT.format(startDate) + " - " + DATE_FORMAT.format(endDate);
    }
}

And it all comes down to this; I have another class that should compatible not only with the VidArchive class, but all implementations of the TimeRange interface. Here is the code that I want to get working

public class TimeBar<E extends TimeRange<E>> extends JProgressBar {
    private TreeSet<E> timeRanges;
    ...

    ...
    public void seekToTime() {
        /** create a dummy object (an implementation of the TimeRange interface) with the most recent date set in TimeBarUI, so that it can be compared
         *  to all the other objects in the set in order to find the closest one by time*/
        E archive = new E.Builder().
                        startDate(((TimeBarUI)ui).getMostRecentDate()).
                        endDate(((TimeBarUI)ui).getMostRecentDate()).
                        build();
        TimeRange<E> closest = timeRanges.headSet(archive, true).last();
        ...
    }
}

As you gentlemen can imagine; that whole E.Builder() thing.. yep, it doesn't work. Help me to get it to work, or find an alternative solution to my conundrum (I would be open to an alternative Builder implementation, but I would very much like to keep my Builder.

P.S. Any other suggestions in regards to my code would be welcome too. I'm always eager to improve.

Was it helpful?

Solution

I am not sure to understand but is it what you try to achieve ?

import java.util.Date;

public interface TimeRange<T,K> extends Comparable<T> {

  public K Builder();

  public static interface TimeRangeBuilder<T> {
    public TimeRangeBuilder<T> startDate(Date startDate);
    public TimeRangeBuilder<T> endDate(Date endDate);
    public T build();
  }

  public Date getStartDate();
  public Date getEndDate();
}

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class VidArchive implements TimeRange<VidArchive, VidArchive.Builder> {
  /** date format used to convert Date objects to human-readable form for the toString() function */
  private static final DateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm:ss");

  private final byte[] bytes;
  private final String cam;
  private final Date startDate;
  private final Date endDate;
  private final String fileName;
  private final String directory;
  private Builder builder;

  @Override
  public Builder Builder() {
    return builder;
  }

  public static class Builder implements TimeRangeBuilder<VidArchive> {
    private byte[] bytes;
    private String cam;
    private Date startDate;
    private Date endDate;
    private String fileName;
    private String directory;
    public Builder() {}
    public Builder bytes(byte[] bytes)          { this.bytes = bytes;           return this;    }
    public Builder cam(String cam)              { this.cam = cam;               return this;    }
    @Override
    public Builder startDate(Date startDate)    { this.startDate = startDate;   return this;    }
    @Override
    public Builder endDate(Date endDate)        { this.endDate = endDate;       return this;    }
    public Builder fileName(String fileName)    { this.fileName = fileName;     return this;    }
    public Builder directory(String directory)  { this.directory = directory;   return this;    }
    @Override
    public VidArchive build()                   { return new VidArchive(this);                  }
  }



  private VidArchive(Builder builder) {
    this.builder = builder;
    bytes = builder.bytes;
    cam = builder.cam;
    startDate = builder.startDate;
    endDate = builder.endDate;
    fileName = builder.fileName;
    directory = builder.directory;
  }

  public byte[] getBytes()        {   return bytes;       }
  public String getCam()          {   return cam;         }
  @Override
  public Date getStartDate()      {   return startDate;   }
  @Override
  public Date getEndDate()        {   return endDate;     }
  public String getFileName()     {   return fileName;    }
  public String getDirectory()    {   return directory;   }

  @Override
  public int compareTo(VidArchive vidArchive) {
    return startDate.compareTo(vidArchive.getStartDate());
  }

  @Override
  public String toString() {
    return DATE_FORMAT.format(startDate) + " - " + DATE_FORMAT.format(endDate);
  }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top