##### 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

     }