Chapter 9. Entity events

Table of Contents

Polling observable

Entities as well as the entire file system, may be configured to be Observable for events. Clients that want to receive notification of entity updates, register a listener of the type EntityObserver on the entity or on the file system object. The listener will then receive all EntityEvent:s that involve the observed entity, or for a file system listener, all events in that file system.

Every event has a sender which is the entity that generated the event.

Example 9.1. Registering an observer on a directory

// d is a directory. Register a simple observer on it.
d.addObserver(
  new EntityObserver() 
  {
    public void update(EntityEvent<?> ee)
    {
      if (ee instanceof ChildEntityAddedEvent)
      {
        System.out.println("Child entity " + 
          ((ChildEntityAddedEvent) ee).getChildEntity() +
          " added to directory " + ee.getSender());
      }
      else
      {
        System.out.println("Event: " + ee);
      }
    }
  });

Directories.newFile(d, "f1");

The observer will print out that the file f1 was added.


Table 9.1. EntityEvent types

EntityEventDescription
ChildEntityAddedEventAn entity has been added to a Directory.
ChildEntityDisappearedEventThe EntityValidityControlStrategy has detected that an entity has disappeared from a Directory. The entity was not removed through using the file system's methods. It might have been removed by another process altogether.
ChildEntityModifiedEventAn entity in a Directory has been modified in a way that updated its last modification time property. For modified files, this event is generated when the client closes its stream or channel on the file.
ChildEntityRemovedEventA child entity has been removed from a Directory, either by deleting it or moving it to another directory.
ChildEntityRenamedEventAn entity in a Directory has been renamed within the same directory.
EntityDeletedEventThe entity has been deleted.
EntityDisappearedEventThe FileSystem's EntityValidityControlStrategy has detected that the entity has disappeared. It was not removed through using the file system's methods. The entity is not valid (its isValid method will return false) when the observer receives the event.
EntityModifiedEventThe entity was modified in a way that updated its latest modification time. For modified files, this event is generated when the client closes its stream or channel on the file.

The EntityObserver's update method is called in the thread that generated the event. This means that, if the file system is locking, the calling thread is holding a write lock on the event's sender when update is called. It also means that update should return quickly. If there is a lot of work to do in response to an event, use an Executor to schedule the work for execution in another thread.

The following examples show which events that are generated when the file system is modified in different ways.

Example 9.2. Adding a file to a directory


Example 9.3. Modifying a file


Example 9.4. Moving an entity


For directories that can be modified by someone that does not use its file system's methods, for instance by another process, a DirectoryMonitorer can be used to detect updates. Generally, it is not recommended to let entities be modified without using their entity objects, but in some cases, such as when monitoring a directory for incoming files, it can be useful. It requires a good EntityValidityControlStrategy for the file system, though.

Example 9.5. Using a polling directory monitorer to watch for incoming XML files

// d is the directory to monitor.
// Create a view that only shows XML files.
DirectoryView dv = d.newView(new EFileNameExtensionFilter("xml"));

// Create a timer that will tell the monitorer when to scan the directory
// for updates. Any old Observable should work; the monitorer will
// scan its directory every time the Observable generates an event.
// Scan every minute.
TimerTicker tt = new TimerTicker(60000);

// Create a polling monitorer on the directory view.
PollingDirectoryMonitorer mon = 
  new PollingDirectoryMonitorer(dv, tt);
  
// Register an observer on the monitorer
mon.addObserver(new EntityObserver() 
  {
    public void update(EntityEvent ee)
    {
      if (ee instanceof ChildEntitiesAddedEvent)
      {
        System.out.println("New child entities: " + ee);
      }
    }
  });

// Start the monitorer
mon.start();

// Start the timer ticker.
tt.start();

// This will generate an event sometime in the next minute
Directories.newFile(d, "foo.xml");

// This will not
Directories.newFile(d, "bar.txt");

// Neither will this
Directories.newDirectory(d, "baz.xml");

// But this will
new File(
  ECFileResolvableUtil.getFileObject(d) + 
    File.separator +
    "doh.xml").createNewFile();