001    package org.hackystat.utilities.time.period;
002    
003    import java.text.SimpleDateFormat;
004    import java.util.ArrayList;
005    import java.util.Calendar;
006    import java.util.Date;
007    import java.util.List;
008    import java.util.Locale;
009    
010    import javax.xml.datatype.XMLGregorianCalendar;
011    
012    /**
013     * Provides a representation for seven Day instances where the first Day 
014     * is always a Sunday and the last Day is always the following Saturday. 
015     * <p>
016     * The Calendar is forced to Locale.US to ensure constant week boundaries. 
017     *
018     * @author Hongbing Kou
019     */
020    public class Week implements TimePeriod {
021      /** First day of the week. */
022      private Day firstDay;
023      /** Last day of the week. */
024      private Day lastDay;
025      /** A list of days in this week. */
026      private List<Day> days;
027       
028      /**
029       * Create a Week instance that starts on Sunday and ends on Saturday and that includes today.
030       */
031      public Week() {
032        this(Day.getInstance(new Date()));
033      }
034      
035      /**
036       * Create a Week instance that includes the passed date.
037       * @param date The date to be included in the constructed Week.
038       */
039      public Week (Date date) {
040        this(Day.getInstance(date));
041      }
042      
043      /**
044       * Creates a Week instance that starts on Sunday and ends on Saturday and that includes the
045       * passed day.
046       * @param day A day that identifies the Week to be returned.
047       */
048      public Week(Day day) {
049        Calendar cal = Calendar.getInstance(Locale.US);
050        cal.setTime(day.getDate());
051        cal.set(Calendar.DAY_OF_WEEK, 1);
052        
053        this.firstDay = Day.getInstance(cal.getTime());
054        cal.set(Calendar.DAY_OF_WEEK, 7);
055        this.lastDay = Day.getInstance(cal.getTime());
056        
057        // Create days' list.
058        this.days = new ArrayList<Day>();
059        for (Day weekDay = this.firstDay; weekDay.compareTo(this.lastDay) <= 0; 
060                                          weekDay = weekDay.inc(1)) {
061          this.days.add(weekDay);
062        }
063      }
064      
065      /**
066       * Creates a week instance starting on Sunday and ending on Saturday that includes the passed
067       * Day.
068       * @param xmlDay The day.
069       */
070      public Week(XMLGregorianCalendar xmlDay) {
071        this(Day.getInstance(xmlDay));
072      }
073    
074      /**
075       * Gets first day of this Week, always a Sunday.
076       * 
077       * @return First day of the week.
078       */
079      public Day getFirstDay() {
080        return this.firstDay;
081      }
082      
083      /**
084       * Gets the last day of this Week, always a Saturday.
085       * 
086       * @return Last day of the week.
087       */
088      public Day getLastDay() {
089        return this.lastDay;
090      }
091    
092      /**
093       * Returns a list with the seven Day instances in this Week.
094       * 
095       * @return A list of the Days in this Week.
096       */
097      public List<Day> getDays() {
098        return this.days;  
099      }
100      
101      /**
102       * Calculate the hashcode for this Week.
103       * 
104       * @return This Week's hashcode.
105       */
106      @Override
107      public int hashCode() {
108        return this.firstDay.hashCode();  
109      }
110      
111      /**
112       * Returns true if the passed object is a Week and is equal to this Week.
113       * 
114       * @param obj Any object.
115       * @return True if the two Week instances are the same.
116       */
117      @Override
118      public boolean equals(Object obj) {
119        return ((obj instanceof Week) &&
120                (this.firstDay.equals(((Week) obj).firstDay)));
121      }
122    
123      /**
124       * Returns a String representation of this Week.
125       * 
126       * @return First day of the week.
127       */
128      public String getWeekRepresentation() {    
129        SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
130        return formatter.format(this.firstDay.getDate()) + " to " + 
131               formatter.format(this.lastDay.getDate());
132      }
133      
134      /**
135       * First day of the week is chosen to represent the week in toString().
136       * 
137       * @return Week string.
138       */
139      @Override
140      public String toString() {    
141        return (new SimpleDateFormat("dd-MMM-yyyy", Locale.US)).format(this.lastDay.getDate());
142      }
143      
144      /**
145       * Returns a new Week instance representing the previous Week.
146       * 
147       * @return The previous Week.
148       */
149      public Week dec() {
150        return new Week(this.firstDay.inc(-7));
151      }
152      
153      /**
154       * Returns a new Week instance representing the next Week.
155       * 
156       * @return The next Week.
157       */
158      public Week inc() {
159        return new Week(this.lastDay.inc(7));
160      }
161      
162      /**
163       * Compares two Week objects.
164       * 
165       * @param obj Another week object.
166       * @return Comparison of the first day.
167       */
168      public int compareTo(Object obj) {
169        if (!(obj instanceof Week)) {
170          return -1;
171        }
172        return this.firstDay.compareTo(((Week) obj).firstDay);
173      }
174    }