/*********************************************************************************** * * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation. * @author Mustansar@rice.edu * * Licensed under the Educational Community License, Version 1.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ecl1.php * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * **********************************************************************************/ package org.sakaiproject.calendar.impl; import java.util.GregorianCalendar; import java.util.Stack; import java.util.TimeZone; import java.util.Vector; import java.util.List; import org.sakaiproject.time.api.Time; import org.sakaiproject.time.api.TimeRange; import org.sakaiproject.time.cover.TimeService; import org.sakaiproject.time.api.TimeBreakdown; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * <p>MWFRecurrenceRule is a time range generating rule that is based on a weekly recurrence.</p> * <p>repaeting Mondays Wendnesday and Fridays</p> * <p>The recurrences happen on the same day-of-week, at the same time as the prototype.</p> * <p>TODO: support changing the day-of-week of recurrences -Mustansar</p> */ public class MWFRecurrenceRule extends RecurrenceRuleBase { /** The unique type / short frequency description. */ protected final static String FREQ = "MWF"; /** * Construct. */ public MWFRecurrenceRule() { super(); } // MWFRecurrenceRule /** * Construct with no limits. * @param interval Every this many number of weeks: 1 would be weekly. */ public MWFRecurrenceRule(int interval) { super(interval); } //MWFRecurrenceRule /** * Construct with count limit. * @param interval Every this many number of weeks: 1 would be weekly. * @param count For this many occurrences - if 0, does not limit. */ public MWFRecurrenceRule(int interval, int count) { super(interval, count); } // MWFRecurrenceRule /** * Construct with time limit. * @param interval Every this many number of weeks: 1 would be weekly. * @param until No time ranges past this time are generated - if null, does not limit. */ public MWFRecurrenceRule(int interval, Time until) { super(interval, until); } // MWFRecurrenceRule /** * Serialize the resource into XML, adding an element to the doc under the top of the stack element. * @param doc The DOM doc to contain the XML (or null for a string return). * @param stack The DOM elements, the top of which is the containing element of the new "resource" element. * @return The newly added element. */ public Element toXml(Document doc, Stack stack) { // add the "rule" element to the stack'ed element Element rule = doc.createElement("rule"); ((Element)stack.peek()).appendChild(rule); // set the class name - old style for CHEF 1.2.10 compatibility rule.setAttribute("class", "org.chefproject.osid.calendar.MWFRecurrenceRule"); // set the rule class name w/o package, for modern usage rule.setAttribute("name", "MWFRecurrenceRule"); // Do the base class part. setBaseClassXML(rule); return rule; } // toXml /* (non-Javadoc) * @see org.chefproject.service.calendar.RecurrenceRuleBase#getRecurrenceType() */ protected int getRecurrenceType() { return GregorianCalendar.WEEK_OF_MONTH; } /** * {@inheritDoc} */ public String getFrequencyDescription() { return rb.getString("set.MWF"); } /** * {@inheritDoc} */ public String getFrequency() { return FREQ; } /** * Return a List of all RecurrenceInstance objects generated by this rule within the given time range, based on the * prototype first range, in time order. * @param prototype The prototype first TimeRange. * @param range A time range to limit the generated ranges. * @param timeZone The time zone to use for displaying times. * %%% Note: this is currently not implemented, and always uses the "local" zone. * @return a List of RecurrenceInstance generated by this rule in this range. */ public List generateInstances(TimeRange prototype, TimeRange range, TimeZone timeZone) { TimeBreakdown startBreakdown = prototype.firstTime().breakdownLocal(); List rv = new Vector(); GregorianCalendar startCalendarDate = TimeService.getCalendar(TimeService.getLocalTimeZone(),0,0,0,0,0,0,0); startCalendarDate.set( startBreakdown.getYear(), startBreakdown.getMonth() - 1, startBreakdown.getDay(), startBreakdown.getHour(), startBreakdown.getMin(), startBreakdown.getSec()); //may have to move this line ahead GregorianCalendar nextCalendarDate = (GregorianCalendar) startCalendarDate.clone(); if(startCalendarDate.get(GregorianCalendar.DAY_OF_WEEK)%2!=0 ){ if(startCalendarDate.get(GregorianCalendar.DAY_OF_WEEK)==7){ startCalendarDate.add(java.util.Calendar.DAY_OF_MONTH, 2); } else if (startCalendarDate.get(GregorianCalendar.DAY_OF_WEEK)==6) { startCalendarDate.add(java.util.Calendar.DAY_OF_MONTH, 3); } else { startCalendarDate.add(java.util.Calendar.DAY_OF_MONTH, 1); } } nextCalendarDate = (GregorianCalendar) startCalendarDate.clone(); int currentCount = 1; int hitCount=1; //counts tth/mwf occurences when getCount()>0 do { Time nextTime = TimeService.newTime(nextCalendarDate); // is this past count? if ((getCount() > 0) && (hitCount > getCount())) break; // is this past until? if ((getUntil() != null) && isAfter(nextTime, getUntil()) ) break; TimeRange nextTimeRange = TimeService.newTimeRange(nextTime.getTime(), prototype.duration()); // Is this out of the range? if (isOverlap(range, nextTimeRange)) { TimeRange eventTimeRange = null; // Single time cases require special handling. if ( prototype.isSingleTime() ) { eventTimeRange = TimeService.newTimeRange(nextTimeRange.firstTime()); } else { eventTimeRange = TimeService.newTimeRange(nextTimeRange.firstTime(), nextTimeRange.lastTime(), true, false); } // use this one String eventHR=eventTimeRange.toStringHR(); rv.add(new RecurrenceInstance(eventTimeRange, currentCount)); } // if next starts after the range, stop generating I have added an extra condition here to test TTH/MWF Number of times repetition else if (isAfter(nextTime, range.lastTime()) ){ break; } do{ nextCalendarDate = (GregorianCalendar) startCalendarDate.clone(); nextCalendarDate.add(java.util.Calendar.DAY_OF_MONTH, currentCount);//"1" is the recurrence type but here thing are confusing if((getInterval()>1&&(nextCalendarDate.get(GregorianCalendar.DAY_OF_WEEK)==7))){ nextCalendarDate.add(java.util.Calendar.DAY_OF_MONTH, ((getInterval()-1)*7)+currentCount);//"1"is the supposed recuurence Type currentCount+=((getInterval()-1)*7)+1; } else { nextCalendarDate.add(java.util.Calendar.DAY_OF_MONTH, 1); currentCount++; } } while((nextCalendarDate.get(GregorianCalendar.DAY_OF_WEEK)%2!=0)); hitCount++; } while (true); return rv; } } // MWFRecurrenceRule