• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 // © 2016 and later: Unicode, Inc. and others.
3 // License & terms of use: http://www.unicode.org/copyright.html#License
4 /**
5  *******************************************************************************
6  * Copyright (C) 2001-2009, International Business Machines Corporation and    *
7  * others. All Rights Reserved.                                                *
8  *******************************************************************************
9  */
10 package ohos.global.icu.impl;
11 
12 import java.util.ArrayList;
13 import java.util.EventListener;
14 import java.util.Iterator;
15 import java.util.List;
16 
17 /**
18  * <p>Abstract implementation of a notification facility.  Clients add
19  * EventListeners with addListener and remove them with removeListener.
20  * Notifiers call notifyChanged when they wish to notify listeners.
21  * This queues the listener list on the notification thread, which
22  * eventually dequeues the list and calls notifyListener on each
23  * listener in the list.</p>
24  *
25  * <p>Subclasses override acceptsListener and notifyListener
26  * to add type-safe notification.  AcceptsListener should return
27  * true if the listener is of the appropriate type; ICUNotifier
28  * itself will ensure the listener is non-null and that the
29  * identical listener is not already registered with the Notifier.
30  * NotifyListener should cast the listener to the appropriate
31  * type and call the appropriate method on the listener.
32  * @hide exposed on OHOS
33  */
34 public abstract class ICUNotifier {
35     private final Object notifyLock = new Object();
36     private NotifyThread notifyThread;
37     private List<EventListener> listeners;
38 
39     /**
40      * Add a listener to be notified when notifyChanged is called.
41      * The listener must not be null. AcceptsListener must return
42      * true for the listener.  Attempts to concurrently
43      * register the identical listener more than once will be
44      * silently ignored.
45      */
addListener(EventListener l)46     public void addListener(EventListener l) {
47         if (l == null) {
48             throw new NullPointerException();
49         }
50 
51         if (acceptsListener(l)) {
52             synchronized (notifyLock) {
53                 if (listeners == null) {
54                     listeners = new ArrayList<EventListener>();
55                 } else {
56                     // identity equality check
57                     for (EventListener ll : listeners) {
58                         if (ll == l) {
59                             return;
60                         }
61                     }
62                 }
63 
64                 listeners.add(l);
65             }
66         } else {
67             throw new IllegalStateException("Listener invalid for this notifier.");
68         }
69     }
70 
71     /**
72      * Stop notifying this listener.  The listener must
73      * not be null.  Attempts to remove a listener that is
74      * not registered will be silently ignored.
75      */
removeListener(EventListener l)76     public void removeListener(EventListener l) {
77         if (l == null) {
78             throw new NullPointerException();
79         }
80         synchronized (notifyLock) {
81             if (listeners != null) {
82                 // identity equality check
83                 Iterator<EventListener> iter = listeners.iterator();
84                 while (iter.hasNext()) {
85                     if (iter.next() == l) {
86                         iter.remove();
87                         if (listeners.size() == 0) {
88                             listeners = null;
89                         }
90                         return;
91                     }
92                 }
93             }
94         }
95     }
96 
97     /**
98      * Queue a notification on the notification thread for the current
99      * listeners.  When the thread unqueues the notification, notifyListener
100      * is called on each listener from the notification thread.
101      */
notifyChanged()102     public void notifyChanged() {
103         synchronized (notifyLock) {
104             if (listeners != null) {
105                 if (notifyThread == null) {
106                     notifyThread = new NotifyThread(this);
107                     notifyThread.setDaemon(true);
108                     notifyThread.start();
109                 }
110                 notifyThread.queue(listeners.toArray(new EventListener[listeners.size()]));
111             }
112         }
113     }
114 
115     /**
116      * The notification thread.
117      */
118     private static class NotifyThread extends Thread {
119         private final ICUNotifier notifier;
120         private final List<EventListener[]> queue = new ArrayList<EventListener[]>();
121 
NotifyThread(ICUNotifier notifier)122         NotifyThread(ICUNotifier notifier) {
123             this.notifier = notifier;
124         }
125 
126         /**
127          * Queue the notification on the thread.
128          */
queue(EventListener[] list)129         public void queue(EventListener[] list) {
130             synchronized (this) {
131                 queue.add(list);
132                 notify();
133             }
134         }
135 
136         /**
137          * Wait for a notification to be queued, then notify all
138          * listeners listed in the notification.
139          */
140         @Override
run()141         public void run() {
142             EventListener[] list;
143             while (true) {
144                 try {
145                     synchronized (this) {
146                         while (queue.isEmpty()) {
147                             wait();
148                         }
149                         list = queue.remove(0);
150                     }
151 
152                     for (int i = 0; i < list.length; ++i) {
153                         notifier.notifyListener(list[i]);
154                     }
155                 }
156                 catch (InterruptedException e) {
157                 }
158             }
159         }
160     }
161 
162     /**
163      * Subclasses implement this to return true if the listener is
164      * of the appropriate type.
165      */
acceptsListener(EventListener l)166     protected abstract boolean acceptsListener(EventListener l);
167 
168     /**
169      * Subclasses implement this to notify the listener.
170      */
notifyListener(EventListener l)171     protected abstract void notifyListener(EventListener l);
172 }
173