001package org.javasimon.callback;
002
003import org.javasimon.Counter;
004import org.javasimon.CounterSample;
005import org.javasimon.Manager;
006import org.javasimon.Simon;
007import org.javasimon.Split;
008import org.javasimon.Stopwatch;
009import org.javasimon.StopwatchSample;
010
011import java.util.HashMap;
012import java.util.Map;
013
014/**
015 * Callback processes various events of the Java Simon API and is used as an extension point of the API.
016 * Callbacks can be registered with the {@link org.javasimon.Manager} using its {@link CompositeCallback}
017 * that can be obtained by calling {@link org.javasimon.Manager#callback()}. After adding the callback
018 * into the main composite callback (or anywhere lower into the callback tree) by calling
019 * {@link CompositeCallback#addCallback(Callback)} all events are propagated to all Callbacks (unless filtered
020 * using {@link FilterCallback}). Methods called on various events are named {@code onEventXY} with type of the source
021 * clearly mentioned in the name (Manager, Simon, Stopwatch, Counter).
022 * <p/>
023 * Callbacks can be configured via Manager configuration facility. (Configuration part is still rather WIP.)
024 * <p/>
025 * Callback can have a lifecycle supported with methods {@link #initialize(Manager)} and {@link #cleanup()}.
026 * Callback is initialized when it is attached to the manager (anywhere in the callback tree) and
027 * deinitialized when the callback is removed from the callback tree.
028 *
029 * @author <a href="mailto:virgo47@gmail.com">Richard "Virgo" Richter</a>
030 */
031public interface Callback {
032
033        /** Lifecycle method called when the callback is added to a manager. */
034        void initialize(Manager manager);
035
036        /**
037         * Lifecycle method called when the callback is removed from the manager. It should implement
038         * any necessary cleanup or resources - e.g. release JDBC connection if one was used for Callback
039         * functionality.
040         * <p/>
041         * <b>It is important to realize that this method is not guaranteed to be called for all callbacks, only for
042         * callbacks removed from Manager's callback tree.</b>
043         */
044        void cleanup();
045
046        /**
047         * Stopwatch start event. <b>Duration of all callbacks is included into the split time!</b>
048         * {@link StopwatchSample} valid for the moment after the start is provided because the callback
049         * is executed out of synchronized block.
050         * It is guaranteed that {@link org.javasimon.Split#getStopwatch()} will not return {@code null}.
051         *
052         * @param split started Split
053         */
054        void onStopwatchStart(Split split);
055
056        /**
057         * Stopwatch stop event. This action is executed after the split time is calculated and does not
058         * affect the measuring. {@link StopwatchSample} valid for the moment after the stop is provided
059         * because the callback is executed out of synchronized block.
060         * It is guaranteed that {@link org.javasimon.Split#getStopwatch()} will not return {@code null}.
061         *
062         * @param split stopped Split
063         * @param sample stopwatch sampled after the stop
064         */
065        void onStopwatchStop(Split split, StopwatchSample sample);
066
067        /**
068         * Stopwatch add split event. {@link StopwatchSample} valid for the moment after the add is provided
069         * because the callback is executed out of synchronized block.
070         * It is guaranteed that {@link org.javasimon.Split#getStopwatch()} will not return {@code null}.
071         *
072         * @param stopwatch modified Stopwatch
073         * @param split added split object
074         * @param sample stopwatch sampled after the add
075         * @since 3.1
076         */
077        void onStopwatchAdd(Stopwatch stopwatch, Split split, StopwatchSample sample);
078
079        /**
080         * Counter decrease event. {@link CounterSample} valid for the moment after the operation is provided
081         * because the callback is executed out of synchronized block.
082         *
083         * @param counter modified Counter
084         * @param dec decrement amount
085         * @param sample counter sampled after the operation
086         */
087        void onCounterDecrease(Counter counter, long dec, CounterSample sample);
088
089        /**
090         * Counter increase event. {@link CounterSample} valid for the moment after the operation is provided
091         * because the callback is executed out of synchronized block.
092         *
093         * @param counter modified Counter
094         * @param inc increment amount
095         * @param sample counter sampled after the operation
096         */
097        void onCounterIncrease(Counter counter, long inc, CounterSample sample);
098
099        /**
100         * Counter set event. {@link CounterSample} valid for the moment after the operation is provided
101         * because the callback is executed out of synchronized block.
102         *
103         * @param counter modified Counter
104         * @param val new value
105         * @param sample counter sampled after the operation
106         */
107        void onCounterSet(Counter counter, long val, CounterSample sample);
108
109        /**
110         * Simon created event is called when Simon is successfully created by the Manager.
111         * <b>Runs within the block synchronized on the Manager</b> - this results in high consistency, but it also
112         * means that <b>implementations of this method should not take much time.</b>
113         *
114         * @param simon created Simon
115         */
116        void onSimonCreated(Simon simon);
117
118        /**
119         * Simon destroyed event is called when Simon is successfully destroyed by the Manager.
120         * <b>Runs within the block synchronized on the Manager</b> - this results in high consistency, but it also
121         * means that <b>implementations of this method should not take much time.</b>
122         *
123         * @param simon destroyed Simon
124         */
125        void onSimonDestroyed(Simon simon);
126
127        /**
128         * Event called when the manager is cleared.
129         * <b>Runs within the block synchronized on the Manager</b> - this results in high consistency, but it also
130         * means that <b>implementations of this method should not take much time.</b>
131         */
132        void onManagerClear();
133
134        /**
135         * Message event is used to propagate arbitrary messages from the manager, or it can
136         * be used by the other Callback methods internally.
137         *
138         * @param message message text
139         */
140        void onManagerMessage(String message);
141
142        /**
143         * Warning event containing warning and/or cause.
144         *
145         * @param warning arbitrary warning message - can be {@code null}, unless concrete implementation states otherwise
146         * @param cause exception causing this warning - can be {@code null}, unless concrete implementation states otherwise
147         */
148        void onManagerWarning(String warning, Exception cause);
149
150        /**
151         * Enumeration of all supported callback actions. {@link #ALL} is meta-action usable in
152         * configurations meaning that the configuration entry applies to all actions (any action).
153         * In callback configuration action names in lowercase and with _ replaced for - can be
154         * used (e.g. "counter-increase" instead for {@link #COUNTER_INCREASE}.
155         * <p/>
156         * Event codes are used for configuration purposes instead of enum literals.
157         */
158        enum Event {
159                /** Meta-action designating all actions (or any action in rules). */
160                ALL("all"),
161
162                /** Start of the stopwatch. */
163                STOPWATCH_START("start"),
164
165                /** Stop of the stopwatch. */
166                STOPWATCH_STOP("stop"),
167
168                /** Adding value to the stopwatch. */
169                STOPWATCH_ADD("add"),
170
171                /** Counter increased. */
172                COUNTER_INCREASE("increase"),
173
174                /** Counter decreased. */
175                COUNTER_DECREASE("decrease"),
176
177                /** Counter set to arbitrary value. */
178                COUNTER_SET("set"),
179
180                /** Creation of a Simon. */
181                CREATED("created"),
182
183                /** Removing of a Simon. */
184                DESTROYED("destroyed"),
185
186                /** Clearing of the manager. */
187                MANAGER_CLEAR("clearManager"),
188
189                /** Event producing arbitrary message. */
190                MESSAGE("message"),
191
192                /** Warning related to the manager. */
193                WARNING("warning");
194
195                private static Map<String, Event> codeValues = new HashMap<>();
196
197                private String code;
198
199                static {
200                        for (Event value : values()) {
201                                codeValues.put(value.code.toLowerCase(), value);
202                        }
203                }
204
205                /**
206                 * Constructor of the event with its code.
207                 *
208                 * @param code code of the event
209                 */
210                Event(String code) {
211                        this.code = code;
212                }
213
214                /**
215                 * Returns event for String code used in XML configuration.
216                 *
217                 * @param code String code
218                 * @return Event object
219                 */
220                public static Event forCode(String code) {
221                        return codeValues.get(code.toLowerCase());
222                }
223        }
224}