/** * Copyright 2010 Sven Diedrichsen * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language * governing permissions and limitations under the License. */ package de.jollyday; import de.jollyday.caching.HolidayManagerValueHandler; import de.jollyday.configuration.ConfigurationProviderManager; import de.jollyday.datasource.ConfigurationDataSource; import de.jollyday.util.Cache; import de.jollyday.util.Cache.ValueHandler; import de.jollyday.util.CalendarUtil; import java.time.LocalDate; import java.util.Calendar; import java.util.HashSet; import java.util.Properties; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; /** * Abstract base class for all holiday manager implementations. Upon call of * getInstance method the implementing class will be read from the * jollyday.properties file and instantiated. * * @author Sven Diedrichsen * @version $Id: $ */ public abstract class HolidayManager { private static final Logger LOG = Logger.getLogger(HolidayManager.class .getName()); /** * Signifies if caching of manager instances is enabled. If not every call * to getInstance will return a newly instantiated and initialized manager. */ private static boolean CACHING_ENABLED = true; /** * Cache for manager instances on a per country basis. */ private static final Cache<HolidayManager> HOLIDAY_MANAGER_CACHE = new Cache<>(); /** * Manager for configuration providers. Delivers the jollyday configuration. */ private static final ConfigurationProviderManager CONFIGURATION_MANAGER_PROVIDER = new ConfigurationProviderManager(); /** * the holiday cache */ private final Cache<Set<Holiday>> holidayCache = new Cache<>(); /** * Utility for calendar operations */ protected CalendarUtil calendarUtil = new CalendarUtil(); /** * The datasource to get the holiday data from. */ private ConfigurationDataSource configurationDataSource; /** * the manager parameter */ private ManagerParameter managerParameter; /** * Creates a HolidayManager instance for the default locale country using * the configured properties from the configuration file. * @return a eventually cached HolidayManager instance */ public static HolidayManager getInstance() { return getInstance(ManagerParameters.create((String)null, null)); } /** * Creates a HolidayManager instance for the default locale country using * the provided properties. * @param properties the overriding configuration properties. * @return a eventually cached HolidayManager instance */ public static HolidayManager getInstance(Properties properties) { return getInstance(ManagerParameters.create((String)null, properties)); } /** * @deprecated Use {@link #getInstance(ManagerParameter)} instead. * @param c the {@link HolidayCalendar} to use for creating a {@link HolidayManager} instance * @return the eventually cached {@link HolidayManager} */ @Deprecated public static HolidayManager getInstance(final HolidayCalendar c) { return getInstance(ManagerParameters.create(c, null)); } /** * @deprecated Use {@link #getInstance(ManagerParameter)} instead. * @param c the {@link HolidayCalendar} to use for creating a {@link HolidayManager} instance * @param properties the configuration overriding {@link Properties} * @return the eventually cached {@link HolidayManager} */ @Deprecated public static HolidayManager getInstance(final HolidayCalendar c, Properties properties) { return getInstance(ManagerParameters.create(c, properties)); } /** * @deprecated Use {@link #getInstance(ManagerParameter)} instead. * @param calendar the calendar to use for creating a {@link HolidayManager} instance * @return the eventually cached {@link HolidayManager} */ @Deprecated public static HolidayManager getInstance(final String calendar) { return getInstance(ManagerParameters.create(calendar, null)); } /** * @deprecated Use {@link #getInstance(ManagerParameter)} instead. * @param calendar the calendar to use for creating a {@link HolidayManager} instance * @param properties the configuration overriding {@link Properties} * @return the eventually cached {@link HolidayManager} */ @Deprecated public static HolidayManager getInstance(final String calendar, Properties properties) { return getInstance(ManagerParameters.create(calendar, properties)); } /** * Creates and returns a {@link HolidayManager} for the provided * {@link ManagerParameters} * * @param parameter * the {@link ManagerParameters} to create the manager with * @return the {@link HolidayManager} instance */ public static HolidayManager getInstance(ManagerParameter parameter) { return createManager(parameter); } /** * Creates a new <code>HolidayManager</code> instance for the country and * puts it to the manager cache. * * @param parameter the parameter will be merged into the current configuration * @return created or cached holiday manager */ private static HolidayManager createManager(final ManagerParameter parameter) { if (LOG.isLoggable(Level.FINER)) { LOG.finer("Creating HolidayManager for calendar '" + parameter + "'. Caching enabled: " + isManagerCachingEnabled()); } CONFIGURATION_MANAGER_PROVIDER.mergeConfigurationProperties(parameter); final String managerImplClassName = readManagerImplClassName(parameter); HolidayManagerValueHandler holidayManagerValueHandler = new HolidayManagerValueHandler( parameter, managerImplClassName); if(isManagerCachingEnabled()){ return HOLIDAY_MANAGER_CACHE.get(holidayManagerValueHandler); }else{ return holidayManagerValueHandler.createValue(); } } /** * Reads the managers implementation class from the properties config file. * @param parameter the parameter to read the manager implementation class from * @return the manager implementation class name */ private static String readManagerImplClassName(ManagerParameter parameter) { String className = parameter.getManangerImplClassName(); if (className == null) { throw new IllegalStateException("Missing configuration '" + ManagerParameter.MANAGER_IMPL_CLASS_PREFIX + "'. Cannot create manager."); } return className; } /** * If true, instantiated managers will be cached. If false every call to * getInstance will create new manager. True by default. * * @param managerCachingEnabled * the managerCachingEnabled to set */ public static void setManagerCachingEnabled(boolean managerCachingEnabled) { CACHING_ENABLED = managerCachingEnabled; } /** * <p> * isManagerCachingEnabled. * </p> * * @return the CACHING_ENABLED */ public static boolean isManagerCachingEnabled() { return CACHING_ENABLED; } /** * Clears the manager cache from all cached manager instances. */ public static void clearManagerCache() { synchronized (HOLIDAY_MANAGER_CACHE) { HOLIDAY_MANAGER_CACHE.clear(); } } /** * Calls isHoliday with {@link LocalDate} object. * * @param c {@link java.util.Calendar} to check. * @param holidayType type holidays to be considered. NULL checks any. * @param args a {@link java.lang.String} object. * @return if the date is a holiday */ public boolean isHoliday(final Calendar c, HolidayType holidayType, final String... args) { return isHoliday(calendarUtil.create(c), holidayType, args); } public boolean isHoliday(final Calendar c, final String... args) { return isHoliday(c, null, args); } /** * Show if the requested date is a holiday. * * @param c The potential holiday. * @param holidayType a {@link HolidayType} object * @param args * Hierarchy to request the holidays for. i.e. args = {'ny'} -> * New York holidays * @return is a holiday in the state/region */ public boolean isHoliday(final LocalDate c, HolidayType holidayType, final String... args) { final StringBuilder keyBuilder = new StringBuilder(); keyBuilder.append(c.getYear()); for (String arg : args) { keyBuilder.append("_"); keyBuilder.append(arg); } Set<Holiday> holidays = holidayCache.get(new ValueHandler<Set<Holiday>>() { @Override public String getKey() { return keyBuilder.toString(); } @Override public Set<Holiday> createValue() { return getHolidays(c.getYear(), args); } }); return calendarUtil.contains(holidays, c, holidayType); } /** * Calls #isHoliday(c, null, args) * @param c the date to check * @param args the arguments to find the calendar * @return whether the date is a holiday */ public boolean isHoliday(final LocalDate c, final String... args){ return isHoliday(c, null, args); } /** * Returns a set of all currently supported calendar codes. * * @return Set of supported calendar codes. */ public static Set<String> getSupportedCalendarCodes() { Set<String> supportedCalendars = new HashSet<>(); for (HolidayCalendar c : HolidayCalendar.values()) { supportedCalendars.add(c.getId()); } return supportedCalendars; } /** * Sets the configuration datasource with this holiday manager. * * @param configurationDataSource * the {@link ConfigurationDataSource} to use. */ public void setConfigurationDataSource( ConfigurationDataSource configurationDataSource) { this.configurationDataSource = configurationDataSource; } /** * Returns the {@link ConfigurationDataSource} to be used to retrieve * holiday data. * * @return the {@link ConfigurationDataSource} to use. */ public ConfigurationDataSource getConfigurationDataSource() { return configurationDataSource; } public ManagerParameter getManagerParameter() { return managerParameter; } /** * Initializes the implementing manager for the provided calendar. * * @param parameters * i.e. us, uk, de */ public void init(ManagerParameter parameters) { this.managerParameter = parameters; this.doInit(); } abstract public void doInit(); /** * Returns the holidays for the requested year and hierarchy structure. * * @param year * i.e. 2010 * @param args * i.e. args = {'ny'}. returns US/New York holidays. No args -> * holidays common to whole country * @return the list of holidays for the requested year */ abstract public Set<Holiday> getHolidays(int year, String... args); /** * Returns the holidays for the requested interval and hierarchy structure. * * @param startDateInclusive * the start date of the interval in which holidays lie, inclusive * @param endDateInclusive * the end date of the interval in which holidays lie, inclusive * @param args * a {@link java.lang.String} object. * @return list of holidays within the interval */ abstract public Set<Holiday> getHolidays(LocalDate startDateInclusive, LocalDate endDateInclusive, String... args); /** * Returns the configured hierarchy structure for the specific manager. This * hierarchy shows how the configured holidays are structured and can be * retrieved. * * @return Current calendars hierarchy */ abstract public CalendarHierarchy getCalendarHierarchy(); }