/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.basics.schedule;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
import org.joda.beans.Bean;
import org.joda.beans.BeanDefinition;
import org.joda.beans.ImmutableBean;
import org.joda.beans.ImmutableValidator;
import org.joda.beans.JodaBeanUtils;
import org.joda.beans.MetaProperty;
import org.joda.beans.Property;
import org.joda.beans.PropertyDefinition;
import org.joda.beans.impl.direct.DirectFieldsBeanBuilder;
import org.joda.beans.impl.direct.DirectMetaBean;
import org.joda.beans.impl.direct.DirectMetaProperty;
import org.joda.beans.impl.direct.DirectMetaPropertyMap;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.opengamma.basics.date.BusinessDayAdjustment;
import com.opengamma.collect.ArgChecker;
/**
* Definition of a periodic schedule.
* <p>
* A periodic schedule is determined using a "periodic frequency".
* This splits the schedule into "regular" periods of a fixed length, such as every 3 months.
* Any remaining days are allocated to irregular "stubs" at the start and/or end.
* <p>
* For example, a 24 month (2 year) swap might be divided into 3 month periods.
* The 24 month period is the overall schedule and the 3 month period is the periodic frequency.
* <p>
* Note that a 23 month swap cannot be split into even 3 month periods.
* Instead, there will be a 2 month "initial" stub at the start, a 2 month "final" stub at the end
* or both an initial and final stub with a combined length of 2 months.
*
* <h4>Example</h4>
* <p>
* This example creates a schedule for a 13 month swap cannot be split into 3 month periods
* with a long initial stub rolling at end-of-month:
* <pre>
* // example swap using builder
* BusinessDayAdjustment businessDayAdj =
* BusinessDayAdjustment.of(BusinessDayConventions.MODIFIED_FOLLOWING, GlobalHolidayCalendars.EUTA);
* PeriodicSchedule definition = PeriodicSchedule.builder()
* .startDate(LocalDate.of(2014, 2, 12))
* .endDate(LocalDate.of(2015, 3, 31))
* .businessDayAdjustment(businessDayAdj)
* .frequency(Frequency.P3M)
* .stubConvention(StubConvention.LONG_INITIAL)
* .rollConvention(RollConventions.EOM)
* .build();
* Schedule schedule = definition.createSchedule();
*
* // result
* period 1: 2014-02-12 to 2014-06-30
* period 2: 2014-06-30 to 2014-09-30
* period 3: 2014-09-30 to 2014-12-31
* period 4: 2014-12-31 to 2015-03-31
* </pre>
*
* <h4>Details about stubs and date rolling</h4>
* <p>
* The stubs are specified using a combination of the {@link StubConvention}, {@link RollConvention} and dates.
* <p>
* The explicit stub dates are checked first. An explicit stub occurs if 'firstRegularStartDate' or
* 'lastRegularEndDate' is present and they differ from 'startDate' and 'endDate'.
* <p>
* If explicit stub dates are specified then they are used to lock the initial or final stub.
* If the stub convention is present, it is matched and validated against the locked stub.
* For example, if an initial stub is specified by dates and the stub convention is 'ShortInitial'
* or 'LongInitial' then the convention is considered to be matched, thus the periodic frequency is
* applied using the implicit stub convention 'None'.
* If the stub convention does not match the dates, then an exception will be thrown during schedule creation.
* If the stub convention is not present, then the periodic frequency is applied
* using the implicit stub convention 'None'.
* <p>
* If explicit stub dates are not specified then the stub convention is used.
* The convention selects whether to use the start date or the end date as the beginning of the schedule calculation.
* The beginning of the calculation must match the roll convention, unless the convention is 'EOM',
* in which case 'EOM' is only applied if the calculation starts at the end of the month.
* <p>
* In all cases, the roll convention is used to fine-tune the dates.
* If not present or 'None', the convention is effectively implied from the first date of the calculation.
* All calculated dates will match the roll convention.
* If this is not possible due to the dates specified then an exception will be thrown during schedule creation.
* <p>
* The schedule operates primarily on "unadjusted" dates.
* An unadjusted date can be any day, including non-business days.
* When the unadjusted schedule has been determined, the appropriate business day adjustment
* is applied to create a parallel schedule of "adjusted" dates.
*/
@BeanDefinition
public final class PeriodicSchedule
implements ImmutableBean, Serializable {
/**
* The start date, which is the start of the first schedule period.
* <p>
* This is the start date of the schedule.
* It is is unadjusted and as such might be a weekend or holiday.
* Any applicable business day adjustment will be applied when creating the schedule.
* This is also known as the unadjusted effective date.
* <p>
* In most cases, the start date of a financial instrument is just after the trade date,
* such as two business days later. However, the start date of a schedule is permitted
* to be any date, which includes dates before or after the trade date.
*/
@PropertyDefinition(validate = "notNull")
private final LocalDate startDate;
/**
* The end date, which is the end of the last schedule period.
* <p>
* This is the end date of the schedule.
* It is is unadjusted and as such might be a weekend or holiday.
* Any applicable business day adjustment will be applied when creating the schedule.
* This is also known as the unadjusted maturity date or unadjusted termination date.
* This date must be after the start date.
*/
@PropertyDefinition(validate = "notNull")
private final LocalDate endDate;
/**
* The regular periodic frequency to use.
* <p>
* Most dates are calculated using a regular periodic frequency, such as every 3 months.
* The actual day-of-month or day-of-week is selected using the roll and stub conventions.
*/
@PropertyDefinition(validate = "notNull")
private final Frequency frequency;
/**
* The business day adjustment to apply.
* <p>
* Each date in the calculated schedule is determined without taking into account weekends and holidays.
* The adjustment specified here is used to convert those dates to valid business days.
* <p>
* The start date and end date may have their own business day adjustment rules.
* If those are not present, then this adjustment is used instead.
*/
@PropertyDefinition(validate = "notNull")
private final BusinessDayAdjustment businessDayAdjustment;
/**
* The optional business day adjustment to apply to the start date.
* <p>
* The start date property is an unadjusted date and as such might be a weekend or holiday.
* The adjustment specified here is used to convert the start date to a valid business day.
* <p>
* If this property is not present, the standard {@code businessDayAdjustment} property is used instead.
*/
@PropertyDefinition(get = "optional")
private final BusinessDayAdjustment startDateBusinessDayAdjustment;
/**
* The optional business day adjustment to apply to the end date.
* <p>
* The end date property is an unadjusted date and as such might be a weekend or holiday.
* The adjustment specified here is used to convert the end date to a valid business day.
* <p>
* If this property is not present, the standard {@code businessDayAdjustment} property is used instead.
*/
@PropertyDefinition(get = "optional")
private final BusinessDayAdjustment endDateBusinessDayAdjustment;
/**
* The optional convention defining how to handle stubs.
* <p>
* The stub convention is used during schedule construction to determine whether the irregular
* remaining period occurs at the start or end of the schedule.
* It also determines whether the irregular period is shorter or longer than the regular period.
* <p>
* The convention 'None' may be used to explicitly indicate there are no stubs.
* This will be validated during schedule construction.
* <p>
* The convention 'Both' may be used to explicitly indicate there is both an initial and final stub.
* The stubs themselves must be specified using explicit dates.
* This will be validated during schedule construction.
* <p>
* If the stub convention is not present, then the convention will be implied from the actual
* explicit dates that have been specified.
* <p>
* If both a stub convention and explicit dates are specified, then the combination will be
* validated during schedule construction. For example, the combination of an explicit dated
* initial stub and a stub convention of 'ShortInitial' or 'LongInitial' is valid, but other
* stub conventions, such as 'ShortFinal' or 'None' would be invalid.
*/
@PropertyDefinition(get = "optional")
private final StubConvention stubConvention;
/**
* The optional convention defining how to roll dates.
* <p>
* The schedule periods are determined at the high level by repeatedly adding
* the frequency to the start date, or subtracting it from the end date.
* The roll convention provides the detailed rule to adjust the day-of-month or day-of-week.
* <p>
* During schedule generation, if this is present it will be used to determine the schedule.
* If not present, then the roll convention will be implied.
*/
@PropertyDefinition(get = "optional")
private final RollConvention rollConvention;
/**
* The optional start date of the first regular schedule period, which is the end date of the initial stub.
* <p>
* This is used to identify the boundary date between the initial stub and the first regular schedule period.
* <p>
* This is an unadjusted date, and as such it might not be a valid business day.
* This date must be on or after 'startDate'.
* <p>
* During schedule generation, if this is present it will be used to determine the schedule.
* If not present, then the overall schedule start date will be used instead, resulting in no initial stub.
*/
@PropertyDefinition(get = "optional")
private final LocalDate firstRegularStartDate;
/**
* The optional end date of the last regular schedule period, which is the start date of the final stub.
* <p>
* This is used to identify the boundary date between the last regular schedule period and the final stub.
* <p>
* This is an unadjusted date, and as such it might not be a valid business day.
* This date must be after 'startDate' and after 'firstRegularStartDate'.
* This date must be on or before 'endDate'.
* <p>
* During schedule generation, if this is present it will be used to determine the schedule.
* If not present, then the overall schedule end date will be used instead, resulting in no final stub.
*/
@PropertyDefinition(get = "optional")
private final LocalDate lastRegularEndDate;
//-------------------------------------------------------------------------
/**
* Obtains an instance based on a stub convention and end-of-month flag.
* <p>
* The business day adjustment is used for all dates.
* The stub convention is used to determine whether there are any stubs.
* If the end-of-month flag is true, then in any case of ambiguity the
* end-of-month will be chosen.
*
* @param unadjustedStartDate start date, which is the start of the first schedule period
* @param unadjustedEndDate the end date, which is the end of the last schedule period
* @param frequency the regular periodic frequency
* @param businessDayAdjustment the business day adjustment to apply
* @param stubConvention the non-null convention defining how to handle stubs
* @param preferEndOfMonth whether to prefer the end-of-month when rolling
* @return the definition
*/
public static PeriodicSchedule of(
LocalDate unadjustedStartDate,
LocalDate unadjustedEndDate,
Frequency frequency,
BusinessDayAdjustment businessDayAdjustment,
StubConvention stubConvention,
boolean preferEndOfMonth) {
ArgChecker.notNull(unadjustedStartDate, "unadjustedStartDate");
ArgChecker.notNull(unadjustedEndDate, "unadjustedEndDate");
ArgChecker.notNull(frequency, "frequency");
ArgChecker.notNull(businessDayAdjustment, "businessDayAdjustment");
ArgChecker.notNull(stubConvention, "stubConvention");
return PeriodicSchedule.builder()
.startDate(unadjustedStartDate)
.endDate(unadjustedEndDate)
.frequency(frequency)
.businessDayAdjustment(businessDayAdjustment)
.stubConvention(stubConvention)
.rollConvention(preferEndOfMonth ? RollConventions.EOM : null)
.build();
}
/**
* Obtains an instance based on roll and stub conventions.
* <p>
* The business day adjustment is used for all dates.
* The stub convention is used to determine whether there are any stubs.
* The roll convention is used to fine tune each rolled date.
*
* @param unadjustedStartDate start date, which is the start of the first schedule period
* @param unadjustedEndDate the end date, which is the end of the last schedule period
* @param frequency the regular periodic frequency
* @param businessDayAdjustment the business day adjustment to apply
* @param stubConvention the non-null convention defining how to handle stubs
* @param rollConvention the non-null convention defining how to roll dates
* @return the definition
*/
public static PeriodicSchedule of(
LocalDate unadjustedStartDate,
LocalDate unadjustedEndDate,
Frequency frequency,
BusinessDayAdjustment businessDayAdjustment,
StubConvention stubConvention,
RollConvention rollConvention) {
ArgChecker.notNull(unadjustedStartDate, "unadjustedStartDate");
ArgChecker.notNull(unadjustedEndDate, "unadjustedEndDate");
ArgChecker.notNull(frequency, "frequency");
ArgChecker.notNull(businessDayAdjustment, "businessDayAdjustment");
ArgChecker.notNull(stubConvention, "stubConvention");
ArgChecker.notNull(rollConvention, "rollConvention");
return PeriodicSchedule.builder()
.startDate(unadjustedStartDate)
.endDate(unadjustedEndDate)
.frequency(frequency)
.businessDayAdjustment(businessDayAdjustment)
.stubConvention(stubConvention)
.rollConvention(rollConvention)
.build();
}
//-------------------------------------------------------------------------
@ImmutableValidator
private void validate() {
ArgChecker.inOrderNotEqual(
startDate, endDate, "startDate", "endDate");
if (firstRegularStartDate != null) {
ArgChecker.inOrderOrEqual(
startDate, firstRegularStartDate, "unadjusted", "firstRegularStartDate");
if (lastRegularEndDate != null) {
ArgChecker.inOrderNotEqual(
firstRegularStartDate, lastRegularEndDate, "firstRegularStartDate", "lastRegularEndDate");
}
}
if (lastRegularEndDate != null) {
ArgChecker.inOrderOrEqual(
lastRegularEndDate, endDate, "lastRegularEndDate", "endDate");
}
}
//-------------------------------------------------------------------------
/**
* Creates the schedule from the definition.
* <p>
* The schedule consists of an optional initial stub, a number of regular periods
* and an optional final stub.
* <p>
* The roll convention, stub convention and additional dates are all used to determine the schedule.
* If the roll convention is not present it will be defaulted from the stub convention, with 'None' as the default.
* If there are explicit stub dates then they will be used.
* If the stub convention is present, then it will be validated against the stub dates.
* If the stub convention and stub dates are not present, then no stubs are allowed.
*
* @return the schedule
* @throws ScheduleException if the definition is invalid
*/
public Schedule createSchedule() {
List<LocalDate> unadj = generateUnadjustedDates();
List<LocalDate> adj = applyBusinessDayAdjustment(unadj);
RollConvention rollConv = getEffectiveRollConvention();
List<SchedulePeriod> periods = new ArrayList<>();
try {
// for performance, handle silly errors using exceptions
for (int i = 0; i < unadj.size() - 1; i++) {
periods.add(SchedulePeriod.of(adj.get(i), adj.get(i + 1), unadj.get(i), unadj.get(i + 1)));
}
} catch (IllegalArgumentException ex) {
// check dates to throw a better exception for duplicate dates in schedule
createUnadjustedDates();
createAdjustedDates();
// unknown exception
ScheduleException se = new ScheduleException(this, "Schedule calculation resulted in invalid period");
se.initCause(ex);
throw se;
}
return Schedule.builder()
.periods(periods)
.frequency(frequency)
.rollConvention(rollConv)
.build();
}
//-------------------------------------------------------------------------
/**
* Creates the list of unadjusted dates in the schedule.
* <p>
* The unadjusted date list will contain at least two elements, the start date and end date.
* Between those dates will be the calculated periodic schedule.
* <p>
* The roll convention, stub convention and additional dates are all used to determine the schedule.
* If the roll convention is not present it will be defaulted from the stub convention, with 'None' as the default.
* If there are explicit stub dates then they will be used.
* If the stub convention is present, then it will be validated against the stub dates.
* If the stub convention and stub dates are not present, then no stubs are allowed.
* If the frequency is 'Term' explicit stub dates are disallowed, and the roll and stub convention are ignored.
*
* @return the schedule of unadjusted dates
* @throws ScheduleException if the definition is invalid
*/
public ImmutableList<LocalDate> createUnadjustedDates() {
List<LocalDate> unadj = generateUnadjustedDates();
// ensure schedule is valid with no duplicated dates
ImmutableList<LocalDate> deduplicated = ImmutableSet.copyOf(unadj).asList();
if (deduplicated.size() < unadj.size()) {
throw new ScheduleException(this, "Schedule calculation resulted in duplicate unadjusted dates: {}", unadj);
}
return deduplicated;
}
// creates the unadjusted dates, returning the mutable list
private List<LocalDate> generateUnadjustedDates() {
LocalDate regStart = getEffectiveFirstRegularStartDate();
LocalDate regEnd = getEffectiveLastRegularEndDate();
boolean explicitInitialStub = !startDate.equals(regStart);
boolean explicitFinalStub = !endDate.equals(regEnd);
// handle TERM frequency
if (frequency == Frequency.TERM) {
if (explicitInitialStub || explicitFinalStub) {
throw new ScheduleException(this, "Explict stubs must not be specified when using 'Term' frequency");
}
return ImmutableList.of(startDate, endDate);
}
// calculate base schedule excluding explicit stubs
RollConvention rollConv = getEffectiveRollConvention();
StubConvention implicitStubConv = generateImplicitStubConvention(explicitInitialStub, explicitFinalStub);
List<LocalDate> unadj = (implicitStubConv.isCalculateBackwards() ?
generateBackwards(regStart, regEnd, rollConv, implicitStubConv) :
generateForwards(regStart, regEnd, rollConv, implicitStubConv));
// add explicit stubs
if (explicitInitialStub) {
unadj.add(0, startDate);
}
if (explicitFinalStub) {
unadj.add(endDate);
}
return unadj;
}
// using knowledge of the explicit stubs, generate the correct convention for implicit stubs
private StubConvention generateImplicitStubConvention(boolean explicitInitialStub, boolean explicitFinalStub) {
// null is not same as NONE
// NONE validates that there are no explicit stubs
// null ensures that remainder after explicit stubs are removed has no stubs
if (stubConvention != null) {
return stubConvention.toImplicit(this, explicitInitialStub, explicitFinalStub);
}
return StubConvention.NONE;
}
// generate the schedule of dates backwards from the end
private List<LocalDate> generateBackwards(LocalDate start, LocalDate end, RollConvention rollConv, StubConvention stubConv) {
// validate
if (rollConv.matches(end) == false) {
throw new ScheduleException(
this, "Date '{}' does not match roll convention '{}' when starting to roll backwards", end, rollConv);
}
// generate
List<LocalDate> dates = new ArrayList<>();
dates.add(start);
dates.add(end);
LocalDate temp = rollConv.previous(end, frequency);
while (temp.isAfter(start)) {
dates.add(1, temp);
temp = rollConv.previous(temp, frequency);
}
// convert short stub to long stub, but only if we actually have a stub
boolean stub = temp.equals(start) == false;
if (stub && stubConv.isLong() && dates.size() > 2) {
dates.remove(1);
}
return dates;
}
// generate the schedule of dates forwards from the start
private List<LocalDate> generateForwards(LocalDate start, LocalDate end, RollConvention rollConv, StubConvention stubConv) {
// validate
if (rollConv.matches(start) == false) {
throw new ScheduleException(
this, "Date '{}' does not match roll convention '{}' when starting to roll forwards", start, rollConv);
}
// generate
List<LocalDate> dates = new ArrayList<>();
dates.add(start);
LocalDate temp = rollConv.next(start, frequency);
while (temp.isBefore(end)) {
dates.add(temp);
temp = rollConv.next(temp, frequency);
}
dates.add(end);
// convert short stub to long stub, but only if we actually have a stub
boolean stub = temp.equals(end) == false;
if (stub && dates.size() > 2) {
if (stubConv == StubConvention.NONE) {
throw new ScheduleException(
this, "Period '{}' to '{}' resulted in a disallowed stub with frequency '{}'", start, end, frequency);
}
if (stubConv.isLong()) {
dates.remove(dates.size() - 2);
}
}
return dates;
}
//-------------------------------------------------------------------------
/**
* Creates the list of adjusted dates in the schedule.
* <p>
* The adjusted date list will contain at least two elements, the start date and end date.
* Between those dates will be the calculated periodic schedule.
* Each date will be a valid business day as per the appropriate business day adjustment.
* <p>
* The roll convention, stub convention and additional dates are all used to determine the schedule.
* If the roll convention is not present it will be defaulted from the stub convention, with 'None' as the default.
* If there are explicit stub dates then they will be used.
* If the stub convention is present, then it will be validated against the stub dates.
* If the stub convention and stub dates are not present, then no stubs are allowed.
*
* @return the schedule of dates adjusted to valid business days
* @throws ScheduleException if the definition is invalid
*/
public ImmutableList<LocalDate> createAdjustedDates() {
List<LocalDate> adj = applyBusinessDayAdjustment(generateUnadjustedDates());
// ensure schedule is valid with no duplicated dates
ImmutableList<LocalDate> deduplicated = ImmutableSet.copyOf(adj).asList();
if (deduplicated.size() < adj.size()) {
throw new ScheduleException(this, "Schedule calculation resulted in duplicate adjusted dates: {}", adj);
}
return deduplicated;
}
// applies the appropriate business day adjustment to each date
private List<LocalDate> applyBusinessDayAdjustment(List<LocalDate> unadj) {
List<LocalDate> adj = new ArrayList<>(unadj.size());
adj.add(MoreObjects.firstNonNull(startDateBusinessDayAdjustment, businessDayAdjustment).adjust(startDate));
for (int i = 1; i < unadj.size() - 1; i++) {
adj.add(businessDayAdjustment.adjust(unadj.get(i)));
}
adj.add(MoreObjects.firstNonNull(endDateBusinessDayAdjustment, businessDayAdjustment).adjust(endDate));
return adj;
}
//-------------------------------------------------------------------------
/**
* Gets the effective roll convention defining how to roll dates.
* <p>
* The schedule periods are determined at the high level by repeatedly adding
* the frequency to the start date, or subtracting it from the end date.
* The roll convention provides the detailed rule to adjust the day-of-month or day-of-week.
* <p>
* The effective roll convention is a non-null value.
* If the roll convention property is not present, this is determined from the
* stub convention, dates and frequency, defaulting to 'None' if necessary.
*
* @return the non-null roll convention
*/
public RollConvention getEffectiveRollConvention() {
// determine roll convention from stub convention, using EOM as a flag
if (stubConvention != null) {
// special handling for EOM as it is advisory rather than mandatory
if (rollConvention == RollConventions.EOM) {
RollConvention derived = stubConvention.toRollConvention(
getEffectiveFirstRegularStartDate(), getEffectiveLastRegularEndDate(), frequency, true);
return (derived == RollConventions.NONE ? RollConventions.EOM : derived);
}
// avoid RollConventions.NONE if possible
if (rollConvention == null || rollConvention == RollConventions.NONE) {
return stubConvention.toRollConvention(
getEffectiveFirstRegularStartDate(), getEffectiveLastRegularEndDate(), frequency, false);
}
}
// avoid RollConventions.NONE if possible
if (rollConvention == null || rollConvention == RollConventions.NONE) {
return StubConvention.NONE.toRollConvention(
getEffectiveFirstRegularStartDate(), getEffectiveLastRegularEndDate(), frequency, false);
}
// use RollConventions.NONE if nothing else applies
return MoreObjects.firstNonNull(rollConvention, RollConventions.NONE);
}
/**
* Gets the effective first regular start date.
* <p>
* This will be either 'firstRegularStartDate' or 'startDate.unadjusted'.
*
* @return the non-null start date of the first regular period
*/
public LocalDate getEffectiveFirstRegularStartDate() {
return MoreObjects.firstNonNull(firstRegularStartDate, startDate);
}
/**
* Gets the effective last regular end date.
* <p>
* This will be either 'lastRegularEndDate' or 'endDate.unadjusted'.
*
* @return the non-null end date of the last regular period
*/
public LocalDate getEffectiveLastRegularEndDate() {
return MoreObjects.firstNonNull(lastRegularEndDate, endDate);
}
/**
* Gets the effective business day adjustment to apply to the start date.
* <p>
* This will be either 'startDateBusinessDayAdjustment' or 'businessDayAdjustment'.
*
* @return the non-null business day adjustment to apply to the start date
*/
public BusinessDayAdjustment getEffectiveStartDateBusinessDayAdjustment() {
return MoreObjects.firstNonNull(startDateBusinessDayAdjustment, businessDayAdjustment);
}
/**
* Gets the effective business day adjustment to apply to the end date.
* <p>
* This will be either 'endDateBusinessDayAdjustment' or 'businessDayAdjustment'.
*
* @return the non-null business day adjustment to apply to the end date
*/
public BusinessDayAdjustment getEffectiveEndDateBusinessDayAdjustment() {
return MoreObjects.firstNonNull(endDateBusinessDayAdjustment, businessDayAdjustment);
}
//-------------------------------------------------------------------------
/**
* Gets the start date, adjusted to be a valid business day.
* <p>
* This applies the business day rules from {@link #getEffectiveStartDateBusinessDayAdjustment()}
* to the start date.
*
* @return the start date, adjusted to a valid business day
*/
public LocalDate getAdjustedStartDate() {
return getEffectiveStartDateBusinessDayAdjustment().adjust(startDate);
}
/**
* Gets the end date, adjusted to be a valid business day.
* <p>
* This applies the business day rules from {@link #getEffectiveEndDateBusinessDayAdjustment()}
* to the end date.
*
* @return the end date, adjusted to a valid business day
*/
public LocalDate getAdjustedEndDate() {
return getEffectiveEndDateBusinessDayAdjustment().adjust(endDate);
}
//------------------------- AUTOGENERATED START -------------------------
///CLOVER:OFF
/**
* The meta-bean for {@code PeriodicSchedule}.
* @return the meta-bean, not null
*/
public static PeriodicSchedule.Meta meta() {
return PeriodicSchedule.Meta.INSTANCE;
}
static {
JodaBeanUtils.registerMetaBean(PeriodicSchedule.Meta.INSTANCE);
}
/**
* The serialization version id.
*/
private static final long serialVersionUID = 1L;
/**
* Returns a builder used to create an instance of the bean.
* @return the builder, not null
*/
public static PeriodicSchedule.Builder builder() {
return new PeriodicSchedule.Builder();
}
private PeriodicSchedule(
LocalDate startDate,
LocalDate endDate,
Frequency frequency,
BusinessDayAdjustment businessDayAdjustment,
BusinessDayAdjustment startDateBusinessDayAdjustment,
BusinessDayAdjustment endDateBusinessDayAdjustment,
StubConvention stubConvention,
RollConvention rollConvention,
LocalDate firstRegularStartDate,
LocalDate lastRegularEndDate) {
JodaBeanUtils.notNull(startDate, "startDate");
JodaBeanUtils.notNull(endDate, "endDate");
JodaBeanUtils.notNull(frequency, "frequency");
JodaBeanUtils.notNull(businessDayAdjustment, "businessDayAdjustment");
this.startDate = startDate;
this.endDate = endDate;
this.frequency = frequency;
this.businessDayAdjustment = businessDayAdjustment;
this.startDateBusinessDayAdjustment = startDateBusinessDayAdjustment;
this.endDateBusinessDayAdjustment = endDateBusinessDayAdjustment;
this.stubConvention = stubConvention;
this.rollConvention = rollConvention;
this.firstRegularStartDate = firstRegularStartDate;
this.lastRegularEndDate = lastRegularEndDate;
validate();
}
@Override
public PeriodicSchedule.Meta metaBean() {
return PeriodicSchedule.Meta.INSTANCE;
}
@Override
public <R> Property<R> property(String propertyName) {
return metaBean().<R>metaProperty(propertyName).createProperty(this);
}
@Override
public Set<String> propertyNames() {
return metaBean().metaPropertyMap().keySet();
}
//-----------------------------------------------------------------------
/**
* Gets the start date, which is the start of the first schedule period.
* <p>
* This is the start date of the schedule.
* It is is unadjusted and as such might be a weekend or holiday.
* Any applicable business day adjustment will be applied when creating the schedule.
* This is also known as the unadjusted effective date.
* <p>
* In most cases, the start date of a financial instrument is just after the trade date,
* such as two business days later. However, the start date of a schedule is permitted
* to be any date, which includes dates before or after the trade date.
* @return the value of the property, not null
*/
public LocalDate getStartDate() {
return startDate;
}
//-----------------------------------------------------------------------
/**
* Gets the end date, which is the end of the last schedule period.
* <p>
* This is the end date of the schedule.
* It is is unadjusted and as such might be a weekend or holiday.
* Any applicable business day adjustment will be applied when creating the schedule.
* This is also known as the unadjusted maturity date or unadjusted termination date.
* This date must be after the start date.
* @return the value of the property, not null
*/
public LocalDate getEndDate() {
return endDate;
}
//-----------------------------------------------------------------------
/**
* Gets the regular periodic frequency to use.
* <p>
* Most dates are calculated using a regular periodic frequency, such as every 3 months.
* The actual day-of-month or day-of-week is selected using the roll and stub conventions.
* @return the value of the property, not null
*/
public Frequency getFrequency() {
return frequency;
}
//-----------------------------------------------------------------------
/**
* Gets the business day adjustment to apply.
* <p>
* Each date in the calculated schedule is determined without taking into account weekends and holidays.
* The adjustment specified here is used to convert those dates to valid business days.
* <p>
* The start date and end date may have their own business day adjustment rules.
* If those are not present, then this adjustment is used instead.
* @return the value of the property, not null
*/
public BusinessDayAdjustment getBusinessDayAdjustment() {
return businessDayAdjustment;
}
//-----------------------------------------------------------------------
/**
* Gets the optional business day adjustment to apply to the start date.
* <p>
* The start date property is an unadjusted date and as such might be a weekend or holiday.
* The adjustment specified here is used to convert the start date to a valid business day.
* <p>
* If this property is not present, the standard {@code businessDayAdjustment} property is used instead.
* @return the optional value of the property, not null
*/
public Optional<BusinessDayAdjustment> getStartDateBusinessDayAdjustment() {
return Optional.ofNullable(startDateBusinessDayAdjustment);
}
//-----------------------------------------------------------------------
/**
* Gets the optional business day adjustment to apply to the end date.
* <p>
* The end date property is an unadjusted date and as such might be a weekend or holiday.
* The adjustment specified here is used to convert the end date to a valid business day.
* <p>
* If this property is not present, the standard {@code businessDayAdjustment} property is used instead.
* @return the optional value of the property, not null
*/
public Optional<BusinessDayAdjustment> getEndDateBusinessDayAdjustment() {
return Optional.ofNullable(endDateBusinessDayAdjustment);
}
//-----------------------------------------------------------------------
/**
* Gets the optional convention defining how to handle stubs.
* <p>
* The stub convention is used during schedule construction to determine whether the irregular
* remaining period occurs at the start or end of the schedule.
* It also determines whether the irregular period is shorter or longer than the regular period.
* <p>
* The convention 'None' may be used to explicitly indicate there are no stubs.
* This will be validated during schedule construction.
* <p>
* The convention 'Both' may be used to explicitly indicate there is both an initial and final stub.
* The stubs themselves must be specified using explicit dates.
* This will be validated during schedule construction.
* <p>
* If the stub convention is not present, then the convention will be implied from the actual
* explicit dates that have been specified.
* <p>
* If both a stub convention and explicit dates are specified, then the combination will be
* validated during schedule construction. For example, the combination of an explicit dated
* initial stub and a stub convention of 'ShortInitial' or 'LongInitial' is valid, but other
* stub conventions, such as 'ShortFinal' or 'None' would be invalid.
* @return the optional value of the property, not null
*/
public Optional<StubConvention> getStubConvention() {
return Optional.ofNullable(stubConvention);
}
//-----------------------------------------------------------------------
/**
* Gets the optional convention defining how to roll dates.
* <p>
* The schedule periods are determined at the high level by repeatedly adding
* the frequency to the start date, or subtracting it from the end date.
* The roll convention provides the detailed rule to adjust the day-of-month or day-of-week.
* <p>
* During schedule generation, if this is present it will be used to determine the schedule.
* If not present, then the roll convention will be implied.
* @return the optional value of the property, not null
*/
public Optional<RollConvention> getRollConvention() {
return Optional.ofNullable(rollConvention);
}
//-----------------------------------------------------------------------
/**
* Gets the optional start date of the first regular schedule period, which is the end date of the initial stub.
* <p>
* This is used to identify the boundary date between the initial stub and the first regular schedule period.
* <p>
* This is an unadjusted date, and as such it might not be a valid business day.
* This date must be on or after 'startDate'.
* <p>
* During schedule generation, if this is present it will be used to determine the schedule.
* If not present, then the overall schedule start date will be used instead, resulting in no initial stub.
* @return the optional value of the property, not null
*/
public Optional<LocalDate> getFirstRegularStartDate() {
return Optional.ofNullable(firstRegularStartDate);
}
//-----------------------------------------------------------------------
/**
* Gets the optional end date of the last regular schedule period, which is the start date of the final stub.
* <p>
* This is used to identify the boundary date between the last regular schedule period and the final stub.
* <p>
* This is an unadjusted date, and as such it might not be a valid business day.
* This date must be after 'startDate' and after 'firstRegularStartDate'.
* This date must be on or before 'endDate'.
* <p>
* During schedule generation, if this is present it will be used to determine the schedule.
* If not present, then the overall schedule end date will be used instead, resulting in no final stub.
* @return the optional value of the property, not null
*/
public Optional<LocalDate> getLastRegularEndDate() {
return Optional.ofNullable(lastRegularEndDate);
}
//-----------------------------------------------------------------------
/**
* Returns a builder that allows this bean to be mutated.
* @return the mutable builder, not null
*/
public Builder toBuilder() {
return new Builder(this);
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj != null && obj.getClass() == this.getClass()) {
PeriodicSchedule other = (PeriodicSchedule) obj;
return JodaBeanUtils.equal(getStartDate(), other.getStartDate()) &&
JodaBeanUtils.equal(getEndDate(), other.getEndDate()) &&
JodaBeanUtils.equal(getFrequency(), other.getFrequency()) &&
JodaBeanUtils.equal(getBusinessDayAdjustment(), other.getBusinessDayAdjustment()) &&
JodaBeanUtils.equal(startDateBusinessDayAdjustment, other.startDateBusinessDayAdjustment) &&
JodaBeanUtils.equal(endDateBusinessDayAdjustment, other.endDateBusinessDayAdjustment) &&
JodaBeanUtils.equal(stubConvention, other.stubConvention) &&
JodaBeanUtils.equal(rollConvention, other.rollConvention) &&
JodaBeanUtils.equal(firstRegularStartDate, other.firstRegularStartDate) &&
JodaBeanUtils.equal(lastRegularEndDate, other.lastRegularEndDate);
}
return false;
}
@Override
public int hashCode() {
int hash = getClass().hashCode();
hash = hash * 31 + JodaBeanUtils.hashCode(getStartDate());
hash = hash * 31 + JodaBeanUtils.hashCode(getEndDate());
hash = hash * 31 + JodaBeanUtils.hashCode(getFrequency());
hash = hash * 31 + JodaBeanUtils.hashCode(getBusinessDayAdjustment());
hash = hash * 31 + JodaBeanUtils.hashCode(startDateBusinessDayAdjustment);
hash = hash * 31 + JodaBeanUtils.hashCode(endDateBusinessDayAdjustment);
hash = hash * 31 + JodaBeanUtils.hashCode(stubConvention);
hash = hash * 31 + JodaBeanUtils.hashCode(rollConvention);
hash = hash * 31 + JodaBeanUtils.hashCode(firstRegularStartDate);
hash = hash * 31 + JodaBeanUtils.hashCode(lastRegularEndDate);
return hash;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder(352);
buf.append("PeriodicSchedule{");
buf.append("startDate").append('=').append(getStartDate()).append(',').append(' ');
buf.append("endDate").append('=').append(getEndDate()).append(',').append(' ');
buf.append("frequency").append('=').append(getFrequency()).append(',').append(' ');
buf.append("businessDayAdjustment").append('=').append(getBusinessDayAdjustment()).append(',').append(' ');
buf.append("startDateBusinessDayAdjustment").append('=').append(startDateBusinessDayAdjustment).append(',').append(' ');
buf.append("endDateBusinessDayAdjustment").append('=').append(endDateBusinessDayAdjustment).append(',').append(' ');
buf.append("stubConvention").append('=').append(stubConvention).append(',').append(' ');
buf.append("rollConvention").append('=').append(rollConvention).append(',').append(' ');
buf.append("firstRegularStartDate").append('=').append(firstRegularStartDate).append(',').append(' ');
buf.append("lastRegularEndDate").append('=').append(JodaBeanUtils.toString(lastRegularEndDate));
buf.append('}');
return buf.toString();
}
//-----------------------------------------------------------------------
/**
* The meta-bean for {@code PeriodicSchedule}.
*/
public static final class Meta extends DirectMetaBean {
/**
* The singleton instance of the meta-bean.
*/
static final Meta INSTANCE = new Meta();
/**
* The meta-property for the {@code startDate} property.
*/
private final MetaProperty<LocalDate> startDate = DirectMetaProperty.ofImmutable(
this, "startDate", PeriodicSchedule.class, LocalDate.class);
/**
* The meta-property for the {@code endDate} property.
*/
private final MetaProperty<LocalDate> endDate = DirectMetaProperty.ofImmutable(
this, "endDate", PeriodicSchedule.class, LocalDate.class);
/**
* The meta-property for the {@code frequency} property.
*/
private final MetaProperty<Frequency> frequency = DirectMetaProperty.ofImmutable(
this, "frequency", PeriodicSchedule.class, Frequency.class);
/**
* The meta-property for the {@code businessDayAdjustment} property.
*/
private final MetaProperty<BusinessDayAdjustment> businessDayAdjustment = DirectMetaProperty.ofImmutable(
this, "businessDayAdjustment", PeriodicSchedule.class, BusinessDayAdjustment.class);
/**
* The meta-property for the {@code startDateBusinessDayAdjustment} property.
*/
private final MetaProperty<BusinessDayAdjustment> startDateBusinessDayAdjustment = DirectMetaProperty.ofImmutable(
this, "startDateBusinessDayAdjustment", PeriodicSchedule.class, BusinessDayAdjustment.class);
/**
* The meta-property for the {@code endDateBusinessDayAdjustment} property.
*/
private final MetaProperty<BusinessDayAdjustment> endDateBusinessDayAdjustment = DirectMetaProperty.ofImmutable(
this, "endDateBusinessDayAdjustment", PeriodicSchedule.class, BusinessDayAdjustment.class);
/**
* The meta-property for the {@code stubConvention} property.
*/
private final MetaProperty<StubConvention> stubConvention = DirectMetaProperty.ofImmutable(
this, "stubConvention", PeriodicSchedule.class, StubConvention.class);
/**
* The meta-property for the {@code rollConvention} property.
*/
private final MetaProperty<RollConvention> rollConvention = DirectMetaProperty.ofImmutable(
this, "rollConvention", PeriodicSchedule.class, RollConvention.class);
/**
* The meta-property for the {@code firstRegularStartDate} property.
*/
private final MetaProperty<LocalDate> firstRegularStartDate = DirectMetaProperty.ofImmutable(
this, "firstRegularStartDate", PeriodicSchedule.class, LocalDate.class);
/**
* The meta-property for the {@code lastRegularEndDate} property.
*/
private final MetaProperty<LocalDate> lastRegularEndDate = DirectMetaProperty.ofImmutable(
this, "lastRegularEndDate", PeriodicSchedule.class, LocalDate.class);
/**
* The meta-properties.
*/
private final Map<String, MetaProperty<?>> metaPropertyMap$ = new DirectMetaPropertyMap(
this, null,
"startDate",
"endDate",
"frequency",
"businessDayAdjustment",
"startDateBusinessDayAdjustment",
"endDateBusinessDayAdjustment",
"stubConvention",
"rollConvention",
"firstRegularStartDate",
"lastRegularEndDate");
/**
* Restricted constructor.
*/
private Meta() {
}
@Override
protected MetaProperty<?> metaPropertyGet(String propertyName) {
switch (propertyName.hashCode()) {
case -2129778896: // startDate
return startDate;
case -1607727319: // endDate
return endDate;
case -70023844: // frequency
return frequency;
case -1065319863: // businessDayAdjustment
return businessDayAdjustment;
case 429197561: // startDateBusinessDayAdjustment
return startDateBusinessDayAdjustment;
case -734327136: // endDateBusinessDayAdjustment
return endDateBusinessDayAdjustment;
case -31408449: // stubConvention
return stubConvention;
case -10223666: // rollConvention
return rollConvention;
case 2011803076: // firstRegularStartDate
return firstRegularStartDate;
case -1540679645: // lastRegularEndDate
return lastRegularEndDate;
}
return super.metaPropertyGet(propertyName);
}
@Override
public PeriodicSchedule.Builder builder() {
return new PeriodicSchedule.Builder();
}
@Override
public Class<? extends PeriodicSchedule> beanType() {
return PeriodicSchedule.class;
}
@Override
public Map<String, MetaProperty<?>> metaPropertyMap() {
return metaPropertyMap$;
}
//-----------------------------------------------------------------------
/**
* The meta-property for the {@code startDate} property.
* @return the meta-property, not null
*/
public MetaProperty<LocalDate> startDate() {
return startDate;
}
/**
* The meta-property for the {@code endDate} property.
* @return the meta-property, not null
*/
public MetaProperty<LocalDate> endDate() {
return endDate;
}
/**
* The meta-property for the {@code frequency} property.
* @return the meta-property, not null
*/
public MetaProperty<Frequency> frequency() {
return frequency;
}
/**
* The meta-property for the {@code businessDayAdjustment} property.
* @return the meta-property, not null
*/
public MetaProperty<BusinessDayAdjustment> businessDayAdjustment() {
return businessDayAdjustment;
}
/**
* The meta-property for the {@code startDateBusinessDayAdjustment} property.
* @return the meta-property, not null
*/
public MetaProperty<BusinessDayAdjustment> startDateBusinessDayAdjustment() {
return startDateBusinessDayAdjustment;
}
/**
* The meta-property for the {@code endDateBusinessDayAdjustment} property.
* @return the meta-property, not null
*/
public MetaProperty<BusinessDayAdjustment> endDateBusinessDayAdjustment() {
return endDateBusinessDayAdjustment;
}
/**
* The meta-property for the {@code stubConvention} property.
* @return the meta-property, not null
*/
public MetaProperty<StubConvention> stubConvention() {
return stubConvention;
}
/**
* The meta-property for the {@code rollConvention} property.
* @return the meta-property, not null
*/
public MetaProperty<RollConvention> rollConvention() {
return rollConvention;
}
/**
* The meta-property for the {@code firstRegularStartDate} property.
* @return the meta-property, not null
*/
public MetaProperty<LocalDate> firstRegularStartDate() {
return firstRegularStartDate;
}
/**
* The meta-property for the {@code lastRegularEndDate} property.
* @return the meta-property, not null
*/
public MetaProperty<LocalDate> lastRegularEndDate() {
return lastRegularEndDate;
}
//-----------------------------------------------------------------------
@Override
protected Object propertyGet(Bean bean, String propertyName, boolean quiet) {
switch (propertyName.hashCode()) {
case -2129778896: // startDate
return ((PeriodicSchedule) bean).getStartDate();
case -1607727319: // endDate
return ((PeriodicSchedule) bean).getEndDate();
case -70023844: // frequency
return ((PeriodicSchedule) bean).getFrequency();
case -1065319863: // businessDayAdjustment
return ((PeriodicSchedule) bean).getBusinessDayAdjustment();
case 429197561: // startDateBusinessDayAdjustment
return ((PeriodicSchedule) bean).startDateBusinessDayAdjustment;
case -734327136: // endDateBusinessDayAdjustment
return ((PeriodicSchedule) bean).endDateBusinessDayAdjustment;
case -31408449: // stubConvention
return ((PeriodicSchedule) bean).stubConvention;
case -10223666: // rollConvention
return ((PeriodicSchedule) bean).rollConvention;
case 2011803076: // firstRegularStartDate
return ((PeriodicSchedule) bean).firstRegularStartDate;
case -1540679645: // lastRegularEndDate
return ((PeriodicSchedule) bean).lastRegularEndDate;
}
return super.propertyGet(bean, propertyName, quiet);
}
@Override
protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) {
metaProperty(propertyName);
if (quiet) {
return;
}
throw new UnsupportedOperationException("Property cannot be written: " + propertyName);
}
}
//-----------------------------------------------------------------------
/**
* The bean-builder for {@code PeriodicSchedule}.
*/
public static final class Builder extends DirectFieldsBeanBuilder<PeriodicSchedule> {
private LocalDate startDate;
private LocalDate endDate;
private Frequency frequency;
private BusinessDayAdjustment businessDayAdjustment;
private BusinessDayAdjustment startDateBusinessDayAdjustment;
private BusinessDayAdjustment endDateBusinessDayAdjustment;
private StubConvention stubConvention;
private RollConvention rollConvention;
private LocalDate firstRegularStartDate;
private LocalDate lastRegularEndDate;
/**
* Restricted constructor.
*/
private Builder() {
}
/**
* Restricted copy constructor.
* @param beanToCopy the bean to copy from, not null
*/
private Builder(PeriodicSchedule beanToCopy) {
this.startDate = beanToCopy.getStartDate();
this.endDate = beanToCopy.getEndDate();
this.frequency = beanToCopy.getFrequency();
this.businessDayAdjustment = beanToCopy.getBusinessDayAdjustment();
this.startDateBusinessDayAdjustment = beanToCopy.startDateBusinessDayAdjustment;
this.endDateBusinessDayAdjustment = beanToCopy.endDateBusinessDayAdjustment;
this.stubConvention = beanToCopy.stubConvention;
this.rollConvention = beanToCopy.rollConvention;
this.firstRegularStartDate = beanToCopy.firstRegularStartDate;
this.lastRegularEndDate = beanToCopy.lastRegularEndDate;
}
//-----------------------------------------------------------------------
@Override
public Object get(String propertyName) {
switch (propertyName.hashCode()) {
case -2129778896: // startDate
return startDate;
case -1607727319: // endDate
return endDate;
case -70023844: // frequency
return frequency;
case -1065319863: // businessDayAdjustment
return businessDayAdjustment;
case 429197561: // startDateBusinessDayAdjustment
return startDateBusinessDayAdjustment;
case -734327136: // endDateBusinessDayAdjustment
return endDateBusinessDayAdjustment;
case -31408449: // stubConvention
return stubConvention;
case -10223666: // rollConvention
return rollConvention;
case 2011803076: // firstRegularStartDate
return firstRegularStartDate;
case -1540679645: // lastRegularEndDate
return lastRegularEndDate;
default:
throw new NoSuchElementException("Unknown property: " + propertyName);
}
}
@Override
public Builder set(String propertyName, Object newValue) {
switch (propertyName.hashCode()) {
case -2129778896: // startDate
this.startDate = (LocalDate) newValue;
break;
case -1607727319: // endDate
this.endDate = (LocalDate) newValue;
break;
case -70023844: // frequency
this.frequency = (Frequency) newValue;
break;
case -1065319863: // businessDayAdjustment
this.businessDayAdjustment = (BusinessDayAdjustment) newValue;
break;
case 429197561: // startDateBusinessDayAdjustment
this.startDateBusinessDayAdjustment = (BusinessDayAdjustment) newValue;
break;
case -734327136: // endDateBusinessDayAdjustment
this.endDateBusinessDayAdjustment = (BusinessDayAdjustment) newValue;
break;
case -31408449: // stubConvention
this.stubConvention = (StubConvention) newValue;
break;
case -10223666: // rollConvention
this.rollConvention = (RollConvention) newValue;
break;
case 2011803076: // firstRegularStartDate
this.firstRegularStartDate = (LocalDate) newValue;
break;
case -1540679645: // lastRegularEndDate
this.lastRegularEndDate = (LocalDate) newValue;
break;
default:
throw new NoSuchElementException("Unknown property: " + propertyName);
}
return this;
}
@Override
public Builder set(MetaProperty<?> property, Object value) {
super.set(property, value);
return this;
}
@Override
public Builder setString(String propertyName, String value) {
setString(meta().metaProperty(propertyName), value);
return this;
}
@Override
public Builder setString(MetaProperty<?> property, String value) {
super.setString(property, value);
return this;
}
@Override
public Builder setAll(Map<String, ? extends Object> propertyValueMap) {
super.setAll(propertyValueMap);
return this;
}
@Override
public PeriodicSchedule build() {
return new PeriodicSchedule(
startDate,
endDate,
frequency,
businessDayAdjustment,
startDateBusinessDayAdjustment,
endDateBusinessDayAdjustment,
stubConvention,
rollConvention,
firstRegularStartDate,
lastRegularEndDate);
}
//-----------------------------------------------------------------------
/**
* Sets the {@code startDate} property in the builder.
* @param startDate the new value, not null
* @return this, for chaining, not null
*/
public Builder startDate(LocalDate startDate) {
JodaBeanUtils.notNull(startDate, "startDate");
this.startDate = startDate;
return this;
}
/**
* Sets the {@code endDate} property in the builder.
* @param endDate the new value, not null
* @return this, for chaining, not null
*/
public Builder endDate(LocalDate endDate) {
JodaBeanUtils.notNull(endDate, "endDate");
this.endDate = endDate;
return this;
}
/**
* Sets the {@code frequency} property in the builder.
* @param frequency the new value, not null
* @return this, for chaining, not null
*/
public Builder frequency(Frequency frequency) {
JodaBeanUtils.notNull(frequency, "frequency");
this.frequency = frequency;
return this;
}
/**
* Sets the {@code businessDayAdjustment} property in the builder.
* @param businessDayAdjustment the new value, not null
* @return this, for chaining, not null
*/
public Builder businessDayAdjustment(BusinessDayAdjustment businessDayAdjustment) {
JodaBeanUtils.notNull(businessDayAdjustment, "businessDayAdjustment");
this.businessDayAdjustment = businessDayAdjustment;
return this;
}
/**
* Sets the {@code startDateBusinessDayAdjustment} property in the builder.
* @param startDateBusinessDayAdjustment the new value
* @return this, for chaining, not null
*/
public Builder startDateBusinessDayAdjustment(BusinessDayAdjustment startDateBusinessDayAdjustment) {
this.startDateBusinessDayAdjustment = startDateBusinessDayAdjustment;
return this;
}
/**
* Sets the {@code endDateBusinessDayAdjustment} property in the builder.
* @param endDateBusinessDayAdjustment the new value
* @return this, for chaining, not null
*/
public Builder endDateBusinessDayAdjustment(BusinessDayAdjustment endDateBusinessDayAdjustment) {
this.endDateBusinessDayAdjustment = endDateBusinessDayAdjustment;
return this;
}
/**
* Sets the {@code stubConvention} property in the builder.
* @param stubConvention the new value
* @return this, for chaining, not null
*/
public Builder stubConvention(StubConvention stubConvention) {
this.stubConvention = stubConvention;
return this;
}
/**
* Sets the {@code rollConvention} property in the builder.
* @param rollConvention the new value
* @return this, for chaining, not null
*/
public Builder rollConvention(RollConvention rollConvention) {
this.rollConvention = rollConvention;
return this;
}
/**
* Sets the {@code firstRegularStartDate} property in the builder.
* @param firstRegularStartDate the new value
* @return this, for chaining, not null
*/
public Builder firstRegularStartDate(LocalDate firstRegularStartDate) {
this.firstRegularStartDate = firstRegularStartDate;
return this;
}
/**
* Sets the {@code lastRegularEndDate} property in the builder.
* @param lastRegularEndDate the new value
* @return this, for chaining, not null
*/
public Builder lastRegularEndDate(LocalDate lastRegularEndDate) {
this.lastRegularEndDate = lastRegularEndDate;
return this;
}
//-----------------------------------------------------------------------
@Override
public String toString() {
StringBuilder buf = new StringBuilder(352);
buf.append("PeriodicSchedule.Builder{");
buf.append("startDate").append('=').append(JodaBeanUtils.toString(startDate)).append(',').append(' ');
buf.append("endDate").append('=').append(JodaBeanUtils.toString(endDate)).append(',').append(' ');
buf.append("frequency").append('=').append(JodaBeanUtils.toString(frequency)).append(',').append(' ');
buf.append("businessDayAdjustment").append('=').append(JodaBeanUtils.toString(businessDayAdjustment)).append(',').append(' ');
buf.append("startDateBusinessDayAdjustment").append('=').append(JodaBeanUtils.toString(startDateBusinessDayAdjustment)).append(',').append(' ');
buf.append("endDateBusinessDayAdjustment").append('=').append(JodaBeanUtils.toString(endDateBusinessDayAdjustment)).append(',').append(' ');
buf.append("stubConvention").append('=').append(JodaBeanUtils.toString(stubConvention)).append(',').append(' ');
buf.append("rollConvention").append('=').append(JodaBeanUtils.toString(rollConvention)).append(',').append(' ');
buf.append("firstRegularStartDate").append('=').append(JodaBeanUtils.toString(firstRegularStartDate)).append(',').append(' ');
buf.append("lastRegularEndDate").append('=').append(JodaBeanUtils.toString(lastRegularEndDate));
buf.append('}');
return buf.toString();
}
}
///CLOVER:ON
//-------------------------- AUTOGENERATED END --------------------------
}