Follow me

Exercise 7: Reacting to time events

In this exercise you will learn to react to timed events.

Question 1 – Moment Of The Day Component: We propose to reconfigure the illuminance based on moment of the day. In that purpose you will need to create a new component “MomentOfTheDay” in a new package “org.example.time”.

Make sure you export the service as it will be reused by your manager.

The component will provide a service MomentOfTheDayService :

package org.example.time;
 
/**
 * The MomentOfTheDay service is used to retrieve the moment of the day.
 * It also supports listeners that are notified when the moment of the day
 * change.
 */
public interface MomentOfTheDayService {
 
    /**
     * Gets the moment of the day.
     * 
     * @return the moment of the day
     */
    MomentOfTheDay getMomentOfTheDay();
 
 
    //...
}

A MomentOfTheDay is defined by the following enum :

package org.example.time;
 
public enum MomentOfTheDay {
    MORNING(6), AFTERNOON(12), EVENING(18), NIGHT(24);
 
    /**
     * Gets the moment of the day corresponding to the hour.
     * 
     * @param hour
     *            the given hour
     * @return the corresponding moment of the day
     */
    MomentOfTheDay getCorrespondingMoment(int hour) {
        assert ((0 <= startHour) && (startHour <= 24));
        // TODO : if (hour < //..
        return null;
    }
 
    /**
     * The hour when the moment start.
     */
    private final int startHour;
 
    /**
     * Build a new moment of the day :
     * 
     * @param startHour
     *            when the moment start.
     */
    MomentOfTheDay(int startHour) {
        assert ((0 <= startHour) && (startHour <= 24));
        this.startHour = startHour;
    }
}

Implement the MomentOfTheDayService. The implementation class should be named “MomentOfTheDayImpl” and will be based on the PeriodicRunnable of the fr.liglab.adele.icasa.service.scheduler package.

The PeriodicRunnable follow the whiteboard pattern (you don’t need to understand how it works to implement it).

Basically you have to provide PeriodicRunnable as a service and implement it into your MomentOfTheDayImpl class. Then iCASA will automatically discover your service and its configuration. It will call the run() method on a regular basis,based on the getPeriod() and getUnit() methods.
momentOfTheDay

public class MomentOfTheDayImpl implements MomentOfTheDayService, PeriodicRunnable{
 
    /**
    * The current moment of the day :
    **/
    MomentOfTheDay currentMomentOfTheDay;
 
    // Implementation of the MomentOfTheDayService ....
 
    public MomentOfTheDay getMomentOfTheDay(){
 
    }
 
    // Implementation ot the PeriodicRunnable ...
    // The service will be periodically called every hour.
    
    @Override
    public long getPeriod(){
        return 1;
    }
 
    @Override
    public TimeUnit getUnit() {
        return TimeUnit.HOURS;
    }

    @Override
    public void run() {
        // The method run is called on a regular basis
 
        // TODO : do something to check the current time of the day and see if
        // it has changed
 
    }
 
}

Complete the code above to work as expected.

Question 2 – Writing a command: You can implement a command to test that your code is working :
momentOfTheDayCommand

g! getMomentOfTheDay
AFTERNOON

Question 3 – Implementing Listeners You will now change your implementation to support listeners.
Here is the new interface of the service :

package org.example.time;
 
public interface MomentOfTheDayService {
 
    MomentOfTheDay getMomentOfTheDay();
 
    /**
     * Register a listener that will be notified each time the current moment of the day
     * changed.
     * 
     * @param listener
     *            the listener
     */
    void register(MomentOfTheDayListener listener);
 
    /**
     * Unregister a moment of the day listener.
     * 
     * @param listener
     *            the listener
     */
    void unregister(MomentOfTheDayListener listener);
}

Here is the interface of the Listeners :

package org.example.time;
 
/**
 * The listener interface for receiving momentOfTheDay events.
 * The class that is interested in processing a momentOfTheDay
 * event implements this interface, and the object created
 * with that class is registered with a component using the
 * MomentOfTheDayService <code>register<code> method. When
 * the momentOfTheDay event occurs, that object's appropriate
 * method (<code>momentOfTheDayHasChanged</code>) is invoked.
 * 
 * When the listener is leaving, it must unregister.
 * 
 */
public interface MomentOfTheDayListener {
 
    /**
     * Notify the listener that moment of the day has changed.
     * 
     * @param newMomentOfTheDay
     *            the new moment of the day
     */
    void momentOfTheDayHasChanged(MomentOfTheDay newMomentOfTheDay);
}

Change your implementation to manage listeners. The easiest way to do the that is to maintain a list of listeners and call the momentOfTheDayHasChanged method of each listener every time the moment of the day changes.

To simplify the concurrency management, you can add synchronize before each method (performance greedy but safe). If you are more confident, you can use a lock to prevent concurrent access to the list.

Question 4 – A moment-aware manager: Change your manager implementation to implement the listener.momentOfTheDayListener
The idea is to adapt the illuminance based on the moment of the day.
Here are some suggestion of factor you could use to compute the SOFT, MEDIUM, FULL configuration:

// There is no need of full illuminance in the morning 
private double factor MORNING_ILLUMINANCE_FACTOR = 0.5;
// In the afternoon the illuminance can be largely limited
private double factor ATERNOON_ILLUMINANCE_FACTOR = 0.2;
// In the evening, the illuminance should be the best
private double factor EVENING_ILLUMINANCE_FACTOR = 1;
// In the night, there is no need to use the full illuminance
private double factor NIGHT_ILLUMINANCE_FACTOR = 0.8;

The new SOFT value would be SOFT = MOMENT_FACTOR * DEFAULT_SOFT where DEFAULT_SOFT is the value you were using before, and MOMENT_FACTOR is one of the FACTOR given above.