/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.convention.frequency; import java.io.Serializable; import java.util.Locale; import java.util.Map; import org.joda.convert.FromString; import org.threeten.bp.Period; import com.google.common.collect.ImmutableMap; import com.opengamma.util.ArgumentChecker; /** * Frequency convention implementation using {@code Period}. */ public final class PeriodFrequency implements Frequency, Serializable { /** Serialization version. */ private static final long serialVersionUID = 1L; /** * A frequency with a period of one year. */ public static final PeriodFrequency ANNUAL = new PeriodFrequency(ANNUAL_NAME, Period.ofYears(1)); /** * A frequency with a period of six months. */ public static final PeriodFrequency SEMI_ANNUAL = new PeriodFrequency(SEMI_ANNUAL_NAME, Period.ofMonths(6)); /** * A frequency with a period of three months. */ public static final PeriodFrequency QUARTERLY = new PeriodFrequency(QUARTERLY_NAME, Period.ofMonths(3)); /** * A frequency with a period of two months. */ public static final PeriodFrequency BIMONTHLY = new PeriodFrequency(BIMONTHLY_NAME, Period.ofMonths(2)); /** * A frequency with a period of one month. */ public static final PeriodFrequency MONTHLY = new PeriodFrequency(MONTHLY_NAME, Period.ofMonths(1)); /** * A frequency with a period of twenty eight days. */ public static final PeriodFrequency TWENTY_EIGHT_DAYS = new PeriodFrequency(TWENTY_EIGHT_DAYS_NAME, Period.ofDays(28)); /** * A frequency with a period of two weeks. */ public static final PeriodFrequency THREE_WEEKS = new PeriodFrequency(THREE_WEEK_NAME, Period.ofDays(21)); /** * A frequency with a period of two weeks. */ public static final PeriodFrequency BIWEEKLY = new PeriodFrequency(BIWEEKLY_NAME, Period.ofDays(14)); /** * A frequency with a period of one week. */ public static final PeriodFrequency WEEKLY = new PeriodFrequency(WEEKLY_NAME, Period.ofDays(7)); /** * A frequency with a period of one day. */ public static final PeriodFrequency DAILY = new PeriodFrequency(DAILY_NAME, Period.ofDays(1)); /** * A continuous frequency, with a period of zero. */ public static final PeriodFrequency CONTINUOUS = new PeriodFrequency(CONTINUOUS_NAME, Period.ZERO); /** * A frequency with a period of four months */ public static final PeriodFrequency FOUR_MONTHS = new PeriodFrequency(FOUR_MONTH_NAME, Period.ofMonths(4)); /** * A frequency with a period of five months */ public static final PeriodFrequency FIVE_MONTHS = new PeriodFrequency(FIVE_MONTH_NAME, Period.ofMonths(5)); /** * A frequency with a period of seven months */ public static final PeriodFrequency SEVEN_MONTHS = new PeriodFrequency(SEVEN_MONTH_NAME, Period.ofMonths(7)); /** * A frequency with a period of eight months */ public static final PeriodFrequency EIGHT_MONTHS = new PeriodFrequency(EIGHT_MONTH_NAME, Period.ofMonths(8)); /** * A frequency with a period of nine months */ public static final PeriodFrequency NINE_MONTHS = new PeriodFrequency(NINE_MONTH_NAME, Period.ofMonths(9)); /** * A frequency with a period of ten months */ public static final PeriodFrequency TEN_MONTHS = new PeriodFrequency(TEN_MONTH_NAME, Period.ofMonths(10)); /** * A frequency with a period of eleven months */ public static final PeriodFrequency ELEVEN_MONTHS = new PeriodFrequency(ELEVEN_MONTH_NAME, Period.ofMonths(11)); /** * A frequency with a period of eighteen months */ public static final PeriodFrequency EIGHTEEN_MONTHS = new PeriodFrequency(EIGHTEEN_MONTH_NAME, Period.ofMonths(18)); /** * A frequency with a period of never */ public static final PeriodFrequency NEVER = new PeriodFrequency(NEVER_NAME, Period.ZERO); /** A map containing all of the frequency */ public static final Map<PeriodFrequency, PeriodFrequency> s_cache = ImmutableMap.<PeriodFrequency, PeriodFrequency>builder() .put(ANNUAL, ANNUAL) .put(SEMI_ANNUAL, SEMI_ANNUAL) .put(QUARTERLY, QUARTERLY) .put(BIMONTHLY, BIMONTHLY) .put(MONTHLY, MONTHLY) .put(BIWEEKLY, BIWEEKLY) .put(WEEKLY, WEEKLY) .put(DAILY, DAILY) .put(CONTINUOUS, CONTINUOUS) .put(FOUR_MONTHS, FOUR_MONTHS) .put(FIVE_MONTHS, FIVE_MONTHS) .put(SEVEN_MONTHS, SEVEN_MONTHS) .put(EIGHT_MONTHS, EIGHT_MONTHS) .put(NINE_MONTHS, NINE_MONTHS) .put(TEN_MONTHS, TEN_MONTHS) .put(ELEVEN_MONTHS, ELEVEN_MONTHS) .put(EIGHTEEN_MONTHS, EIGHTEEN_MONTHS) .build(); /** * The name of the convention. */ private final String _name; /** * The length of the period. */ private final Period _period; /** * Gets a frequency from a string. * <p> * This parses the known {@code PeriodFrequency} instances by name. * Name matching is case insensitive. * * @param name the name of the convention, not null * @return the period frequency matching the name, not null * @throws IllegalArgumentException if the name is unknown */ @FromString public static PeriodFrequency of(final String name) { String nameLower = name.toLowerCase(Locale.ENGLISH); for (PeriodFrequency freq : s_cache.keySet()) { if (freq.getName().toLowerCase(Locale.ENGLISH).equals(nameLower)) { return freq; } } throw new IllegalArgumentException("Unknown PeriodFrequency: " + name); } /** * Obtains an instance. * * @param name the name of the convention, not null * @param period length of the period, not null * @return a period frequency, not null */ public static PeriodFrequency of(final String name, final Period period) { final PeriodFrequency temp = new PeriodFrequency(name, period); if (s_cache.containsKey(temp)) { return s_cache.get(temp); } return temp; } /** * Constructs a frequency from a period. * * @param period The period, not null * @return a period frequency, not null */ public static PeriodFrequency of(final Period period) { ArgumentChecker.notNull(period, "period"); for (final Map.Entry<PeriodFrequency, PeriodFrequency> entry : s_cache.entrySet()) { if (entry.getKey().getPeriod().normalized().equals(period.normalized())) { return entry.getValue(); } } return new PeriodFrequency(period.toString(), period); } /** * Given a {@link PeriodFrequency} or {@link SimpleFrequency}, returns a {@link PeriodFrequency}. * If the input is already a {@link PeriodFrequency}, then the original object is returned. * * @param frequency The frequency, not null * @return A frequency based on {@link Period} * @throws IllegalArgumentException if the input is not a {@link PeriodFrequency} or {@link SimpleFrequency} */ public static PeriodFrequency convertToPeriodFrequency(final Frequency frequency) { ArgumentChecker.notNull(frequency, "frequency"); if (frequency instanceof PeriodFrequency) { return (PeriodFrequency) frequency; } else if (frequency instanceof SimpleFrequency) { return ((SimpleFrequency) frequency).toPeriodFrequency(); } throw new IllegalArgumentException("Can only handle PeriodFrequency and SimpleFrequency"); } /** * Creates an instance. * * @param name the name of the convention, not null * @param period length of the period, not null */ /* package */PeriodFrequency(final String name, final Period period) { ArgumentChecker.notNull(name, "name"); ArgumentChecker.notNull(period, "period"); _name = name; _period = period; } // ------------------------------------------------------------------------- /** * @deprecated use getName() * @return the name of the convention */ @Override @Deprecated public String getConventionName() { return getName(); } @Override public String getName() { return _name; } /** * Gets the length of the period defining the convention. * * @return the length of the period, not null */ public Period getPeriod() { return _period; } // ------------------------------------------------------------------------- @Override public boolean equals(final Object obj) { if (obj == this) { return true; } if (obj instanceof PeriodFrequency) { final PeriodFrequency other = (PeriodFrequency) obj; return _name.equals(other._name) && _period.equals(other._period); } return false; } @Override public int hashCode() { return _name.hashCode() ^ _period.hashCode(); } @Override public String toString() { return "Frequency[" + "name = " + _name + " period = " + _period + "]"; } /** * Converts this to a simple frequency. * * @return the simple frequency, not null */ public SimpleFrequency toSimpleFrequency() { if (_name.equals(ANNUAL_NAME)) { return SimpleFrequency.ANNUAL; } if (_name.equals(BIMONTHLY_NAME)) { return SimpleFrequency.BIMONTHLY; } if (_name.equals(BIWEEKLY_NAME)) { return SimpleFrequency.BIWEEKLY; } if (_name.equals(CONTINUOUS_NAME)) { return SimpleFrequency.CONTINUOUS; } if (_name.equals(DAILY_NAME)) { return SimpleFrequency.DAILY; } if (_name.equals(MONTHLY_NAME)) { return SimpleFrequency.MONTHLY; } if (_name.equals(QUARTERLY_NAME)) { return SimpleFrequency.QUARTERLY; } if (_name.equals(SEMI_ANNUAL_NAME)) { return SimpleFrequency.SEMI_ANNUAL; } if (_name.equals(WEEKLY_NAME)) { return SimpleFrequency.WEEKLY; } if (_name.equals(FOUR_MONTH_NAME)) { return SimpleFrequency.FOUR_MONTHS; } if (_name.equals(FIVE_MONTH_NAME)) { return SimpleFrequency.FIVE_MONTHS; } if (_name.equals(SEVEN_MONTH_NAME)) { return SimpleFrequency.SEVEN_MONTHS; } if (_name.equals(EIGHT_MONTH_NAME)) { return SimpleFrequency.EIGHT_MONTHS; } if (_name.equals(NINE_MONTH_NAME)) { return SimpleFrequency.NINE_MONTHS; } if (_name.equals(TEN_MONTH_NAME)) { return SimpleFrequency.TEN_MONTHS; } if (_name.equals(ELEVEN_MONTH_NAME)) { return SimpleFrequency.ELEVEN_MONTHS; } if (_name.equals(EIGHT_MONTH_NAME)) { return SimpleFrequency.EIGHTEEN_MONTHS; } if (_name.equals(TWENTY_EIGHT_DAYS_NAME)) { return SimpleFrequency.TWENTY_EIGHT_DAYS; } throw new IllegalArgumentException("Cannot get a simple frequency for " + toString()); } }