##### Coverage Report - org.apache.commons.configuration.event.EventSource

Classes in this File | Line Coverage | Branch Coverage | Complexity
EventSource |
92% | 34/37
100% | 6/6
| 1.6666666666666667;1,667

1 |  |
     /*
2 |  |
      * Licensed to the Apache Software Foundation (ASF) under one or more
3 |  |
      * contributor license agreements.  See the NOTICE file distributed with
4 |  |
      * this work for additional information regarding copyright ownership.
5 |  |
      * The ASF licenses this file to You under the Apache License, Version 2.0
6 |  |
      * (the "License"); you may not use this file except in compliance with
7 |  |
      * the License.  You may obtain a copy of the License at
8 |  |
      *
9 |  |
      *     http://www.apache.org/licenses/LICENSE-2.0
10 |  |
      *
11 |  |
      * Unless required by applicable law or agreed to in writing, software
12 |  |
      * distributed under the License is distributed on an "AS IS" BASIS,
13 |  |
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 |  |
      * See the License for the specific language governing permissions and
15 |  |
      * limitations under the License.
16 |  |
      */
17 |  |
     package org.apache.commons.configuration.event;
18 |  |
19 |  |
     import java.util.ArrayList;
20 |  |
     import java.util.Collection;
21 |  |
     import java.util.Collections;
22 |  |
     import java.util.Iterator;
23 |  |
     import java.util.LinkedList;
24 |  |
25 |  |
     /**
26 |  |
      * <p>
27 |  |
      * A base class for objects that can generate configuration events.
28 |  |
      * </p>
29 |  |
      * <p>
30 |  |
      * This class implements functionality for managing a set of event listeners
31 |  |
      * that can be notified when an event occurs. It can be extended by
32 |  |
      * configuration classes that support the event machanism. In this case these
33 |  |
      * classes only need to call the <code>fireEvent()</code> method when an event
34 |  |
      * is to be delivered to the registered listeners.
35 |  |
      * </p>
36 |  |
      * <p>
37 |  |
      * Adding and removing event listeners can happen concurrently to manipulations
38 |  |
      * on a configuration that cause events. The operations are synchronized.
39 |  |
      * </p>
40 |  |
      * <p>
41 |  |
      * With the <code>detailEvents</code> property the number of detail events can
42 |  |
      * be controlled. Some methods in configuration classes are implemented in a way
43 |  |
      * that they call other methods that can generate their own events. One example
44 |  |
      * is the <code>setProperty()</code> method that can be implemented as a
45 |  |
      * combination of <code>clearProperty()</code> and <code>addProperty()</code>.
46 |  |
      * With <code>detailEvents</code> set to <b>true</b>, all involved methods
47 |  |
      * will generate events (i.e. listeners will receive property set events,
48 |  |
      * property clear events, and property add events). If this mode is turned off
49 |  |
      * (which is the default), detail events are suppressed, so only property set
50 |  |
      * events will be received. Note that the number of received detail events may
51 |  |
      * differ for different configuration implementations.
52 |  |
      * <code>{@link org.apache.commons.configuration.HierarchicalConfiguration HierarchicalConfiguration}</code>
53 |  |
      * for instance has a custom implementation of <code>setProperty()</code>, which
54 |  |
      * does not generate any detail events.
55 |  |
      * </p>
56 |  |
      *
57 |  |
      * @author <a
58 |  |
      * href="http://jakarta.apache.org/commons/configuration/team-list.html">Commons
59 |  |
      * Configuration team</a>
60 |  |
      * @version $Id: EventSource.java 439648 2006-09-02 20:42:10Z oheger $
61 |  |
      * @since 1.3
62 |  |
      */
63 |  |
     public class EventSource
