001    package org.hackystat.utilities.time.interval;
002    
003    import java.util.Iterator;
004    
005    import javax.xml.datatype.XMLGregorianCalendar;
006    
007    import org.hackystat.utilities.time.period.Month;
008    
009    /**
010     * Provides month interval type.
011     * 
012     * @author Hongbing Kou, Philip Johnson
013     */
014    public class MonthInterval extends Interval implements Iterable<Month> {
015      /** Start month. */
016      private final Month startMonth;
017      /** End month. */
018      private final Month endMonth;
019      
020      /**
021       * Creates a MonthInterval object with start month and end month.
022       * 
023       * @param startYear Start year.  
024       * @param startMonth Start month.
025       * @param endYear End year.
026       * @param endMonth End month.
027       * 
028       * @throws IllegalIntervalException If try to create an interval with invalid period.
029       */
030      public MonthInterval(String startYear, String startMonth, String endYear, String endMonth) 
031         throws IllegalIntervalException {
032        super("Month");    
033        int year = Integer.parseInt(startYear);
034        int month = Integer.parseInt(startMonth);
035        this.startMonth = new Month(year, month);
036        
037        year = Integer.parseInt(endYear);
038        month = Integer.parseInt(endMonth);    
039        this.endMonth = new Month(year, month);   
040        
041        if (this.startMonth.compareTo(this.endMonth) > 0) {
042          throw new IllegalIntervalException("Start month " + this.startMonth 
043                                           + "  is later than end month " + this.endMonth);
044        }
045      }
046      
047      /**
048       * Creates a MonthInterval object with start month and end month.
049       * 
050       * @param startMonth Start month.
051       * @param endMonth End month.
052       * 
053       * @throws IllegalIntervalException If try to create an interval with invalid period.
054       */
055      public MonthInterval(XMLGregorianCalendar startMonth, XMLGregorianCalendar endMonth) 
056         throws IllegalIntervalException {
057        super("Month");    
058        this.startMonth = new Month(startMonth);
059        this.endMonth = new Month(endMonth);   
060        
061        if (this.startMonth.compareTo(this.endMonth) > 0) {
062          throw new IllegalIntervalException("Start month " + this.startMonth 
063                                           + "  is later than end month " + this.endMonth);
064        }
065      }
066      
067      /**
068       * Gets start month.
069       * 
070       * @return Start month.
071       */
072      public Month getStartMonth() {
073        return this.startMonth;
074      }
075    
076      /**
077       * Gets the end month.
078       * 
079       * @return End month.
080       */
081      public Month getEndMonth() {
082        return this.endMonth;
083      }
084    
085      
086      /**
087       * String representation of the MonthInterval object.
088       * 
089       * @return Month interval string  
090       */
091      @Override
092      public String toString() {
093        StringBuffer buffer = new StringBuffer(30);
094        buffer.append("Month Interval : ");
095        buffer.append(this.startMonth);
096        buffer.append(" ~ ");
097        buffer.append(this.endMonth);
098        
099        return buffer.toString();
100      }  
101      
102      /**
103       * Gets the iterator over the month interval.
104       * 
105       * @return Iterator over month. 
106       */
107      @Override
108      public Iterator<Month> iterator() {
109        return new MonthIterator(this);
110      }  
111      
112      /**
113       * Gets the hash code.
114       * 
115       * @return The hash code.
116       */
117      @Override
118      public int hashCode() {
119        return this.startMonth.hashCode() / 2 + this.endMonth.hashCode() / 2;
120      }
121      
122      /**
123       * Indicates whether some other object is "equal to" this one. 
124       * 
125       * @param obj Another instance of <code>DayInterval</code>.
126       * 
127       * @return True if they are equal, false otherwise.
128       */
129      @Override
130      public boolean equals(Object obj) {
131        if (!(obj instanceof MonthInterval)) {
132          return false;
133        }    
134        MonthInterval another = (MonthInterval) obj;
135        return this.startMonth.equals(another.startMonth) && this.endMonth.equals(another.endMonth);
136      }  
137    }