/*
* 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 org.jfin.date.util.ISDADateFormat;
import java.util.List;
import java.util.Calendar;
import java.util.ArrayList;
import java.util.Collections;
import java.util.logging.Logger;
/**
* Class which provides functionality required to 'cut' one schedule
* by another schedule.
*
* This is used, for example, when you have a seperate schedule for the
* accrual periods from the notional, and the notional changes at a different
* frequency, or on different dates, from the accrual periods.
*/
public class ScheduleCutter {
private static Logger logger = Logger.getLogger("org.jfin.date.ScheduleCutter");
private static ScheduleCutterPeriodComparator scheduleCutterPeriodComparator = new ScheduleCutterPeriodComparator();
/**
* Cuts the scheduleToCut using the dates contained within the cutTemplate
*
* @param scheduleToCut The schedule which contains the periods which are going to be cut
* @param cutTemplate The schedule which contains the dates which are used to cut the scheduleToCut
* @return A list of periods from scheduleToCut, cut and cloned to match the cutTemplate
* @throws ScheduleException Throws a schedule exception if there are errors during the cut operation
*/
public List cutSchedules(List scheduleToCut, List extends Period> cutTemplate) throws ScheduleException {
List cutCalendars = new ArrayList();
logger.finer("Creating distinct list of dates in the cut template.");
for(Period cutTemplatePeriod: cutTemplate) {
if(!cutCalendars.contains(cutTemplatePeriod.getStartCalendar())) {
cutCalendars.add(cutTemplatePeriod.getStartCalendar());
}
if(!cutCalendars.contains(cutTemplatePeriod.getEndCalendar())) {
cutCalendars.add(cutTemplatePeriod.getEndCalendar());
}
}
return cutScheduleByDates(scheduleToCut,cutCalendars);
}
public List cutScheduleByDates(List scheduleToCut, List cutDates) throws ScheduleException {
logger.finer("Ensuring that the schedule to cut does not have overlapping periods.");
Collections.sort(scheduleToCut,scheduleCutterPeriodComparator);
for(int i=1;i0) {
throw new ScheduleException("Could not cut schedule with overlapping periods (period "+(i-1)+": "+period1+" and period "+i+": "+period2);
}
}
logger.finer("Cutting schedule");
List resultantSchedule = new ArrayList();
for(T period: scheduleToCut) {
resultantSchedule.addAll(cutPeriodByDates(period,cutDates));
}
return resultantSchedule;
}
/**
* Cuts the period based upon the cutDates and returns a List of the resultant periods or a List containing the original period if it
* wasn't cut.
*
* @param period The period to cut
* @param cutDates The dates with which to perform the cut
* @return The resultant period or periods
*/
public List cutPeriodByDates(T period, List cutDates) {
List resultantSchedule = new ArrayList();
for(Calendar date: cutDates) {
if(periodContainsDate(period,date)) {
logger.finest("Cutting period "+period+" by date "+ ISDADateFormat.format(date));
T cutPeriod1 = (T)period.clone();
T cutPeriod2 = (T)period.clone();
cutPeriod1.setEndCalendar(date);
cutPeriod2.setStartCalendar(date);
resultantSchedule.addAll(cutPeriodByDates(cutPeriod1,cutDates));
resultantSchedule.addAll(cutPeriodByDates(cutPeriod2,cutDates));
return resultantSchedule;
}
}
logger.finest("Period "+period+" not cut by any of the cut dates");
resultantSchedule.add(period);
return resultantSchedule;
}
/**
* Returns true if the date provided is *within* the period; the date given must be between
* the start and end date of the period excluding the start and end date.
*
* @param period The period to check
* @param date The date to check
* @return true if the date is between the start and end date of the period excluding the start and end date, otherwise false
*/
public boolean periodContainsDate(T period, Calendar date) {
return period.getStartCalendar().before(date) && period.getEndCalendar().after(date);
}
}
Ads help maintain this website.