Coverage Report - org.webslinger.io.AbstractMonitor
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractMonitor
0%
0/29
0%
0/11
0
AbstractMonitor$Watched
0%
0/4
N/A
0
AbstractMonitor$WatchedListener
0%
0/19
0%
0/3
0
 
 1  
 package org.webslinger.io;
 2  
 
 3  
 import java.io.IOException;
 4  
 import java.util.HashSet;
 5  
 import java.util.concurrent.ConcurrentHashMap;
 6  
 
 7  
 import org.webslinger.util.BinTimer;
 8  
 
 9  
 public abstract class AbstractMonitor<I, M extends AbstractMonitor<I, M, W, L>, W extends AbstractMonitor.Watched<I, M, W, L>, L extends Monitor.Listener<I>> implements Monitor<I, L> {
 10  0
     protected final ConcurrentHashMap<I, WatchedListener<I, M, W, L>> watches = new ConcurrentHashMap<I, WatchedListener<I, M, W, L>>();
 11  
 
 12  0
     protected AbstractMonitor() {
 13  0
     }
 14  
 
 15  
     public void add(I item, L listener) throws IOException {
 16  
         WatchedListener<I, M, W, L> oldWl, newWl;
 17  
         do {
 18  0
             oldWl = watches.get(item);
 19  0
             if (oldWl == null) {
 20  0
                 W watched = createWatched(item);
 21  0
                 newWl = new WatchedListener<I, M, W, L>(watched, listener);
 22  0
                 if (watches.putIfAbsent(item, newWl) != null) continue;
 23  0
                 activate(watched);
 24  0
                 break;
 25  
             }
 26  0
             newWl = oldWl.add(listener);
 27  0
         } while (!watches.replace(item, oldWl, newWl));
 28  0
     }
 29  
 
 30  
     public void remove(I item, L listener) throws IOException {
 31  
         WatchedListener<I, M, W, L> oldWl, newWl;
 32  
         do {
 33  0
             oldWl = watches.get(item);
 34  0
             if (oldWl == null) break;
 35  0
             newWl = oldWl.remove(listener);
 36  0
             if (newWl == oldWl) break;
 37  0
             if (newWl == null) {
 38  0
                 if (!watches.remove(item, oldWl)) continue;
 39  0
                 deactivate(oldWl.watched);
 40  0
                 break;
 41  
             }
 42  0
         } while (!watches.replace(item, oldWl, newWl));
 43  0
     }
 44  
 
 45  
     protected W getWatched(I item) {
 46  0
         WatchedListener<I, M, W, L> wl = watches.get(item);
 47  0
         return wl != null ? wl.watched : null;
 48  
     }
 49  
 
 50  
     protected void fireEvent(I item, Listener.Event event) {
 51  0
         WatchedListener<I, M, W, L> wl = watches.get(item);
 52  0
         if (wl == null) return;
 53  0
         for (L listener: wl.listeners) listener.acceptEvent(item, event);
 54  0
     }
 55  
 
 56  
     protected abstract void activate(W watched) throws IOException;
 57  
     protected abstract void deactivate(W watched) throws IOException;
 58  
     protected abstract W createWatched(I item) throws IOException;
 59  
 
 60  
     public static class WatchedListener<I, M extends AbstractMonitor<I, M, W, L>, W extends Watched<I, M, W, L>, L extends Listener<I>> {
 61  
         protected final W watched;
 62  
         protected final HashSet<L> listeners;
 63  
 
 64  0
         protected WatchedListener(W watched, L listener) throws IOException {
 65  0
             this.watched = watched;
 66  0
             watched.init();
 67  0
             listeners = new HashSet<L>();
 68  0
             listeners.add(listener);
 69  0
         }
 70  
 
 71  0
         protected WatchedListener(W watched, HashSet<L> listeners) {
 72  0
             this.watched = watched;
 73  0
             this.listeners = listeners;
 74  0
         }
 75  
 
 76  
         protected WatchedListener<I, M, W, L> add(L listener) {
 77  0
             if (listeners.contains(listener)) return this;
 78  0
             HashSet<L> newListeners = new HashSet<L>(listeners);
 79  0
             newListeners.add(listener);
 80  0
             return new WatchedListener<I, M, W, L>(watched, newListeners);
 81  
         }
 82  
 
 83  
         protected WatchedListener<I, M, W, L> remove(Listener<I> listener) {
 84  0
             if (!listeners.contains(listener)) return this;
 85  0
             HashSet<L> newListeners = new HashSet<L>(listeners);
 86  0
             newListeners.remove(listener);
 87  0
             if (newListeners.isEmpty()) return null;
 88  0
             return new WatchedListener<I, M, W, L>(watched, newListeners);
 89  
         }
 90  
     }
 91  
 
 92  
     public static abstract class Watched<I, M extends AbstractMonitor<I, M, W, L>, W extends Watched<I, M, W, L>, L extends Listener<I>> {
 93  
         protected final M monitor;
 94  
 
 95  0
         protected Watched(M monitor) {
 96  0
             this.monitor = monitor;
 97  0
         }
 98  
 
 99  
         protected void init() throws IOException {
 100  0
         }
 101  
     }
 102  
 }