/** * 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.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.joda.convert.FromString; import com.opengamma.OpenGammaRuntimeException; import com.opengamma.financial.convention.AbstractNamedInstanceFactory; /** * Factory to obtain instances of {@code SimpleFrequency}. */ public final class SimpleFrequencyFactory extends AbstractNamedInstanceFactory<SimpleFrequency> { /** * Singleton instance. */ public static final SimpleFrequencyFactory INSTANCE = new SimpleFrequencyFactory(); /** * Map of periods per year to convention, only contains frequencies with an integer number of periods per year * (plus {@link SimpleFrequency#TWENTY_EIGHT_DAYS} with a key of 13 periods). */ private final Map<Integer, SimpleFrequency> _periodsMap = new HashMap<>(); //------------------------------------------------------------------------- /** * Finds a convention by name, ignoring case. * * @param name the name of the instance to find, not null * @return the convention, not null * @throws IllegalArgumentException if the name is not found */ @FromString public static SimpleFrequency of(final String name) { return INSTANCE.instance(name); } //------------------------------------------------------------------------- /** * Restricted constructor, hard coding the conventions. */ private SimpleFrequencyFactory() { super(SimpleFrequency.class); addInstance(SimpleFrequency.NEVER, "1t"); addInstance(SimpleFrequency.ANNUAL, "12m", "1y", "Yearly"); addInstance(SimpleFrequency.SEMI_ANNUAL, "6m", "Half Yearly"); addInstance(SimpleFrequency.QUARTERLY, "3m"); addInstance(SimpleFrequency.BIMONTHLY, "2m"); addInstance(SimpleFrequency.MONTHLY, "1m"); addInstance(SimpleFrequency.TWENTY_EIGHT_DAYS, "28d"); addInstance(SimpleFrequency.THREE_WEEKS, "3w"); addInstance(SimpleFrequency.BIWEEKLY, "2w"); addInstance(SimpleFrequency.WEEKLY, "1w"); addInstance(SimpleFrequency.DAILY, "1d"); addInstance(SimpleFrequency.CONTINUOUS); addInstance(SimpleFrequency.FOUR_MONTHS, "4m"); addInstance(SimpleFrequency.FIVE_MONTHS, "5m"); addInstance(SimpleFrequency.SEVEN_MONTHS, "7m"); addInstance(SimpleFrequency.EIGHT_MONTHS, "8m"); addInstance(SimpleFrequency.NINE_MONTHS, "9m"); addInstance(SimpleFrequency.TEN_MONTHS, "10m"); addInstance(SimpleFrequency.ELEVEN_MONTHS, "11m"); storeByPeriodCount(SimpleFrequency.DAILY, SimpleFrequency.WEEKLY, SimpleFrequency.BIWEEKLY, SimpleFrequency.TWENTY_EIGHT_DAYS, SimpleFrequency.MONTHLY, SimpleFrequency.BIMONTHLY, SimpleFrequency.QUARTERLY, SimpleFrequency.SEMI_ANNUAL, SimpleFrequency.ANNUAL); } /** * Stores the frequencies keyed by the number of periods per year. This only really makes sense for periods * with an integer number of periods per year. It will fail if it is called with multiple frequencies whose * period counts round to the same integer. * @param frequencies The frequencies to keyed on their (integer) period count. */ private void storeByPeriodCount(final SimpleFrequency... frequencies) { for (final SimpleFrequency frequency : frequencies) { final int periodsPerYear = (int) frequency.getPeriodsPerYear(); // this check is to prevent a repeat of a bug where frequencies were overwritten by another frequency whose // non-integer period count rounded to the same integer if (_periodsMap.containsKey(periodsPerYear)) { final SimpleFrequency existingFrequency = _periodsMap.get(periodsPerYear); throw new OpenGammaRuntimeException("Cannot overwrite " + existingFrequency.getName() + " with " + frequency.getName()); } _periodsMap.put(periodsPerYear, frequency); } } //------------------------------------------------------------------------- /** * Gets a convention by name. * Matching is case insensitive. * * @param name the name, not null * @return the convention, null if not found * @deprecated Use {@link #of(String)} or {@link #instance(String)}. */ @Deprecated public SimpleFrequency getFrequency(final String name) { try { return instance(name); } catch (IllegalArgumentException ex) { return null; } } /** * Gets a convention by the number of periods per year. * <p> * Some underlying data systems use this representation for frequency. * * @param periods the number of periods per year, zero means once at end * @return the convention, null if not found */ public SimpleFrequency getFrequency(final int periods) { return _periodsMap.get(periods); } /** * Iterates over the available frequencies. No particular ordering is specified and conventions may * exist in the system not provided by this factory that aren't included as part of this enumeration. * * @return the available conventions, not null * @deprecated Use {@link #instanceMap()} */ @Deprecated public Iterator<SimpleFrequency> enumerateAvailableFrequencies() { List<SimpleFrequency> frequencies = new ArrayList<>(instanceMap().values()); Collections.sort(frequencies, new Comparator<SimpleFrequency>() { @Override public int compare(final SimpleFrequency o1, final SimpleFrequency o2) { return (int) Math.signum(o2.getPeriodsPerYear() - o1.getPeriodsPerYear()); } }); return frequencies.iterator(); } }