com.helger.datetime.holiday.parser.AbstractHolidayParser.java Source code

Java tutorial

Introduction

Here is the source code for com.helger.datetime.holiday.parser.AbstractHolidayParser.java

Source

/**
 * Copyright (C) 2014-2015 Philip Helger (www.helger.com)
 * philip[at]helger[dot]com
 *
 * 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 com.helger.datetime.holiday.parser;

import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;

import org.joda.time.LocalDate;

import com.helger.datetime.holiday.config.Holiday;
import com.helger.datetime.holiday.config.MoveableHoliday;
import com.helger.datetime.holiday.config.MovingCondition;
import com.helger.datetime.holiday.config.With;
import com.helger.datetime.holiday.mgr.XMLUtil;

/**
 * The abstract base class for all {@link IHolidayParser} implementations.
 * 
 * @author Sven Diedrichsen
 * @author Philip Helger
 */
@Immutable
public abstract class AbstractHolidayParser implements IHolidayParser {
    protected AbstractHolidayParser() {
    }

    /**
     * Evaluates if the provided <code>Holiday</code> instance is valid for the
     * provided year.
     * 
     * @param aHoliday
     *        The holiday configuration entry to validate
     * @param nYear
     *        The year to validate against.
     * @return is valid for the year.
     */
    protected static final boolean isValid(final Holiday aHoliday, final int nYear) {
        return _isValidInYear(aHoliday, nYear) && _isValidForCycle(aHoliday, nYear);
    }

    /**
     * Checks cyclic holidays and checks if the requested year is hit within the
     * cycles.
     * 
     * @param aHoliday
     *        Holiday
     * @param nYear
     *        the year to check against
     * @return is valid
     */
    private static boolean _isValidForCycle(@Nonnull final Holiday aHoliday, final int nYear) {
        final String sEvery = aHoliday.getEvery();
        if (sEvery != null && !"EVERY_YEAR".equals(sEvery)) {
            if ("ODD_YEARS".equals(sEvery))
                return nYear % 2 != 0;
            if ("EVEN_YEARS".equals(sEvery))
                return nYear % 2 == 0;

            if (aHoliday.getValidFrom() != null) {
                int nCycleYears = 0;
                if ("2_YEARS".equalsIgnoreCase(sEvery))
                    nCycleYears = 2;
                else if ("3_YEARS".equalsIgnoreCase(sEvery))
                    nCycleYears = 3;
                else if ("4_YEARS".equalsIgnoreCase(sEvery))
                    nCycleYears = 4;
                else if ("5_YEARS".equalsIgnoreCase(sEvery))
                    nCycleYears = 5;
                else if ("6_YEARS".equalsIgnoreCase(sEvery))
                    nCycleYears = 6;
                else
                    throw new IllegalArgumentException("Cannot handle unknown cycle type '" + sEvery + "'.");

                return (nYear - aHoliday.getValidFrom().intValue()) % nCycleYears == 0;
            }
        }
        return true;
    }

    /**
     * Checks whether the holiday is within the valid date range.
     * 
     * @param aHoliday
     * @param nYear
     * @return is valid.
     */
    private static boolean _isValidInYear(@Nonnull final Holiday aHoliday, final int nYear) {
        return (aHoliday.getValidFrom() == null || aHoliday.getValidFrom().intValue() <= nYear)
                && (aHoliday.getValidTo() == null || aHoliday.getValidTo().intValue() >= nYear);
    }

    /**
     * Determines if the provided date shall be substituted.
     * 
     * @param aFixed
     *        The date to be checked. May not be <code>null</code>.
     * @param aMoveCond
     *        The move condition. May not be <code>null</code>.
     */
    protected static final boolean shallBeMoved(@Nonnull final LocalDate aFixed,
            @Nonnull final MovingCondition aMoveCond) {
        return aFixed.getDayOfWeek() == XMLUtil.getWeekday(aMoveCond.getSubstitute());
    }

    /**
     * Moves the date using the FixedMoving information
     * 
     * @param aMoveCond
     * @param aDate
     * @return The moved date
     */
    private static LocalDate _moveDate(final MovingCondition aMoveCond, final LocalDate aDate) {
        final int nWeekday = XMLUtil.getWeekday(aMoveCond.getWeekday());
        final int nDirection = aMoveCond.getWith() == With.NEXT ? 1 : -1;

        LocalDate aMovedDate = aDate;
        while (aMovedDate.getDayOfWeek() != nWeekday) {
            aMovedDate = aMovedDate.plusDays(nDirection);
        }
        return aMovedDate;
    }

    /**
     * Moves a date if there are any moving conditions for this holiday and any of
     * them fit.
     * 
     * @param aMoveableHoliday
     * @param aFixed
     * @return the moved date
     */
    protected static final LocalDate moveDate(final MoveableHoliday aMoveableHoliday, final LocalDate aFixed) {
        for (final MovingCondition aMoveCond : aMoveableHoliday.getMovingCondition())
            if (shallBeMoved(aFixed, aMoveCond))
                return _moveDate(aMoveCond, aFixed);
        return aFixed;
    }
}