64 |  |
     {
65 |  |
         /** A collection for the registered event listeners. */
66 |  |
         private Collection listeners;
67 |  |
68 |  |
         /** A counter for the detail events. */
69 |  |
         private int detailEvents;
70 |  |
71 |  |
         /**
72 |  |
          * Creates a new instance of <code>EventSource</code>.
73 |  |
          */
74 |  |
         public EventSource()
75 | 2258 |
         {
76 | 2258 |
             clearConfigurationListeners();
77 | 2258 |
         }
78 |  |
79 |  |
         /**
80 |  |
          * Adds a configuration listener to this object.
81 |  |
          *
82 |  |
          * @param l the listener to add
83 |  |
          */
84 |  |
         public void addConfigurationListener(ConfigurationListener l)
85 |  |
         {
86 | 1317 |
             if (l == null)
87 |  |
             {
88 | 1 |
                 throw new IllegalArgumentException("Listener must not be null!");
89 |  |
             }
90 | 1316 |
             synchronized (listeners)
91 |  |
             {
92 | 1316 |
                 listeners.add(l);
93 | 1316 |
             }
94 | 1316 |
         }
95 |  |
96 |  |
         /**
97 |  |
          * Removes the specified event listener so that it does not receive any
98 |  |
          * further events caused by this object.
99 |  |
          *
100 |  |
          * @param l the listener to be removed
101 |  |
          * @return a flag whether the event listener was found
102 |  |
          */
103 |  |
         public boolean removeConfigurationListener(ConfigurationListener l)
104 |  |
         {
105 | 380 |
             synchronized (listeners)
106 |  |
             {
107 | 380 |
                 return listeners.remove(l);
108 | 0 |
             }
109 |  |
         }
110 |  |
111 |  |
         /**
112 |  |
          * Returns a collection with all configuration event listeners that are
113 |  |
          * currently registered at this object.
114 |  |
          *
115 |  |
          * @return a collection with the registered
116 |  |
          * <code>ConfigurationListener</code>s (this collection cannot be
117 |  |
          * changed)
118 |  |
          */
119 |  |
         public Collection getConfigurationListeners()
120 |  |
         {
121 | 26 |
             synchronized (listeners)
122 |  |
             {
123 | 26 |
                 return Collections.unmodifiableCollection(listeners);
124 | 0 |
             }
125 |  |
         }
126 |  |
127 |  |
         /**
128 |  |
          * Removes all registered configuration listeners.
129 |  |
          */
130 |  |
         public void clearConfigurationListeners()
131 |  |
         {
132 | 2281 |
             listeners = new LinkedList();
133 | 2281 |
         }
134 |  |
135 |  |
         /**
136 |  |
          * Returns a flag whether detail events are enabled.
137 |  |
          *
138 |  |
          * @return a flag if detail events are generated
139 |  |
          */
140 |  |
         public boolean isDetailEvents()
141 |  |
         {
142 | 4 |
             synchronized (listeners)
143 |  |
             {
144 | 4 |
                 return detailEvents > 0;
145 | 0 |
             }
146 |  |
         }
147 |  |
148 |  |
         /**
149 |  |
          * Determines whether detail events should be generated. If enabled, some
150 |  |
          * methods can generate multiple update events. Note that this method
151 |  |
          * records the number of calls, i.e. if for instance
152 |  |
          * <code>setDetailEvents(false)</code> was called three times, you will
153 |  |
          * have to invoke the method as often to enable the details.
154 |  |
          *
155 |  |
          * @param enable a flag if detail events should be enabled or disabled
156 |  |
          */
157 |  |
         public void setDetailEvents(boolean enable)
158 |  |
         {
159 | 4491 |
             synchronized (listeners)
160 |  |
             {
161 | 4491 |
                 if (enable)
162 |  |
                 {
163 | 2254 |
                     detailEvents++;
164 |  |
                 }
165 |  |
                 else
166 |  |
                 {
167 | 2237 |
                     detailEvents--;
168 |  |
                 }
169 | 4491 |
             }
170 | 4491 |
         }
171 |  |
172 |  |
         /**
173 |  |
          * Creates an event object and delivers it to all registered event
174 |  |
          * listeners. The method will check first if sending an event is allowed
175 |  |
          * (making use of the <code>detailEvents</code> property), and if
176 |  |
          * listeners are registered.
177 |  |
          *
178 |  |
          * @param type the event's type
179 |  |
          * @param propName the name of the affected property (can be <b>null</b>)
180 |  |
          * @param propValue the value of the affected property (can be <b>null</b>)
181 |  |
          * @param before the before update flag
182 |  |
          */
183 |  |
         protected void fireEvent(int type, String propName, Object propValue,
184 |  |
                 boolean before)
185 |  |
         {
186 | 79475 |
             Collection listenersToCall = null;
187 |  |
188 | 79475 |
             synchronized (listeners)
189 |  |
             {
190 | 79475 |
                 if (detailEvents >= 0 && listeners.size() > 0)
191 |  |
                 {
192 |  |
                     // Copy listeners to another collection so that manipulating
193 |  |
                     // the listener list during event delivery won't cause problems
194 | 469 |
                     listenersToCall = new ArrayList(listeners);
195 |  |
                 }
196 | 79475 |
             }
197 |  |
198 | 79475 |
             if (listenersToCall != null)
199 |  |
             {
200 | 469 |
                 ConfigurationEvent event = createEvent(type, propName, propValue,
201 |  |
                         before);
202 | 1440 |
                 for (Iterator it = listenersToCall.iterator(); it.hasNext();)
203 |  |
                 {
204 | 502 |
                     ((ConfigurationListener) it.next()).configurationChanged(event);
205 |  |
                 }
206 |  |
             }
207 | 79475 |
         }
208 |  |
209 |  |
         /**
210 |  |
          * Creates a <code>ConfigurationEvent</code> object based on the passed in
211 |  |
          * parameters. This is called by <code>fireEvent()</code> if it decides
212 |  |
          * that an event needs to be generated.
213 |  |
          *
214 |  |
          * @param type the event's type
215 |  |
          * @param propName the name of the affected property (can be <b>null</b>)
216 |  |
          * @param propValue the value of the affected property (can be <b>null</b>)
217 |  |
          * @param before the before update flag
218 |  |
          * @return the newly created event object
219 |  |
          */
220 |  |
         protected ConfigurationEvent createEvent(int type, String propName,
221 |  |
                 Object propValue, boolean before)
222 |  |
         {
223 | 469 |
             return new ConfigurationEvent(this, type, propName, propValue, before);
224 |  |
         }
225 |  |
     }