001package jmri.implementation;
002
003import java.beans.PropertyChangeEvent;
004import java.util.Date;
005import jmri.Conditional;
006import jmri.InstanceManager;
007import jmri.Timebase;
008
009/**
010 * A service class for monitoring a bound property in one of the JMRI Named
011 * beans For use with properties having two states which are determined by
012 * containment in an interval (e.g. Fast Clock ranges).
013 * <p>
014 * This file is part of JMRI.
015 * <p>
016 * JMRI is free software; you can redistribute it and/or modify it under the
017 * terms of version 2 of the GNU General Public License as published by the Free
018 * Software Foundation. See the "COPYING" file for a copy of this license.
019 * <p>
020 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY
021 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
022 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
023 *
024 * @author Pete Cressman Copyright (C) 2009
025 * @since 2.5.1
026 */
027public class JmriClockPropertyListener extends JmriSimplePropertyListener {
028
029    static int SIZE = 10;
030    int numRanges = 0;
031    int[] _beginTimes = new int[SIZE];
032    int[] _endTimes = new int[SIZE];
033    boolean[] _rangeList = new boolean[SIZE];
034    Timebase _fastClock;
035    int _currentMinutes;
036
037    @SuppressWarnings("deprecation") // Date.getTime
038    JmriClockPropertyListener(String propName, int type, String name, Conditional.Type varType,
039            Conditional client, int beginTime, int endTime) {
040        super(propName, type, name, varType, client);
041        _beginTimes[0] = fixMidnight(beginTime);
042        _endTimes[0] = fixMidnight(endTime);
043        _rangeList[0] = false;
044        numRanges = 1;
045        _fastClock = InstanceManager.getDefault(jmri.Timebase.class);
046        Date currentTime = _fastClock.getTime();
047        _currentMinutes = (currentTime.getHours() * 60) + currentTime.getMinutes();
048    }
049
050    private int fixMidnight(int time) {
051        if (time > 24 * 60) {
052            time -= 24 * 60;
053        }
054        return time;
055    }
056
057    public void setRange(int beginTime, int endTime) {
058        if (numRanges >= _rangeList.length) {
059            int[] temp = new int[numRanges + SIZE];
060            System.arraycopy(_beginTimes, 0, temp, 0, _beginTimes.length);
061            _beginTimes = temp;
062            temp = new int[numRanges + SIZE];
063            System.arraycopy(_endTimes, 0, temp, 0, _endTimes.length);
064            _endTimes = temp;
065            boolean[] bools = new boolean[numRanges + SIZE];
066            System.arraycopy(_rangeList, 0, bools, 0, _rangeList.length);
067            _rangeList = bools;
068        }
069        _beginTimes[numRanges] = fixMidnight(beginTime);
070        _endTimes[numRanges] = fixMidnight(endTime);
071        _rangeList[numRanges] = false;
072        numRanges++;
073    }
074
075    /**
076     * Check if have entered/exited one of the Fast Clock Ranges
077     * <p>
078     * This method is invoked when the minute listener fires.
079     */
080    @SuppressWarnings("deprecation")  // Date.getHours, getMinutes, getSeconds
081    @Override
082    public void propertyChange(PropertyChangeEvent evt) {
083        Date currentTime = _fastClock.getTime();
084        //int oldMinutes = _currentMinutes;
085        _currentMinutes = (currentTime.getHours() * 60) + currentTime.getMinutes();
086        // check if we have entered or left one of the ranges
087        boolean[] newRangeList = new boolean[_rangeList.length];
088        for (int i = 0; i < numRanges; i++) {
089            // check if entered or left desired time range
090            if (_beginTimes[i] < _endTimes[i]) {
091                // range not crossing midnight, test ends of range
092                if ((_beginTimes[i] <= _currentMinutes) && (_currentMinutes <= _endTimes[i])) {
093                    newRangeList[i] = true;
094                } else {
095                    newRangeList[i] = false;
096                }
097            } else { // range crosses midnight
098                if ((_beginTimes[i] <= _currentMinutes) || (_currentMinutes <= _endTimes[i])) {
099                    newRangeList[i] = true;
100                } else {
101                    newRangeList[i] = false;
102                }
103            }
104            //log.debug("currentMinutes= "+_currentMinutes+" beginTime= "+_beginTimes[i]+
105            //          " endTime="+_endTimes[i]+"new= "+newRangeList[i]+" old= "+_rangeList[i]);
106        }
107        // check for changes
108        for (int i = 0; i < numRanges; i++) {
109            if (_rangeList[i] != newRangeList[i]) {
110                _rangeList = newRangeList;
111                super.propertyChange(evt);
112            }
113        }
114    }
115}