/*
 * 

jFin, open source derivatives trade processing

* *

Copyright (C) 2005, 2006, 2007 Morgan Brown Consultancy Ltd.

* *

This file is part of jFin.

* *

jFin is free software; you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version.

* *

jFin is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public * License for more details.

* *

You should have received a copy of the GNU General Public License along * with jFin; if not, write to the Free Software Foundation, Inc., 51 Franklin * St, Fifth Floor, Boston, MA 02110-1301 USA.

*/ package org.jfin.date; import java.util.List; import java.util.Calendar; import java.util.ArrayList; import java.text.ParseException; /** * */ public class TypedScheduleGenerator { private T prototype; private int maxPeriods = -1; public TypedScheduleGenerator(T prototype) { this.prototype = prototype; } public TypedScheduleGenerator(T prototype, int maxPeriods) { this.prototype = prototype; this.maxPeriods = maxPeriods; } public T getPrototype() { return prototype; } public void setPrototype(T prototype) { this.prototype = prototype; } public int getMaxPeriods() { return maxPeriods; } public void setMaxPeriods(int maxPeriods) { this.maxPeriods = maxPeriods; } public List generateSchedule(Calendar startDate, String maturityString, Frequency frequency, StubType stubType) throws ScheduleException, ParseException { Tenor tenor = new Tenor(maturityString); return generateSchedule(startDate, tenor, frequency,stubType); } public List generateSchedule(Calendar startDate, Tenor tenor, Frequency frequency, StubType stubType) throws ScheduleException { Calendar endDate = copyAndReset(startDate); endDate.add(tenor.getCalendarUnit(),tenor.getAmount()); return generateSchedule(startDate, endDate, frequency.getPeriodAmount(),frequency.getPeriodUnit(),stubType); } public List generateSchedule(Calendar startDate, Calendar endDate, Frequency frequency, StubType stubType) throws ScheduleException { return generateSchedule(startDate, endDate, frequency.getPeriodAmount(),frequency.getPeriodUnit(),stubType); } public List generateSchedule(Calendar startDate, Calendar endDate, int frequencyAmount, int frequencyUnit, StubType stubType) throws ScheduleException { switch(stubType) { case LONG_FIRST: return generateScheduleInternal(endDate,startDate,-1*frequencyAmount,frequencyUnit,stubType); case LONG_LAST: return generateScheduleInternal(startDate,endDate,frequencyAmount,frequencyUnit,stubType); case SHORT_FIRST: return generateScheduleInternal(endDate,startDate,-1*frequencyAmount,frequencyUnit,stubType); case SHORT_LAST: return generateScheduleInternal(startDate,endDate,frequencyAmount,frequencyUnit,stubType); default: return generateScheduleInternal(startDate,endDate,frequencyAmount,frequencyUnit,stubType); } } private List generateScheduleInternal(Calendar startDate, Calendar endDate, int frequencyAmount, int frequencyUnit, StubType stubType) throws ScheduleException { startDate = copyAndReset(startDate); endDate = copyAndReset(endDate); Calendar holdDate = copyAndReset(startDate); List schedule = new ArrayList(); int periodCount=1; boolean finished = false; boolean forwards = frequencyAmount>0; while(!finished) { Calendar nextDate1 = copyAndReset(startDate); nextDate1.add(frequencyUnit,periodCount*frequencyAmount); if(stubType.isShortStub()) { if(isBeyond(nextDate1,endDate,forwards) || isEqual(nextDate1,endDate)) { T period = createPeriod(holdDate,endDate,holdDate,nextDate1,forwards); addPeriodToSchedule(schedule,period,forwards); finished = true; } else { T period = createPeriod(holdDate,nextDate1,holdDate,nextDate1,forwards); addPeriodToSchedule(schedule,period,forwards); } } else if(stubType.isLongStub()) { Calendar nextDate2 = copyAndReset(startDate); nextDate2.add(frequencyUnit,(periodCount+1) * frequencyAmount); if(isBeyond(nextDate2,endDate,forwards)) { T period = createPeriod(holdDate,endDate,nextDate1,nextDate2,forwards); addPeriodToSchedule(schedule,period,forwards); finished = true; } else { T period = createPeriod(holdDate,nextDate1,holdDate,nextDate1,forwards); addPeriodToSchedule(schedule,period,forwards); } } else { if(isBeyond(nextDate1,endDate,forwards)) { throw new ScheduleException("StubType.NONE used when periods do not fit start and end date"); } else { T period = createPeriod(holdDate,nextDate1,holdDate,nextDate1,forwards); addPeriodToSchedule(schedule,period,forwards); if(isEqual(nextDate1,endDate)) { finished = true; } } } holdDate = copyAndReset(nextDate1); periodCount++; if(maxPeriods>0 && periodCount>maxPeriods) { throw new ScheduleException("Maximum number of periods ("+maxPeriods+") exceeded."); } } return schedule; } private T createPeriod(Calendar startDate, Calendar endDate, Calendar referenceStartDate, Calendar referenceEndDate, boolean forwards) throws ScheduleException { T period = createPeriod(); if(forwards) { period.setStartCalendar(startDate); period.setEndCalendar(endDate); period.setReferenceStartCalendar(referenceStartDate); period.setReferenceEndCalendar(referenceEndDate); } else { period.setStartCalendar(endDate); period.setEndCalendar(startDate); period.setReferenceStartCalendar(referenceEndDate); period.setReferenceEndCalendar(referenceStartDate); } if(period instanceof Initialisable) { Initialisable initialisablePeriod = (Initialisable)period; initialisablePeriod.initialise(); } return period; } private void addPeriodToSchedule(List schedule, T period, boolean forwards) { if(forwards) { schedule.add(period); } else { schedule.add(0,period); } } private T createPeriod() throws ScheduleException { if(prototype==null) { throw new ScheduleException("TypedScheduleGenerator requires a non null prototype to function."); } else { return (T)prototype.clone(); } } private boolean isEqual(Calendar date1, Calendar date2) { return !(date1.after(date2) || date1.before(date2)); } private boolean isBeyond(Calendar date1, Calendar date2, boolean forwards) { if(forwards) { return date1.after(date2); } else { return date2.after(date1); } } /** * Copy a calendar and reset it's time to midnight to avoid * problems relating to generating schedules around midnight. * @param calendar The calendar to copy and reset * @return Calendar the calendar which has been copied and reset */ public static Calendar copyAndReset(Calendar calendar) { Calendar copy = (Calendar)calendar.clone(); copy.set(Calendar.HOUR_OF_DAY,0); copy.set(Calendar.MINUTE,0); copy.set(Calendar.SECOND,0); copy.set(Calendar.MILLISECOND,0); return copy; } }

Ads help maintain this website.