001/*
002 * (C) Copyright 2006-2010 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     <a href="mailto:nulrich@nuxeo.com">Nicolas Ulrich</a>
016 *
017 */
018
019package org.nuxeo.business.days.management.service;
020
021import java.util.Calendar;
022import java.util.Date;
023import java.util.GregorianCalendar;
024import java.util.HashMap;
025import java.util.Map;
026
027import org.nuxeo.business.days.management.checker.HolidaysChecker;
028import org.nuxeo.business.days.management.service.BusinessDaysService;
029import org.nuxeo.runtime.model.ComponentInstance;
030import org.nuxeo.runtime.model.DefaultComponent;
031
032/**
033 * @author Nicolas Ulrich
034 */
035public class BusinessDaysServiceImpl extends DefaultComponent implements BusinessDaysService {
036
037    private final Map<String, Integer> values = new HashMap<String, Integer>();
038
039    private HolidaysChecker check;
040
041    public Date getLimitDate(String label, Date from) {
042
043        if (!values.containsKey(label)) {
044            return null;
045        }
046
047        int duration = values.get(label);
048
049        Calendar fromCalendar = GregorianCalendar.getInstance();
050        fromCalendar.setTime(from);
051        fromCalendar.set(Calendar.HOUR_OF_DAY, 0); // set hour to midnight
052        fromCalendar.set(Calendar.MINUTE, 0); // set minute in hour
053        fromCalendar.set(Calendar.SECOND, 0); // set second in minute
054        fromCalendar.set(Calendar.MILLISECOND, 0);
055
056        for (int i = 0; i < duration; i++) {
057
058            fromCalendar.add(Calendar.DAY_OF_YEAR, 1);
059
060            // If this is a non working day, increase the limit
061            if (isHolidayDay(fromCalendar)) {
062                duration++;
063            }
064
065        }
066
067        return fromCalendar.getTime();
068    }
069
070    private boolean isHolidayDay(Calendar day) {
071        if (day.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || day.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY
072                || (check != null && check.isHoliday(day.getTime())))
073            return true;
074
075        return false;
076
077    }
078
079    @Override
080    public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
081
082        if (extensionPoint.equals("duration")) {
083
084            DurationDescriptor duration = ((DurationDescriptor) contribution);
085            values.put(duration.label, duration.numberOfDays);
086
087        } else if (extensionPoint.equals("holidaysChecker")) {
088
089            HolidaysCheckerDescriptor distributionType = ((HolidaysCheckerDescriptor) contribution);
090            try {
091                check = (HolidaysChecker) Class.forName(distributionType.clazz).newInstance();
092            } catch (ReflectiveOperationException e) {
093                throw new RuntimeException(e);
094            }
095
096        }
097
098    }
099
100    @Override
101    public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
102
103        if (extensionPoint.equals("duration")) {
104
105            DurationDescriptor duration = ((DurationDescriptor) contribution);
106            values.remove(duration);
107
108        }
109
110    }
111
112}