001/*
002 * (C) Copyright 2006-2010 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     <a href="mailto:nulrich@nuxeo.com">Nicolas Ulrich</a>
018 *
019 */
020
021package org.nuxeo.business.days.management.service;
022
023import java.util.Calendar;
024import java.util.Date;
025import java.util.GregorianCalendar;
026import java.util.HashMap;
027import java.util.Map;
028
029import org.nuxeo.business.days.management.checker.HolidaysChecker;
030import org.nuxeo.business.days.management.service.BusinessDaysService;
031import org.nuxeo.runtime.model.ComponentInstance;
032import org.nuxeo.runtime.model.DefaultComponent;
033
034/**
035 * @author Nicolas Ulrich
036 */
037public class BusinessDaysServiceImpl extends DefaultComponent implements BusinessDaysService {
038
039    private final Map<String, Integer> values = new HashMap<String, Integer>();
040
041    private HolidaysChecker check;
042
043    public Date getLimitDate(String label, Date from) {
044
045        if (!values.containsKey(label)) {
046            return null;
047        }
048
049        int duration = values.get(label);
050
051        Calendar fromCalendar = GregorianCalendar.getInstance();
052        fromCalendar.setTime(from);
053        fromCalendar.set(Calendar.HOUR_OF_DAY, 0); // set hour to midnight
054        fromCalendar.set(Calendar.MINUTE, 0); // set minute in hour
055        fromCalendar.set(Calendar.SECOND, 0); // set second in minute
056        fromCalendar.set(Calendar.MILLISECOND, 0);
057
058        for (int i = 0; i < duration; i++) {
059
060            fromCalendar.add(Calendar.DAY_OF_YEAR, 1);
061
062            // If this is a non working day, increase the limit
063            if (isHolidayDay(fromCalendar)) {
064                duration++;
065            }
066
067        }
068
069        return fromCalendar.getTime();
070    }
071
072    private boolean isHolidayDay(Calendar day) {
073        if (day.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || day.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY
074                || (check != null && check.isHoliday(day.getTime())))
075            return true;
076
077        return false;
078
079    }
080
081    @Override
082    public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
083
084        if (extensionPoint.equals("duration")) {
085
086            DurationDescriptor duration = ((DurationDescriptor) contribution);
087            values.put(duration.label, duration.numberOfDays);
088
089        } else if (extensionPoint.equals("holidaysChecker")) {
090
091            HolidaysCheckerDescriptor distributionType = ((HolidaysCheckerDescriptor) contribution);
092            try {
093                check = (HolidaysChecker) Class.forName(distributionType.clazz).newInstance();
094            } catch (ReflectiveOperationException e) {
095                throw new RuntimeException(e);
096            }
097
098        }
099
100    }
101
102    @Override
103    public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
104
105        if (extensionPoint.equals("duration")) {
106
107            DurationDescriptor duration = ((DurationDescriptor) contribution);
108            values.remove(duration);
109
110        }
111
112    }
113
114}