View Javadoc

1   package cz.cuni.amis.pogamut.base.utils.logging.marks;
2   
3   import cz.cuni.amis.pogamut.base.utils.logging.LogCategory;
4   import java.io.Serializable;
5   import java.util.Calendar;
6   import java.util.logging.Level;
7   import java.util.logging.LogRecord;
8   
9   /**
10   * DO NOT USE THIS CLASS!! Use methods in {@link LogCategory} to add events to the log.
11   * <p/>
12   * This class is special parameter of the {@link LogRecord} that means some
13   * kind of event has happend to the agent. The handler of log records can do some
14   * nifty stuff when he finds this object as parameter of {@link LogRecord},
15   * like showing in some GUI.
16   * <p/>
17   * Under normal circumstances, you create new mark using one of create* methods,
18   * pass it as parameter of some log message, it gets transfered (probably through JMX)
19   * to some handler on the other side (in our particular case to Netbeans plugin
20   * and timeline), where some handler will look for {@link LogRecord LogRecords}
21   * with this object as one of parameters and when it finds it, it shows the mark
22   * in some GUI.
23   * {@code
24   *  // create an event that with text "Text of event for GUI" that will be
25   *  // shown for duration of 2 seconds.
26   *  logger.info("Text of event for text logger" , new Object[]{LogEventMark.createFixedLengthEvent(Level.INFO, "Text of event for GUI", null, 2000)});
27   * }
28   *
29   * @see LogMapMark
30   * @author Honza
31   */
32  public class LogEventMark implements Serializable {
33  
34      /**
35       * Type of {@link LogEventMark}. 
36       */
37      public enum Type {
38  
39          /**
40           * Single time event. Event of this type has no duration,
41           * <p/>
42           * Example: I have died.
43           */
44          SINGLE_EVENT,
45          /**
46           * Event that lasts for certain specified duration.
47           * <p/>
48           * Example: Item taken, won't spawn for 32 seconds
49           */
50          FIXED_DURATION,
51          /**
52           * Used as start mark of event that has variable duration. This ends
53           * only when corresponding end event is send.
54           * <p/>
55           * Example: bot has been hurt, start event "bot is low on health"
56           */
57          START_EVENT,
58          /**
59           * End mark of event with variable duration, shoudn't be created directly,
60           * but through {@link LogEventMark#getEndMark() }
61           * Example: bot picked health pack, end event "bot is low on health"
62           */
63          END_EVENT
64      }
65      /**
66       * Generator of unique id. All create* methods are synchronized so you can't
67       * generate two marks with same id.
68       */
69      private static int lastAssignedID = 0;
70      /**
71       * Unique id of event. Start and end marks of same event have same id.
72       */
73      private final int id;
74      /**
75       * Level of event.
76       */
77      private final Level level;
78      /**
79       * Text of event.
80       */
81      private final String text;
82      /**
83       * Timestamp for when the event has started. In ms since epoch.
84       */
85      private final long time;
86      /**
87       * How long should event last, in ms.
88       */
89      private final long duration;
90      /**
91       * Type of event.
92       */
93      private Type type;
94  
95      /**
96       * Create new log event mark. For use of create* methods.
97       * @param id unique id of log event, only start and end marks of same event can have same id.
98       * @param level how important is this log event
99       * @param text text of event
100      * @param time when should event start, in ms since epoch
101      * @param duration how long should event last.
102      * @param type what is type of mark.
103      */
104     private LogEventMark(int id, Level level, String text, long time, long duration, Type type) {
105         this.id = id;
106         this.level = level;
107         this.text = text;
108         this.time = time;
109         this.duration = duration;
110         this.type = type;
111     }
112 
113     /**
114      * Create new log event mark. Create id from {@link LogEventMark#lastAssignedID} 
115      * and set start time of event from from {@link Calendar#getTimeInMillis() }.
116      * Basically wrapper for {@link LogEventMark#LogEventMark(int, java.lang.String, long, long, cz.cuni.amis.pogamut.base.utils.logging.marks.LogEventMark.Type) }.
117      * @param level how important is this log event
118      * @param text text of event
119      * @param duration how long should event last.
120      * @param type what is type of mark.
121      */
122     private LogEventMark(Level level, String text, long duration, Type type) {
123         this(++lastAssignedID, level, text, Calendar.getInstance().getTimeInMillis(), duration, type);
124     }
125 
126     /**
127      * Create single event. Such event has no duration.
128      * @param level level of log event, should be same as carrying {@link LogRecord}.
129      * @param text text of single event
130      * @return created single event.
131      */
132     public static synchronized LogEventMark createSingleLengthEvent(Level level, String text) {
133         return new LogEventMark(level, text, 0, Type.SINGLE_EVENT);
134     }
135 
136     /**
137      * Create log event that will last for some time.
138      * @param level level of log event, should be same as carrying {@link LogRecord}.
139      * @param text Text of event
140      * @param duration how long should event last.
141      */
142     public static synchronized LogEventMark createFixedLengthEvent(Level level, String text, long duration) {
143         return new LogEventMark(level, text, duration, Type.FIXED_DURATION);
144     }
145 
146     /**
147      * Create log event that will last until notified it should stop.
148      * In order to stop the event, create end mark of event using
149      * {@link LogEventMark#getEndMark() }.
150      * @param level level of log event, should be same as carrying {@link LogRecord}.
151      * @param text text of event.
152      * @return created event.
153      */
154     public static synchronized LogEventMark createVariableLengthEvent(Level level, String text) {
155         return new LogEventMark(level, text, Integer.MAX_VALUE, Type.START_EVENT);
156     }
157 
158     /**
159      * Get human readable representation of LogEventMark.
160      */
161     @Override
162     public String toString() {
163         return getClass().getSimpleName() + " " + getText();
164     }
165 
166     /**
167      * Get unique id of event. Start and end marks of variable event have 
168      * same id, because they mark same event.
169      */
170     public int getId() {
171         return id;
172     }
173 
174     /**
175      * What is level of this event?
176      * @return level of event.
177      */
178     public Level getLevel() {
179         return level;
180     }
181 
182     /**
183      * @return the message of this event
184      */
185     public String getText() {
186         return text;
187     }
188 
189     /**
190      * @return when does event start
191      */
192     public long getTime() {
193         return time;
194     }
195 
196     /**
197      * @return the type of event
198      */
199     public Type getType() {
200         return type;
201     }
202 
203     /**
204      * @return the duration of event. 0 for single event, Integer.MAX_VALUE for variable length event
205      */
206     public long getDuration() {
207         return duration;
208     }
209 
210     /**
211      * Get ending mark for variable length event.
212      * @return if this mark is {@link Type#START_EVENT start mark}, create new end mark,
213      *         if this mark is {@link Type#END_EVENT end mark}, return this mark (since we already are end mark).
214      * @throws IllegalStateException if {@link Type type} of mark is not 
215      *         {@link Type#START_EVENT start} or {@link Type#END_EVENT end}.
216      */
217     public LogEventMark getEndMark() {
218         switch (getType()) {
219             case START_EVENT:
220                 return new LogEventMark(this.id, this.level, this.text, this.time, this.duration, Type.END_EVENT);
221             case END_EVENT:
222                 return this;
223             default:
224                 throw new IllegalStateException("Unexpected type of mark: " + getType());
225         }
226     }
227 
228     @Override
229     public boolean equals(Object otherObject) {
230         if (this == otherObject) {
231             return true;
232         }
233         if (!(otherObject instanceof LogEventMark)) {
234             return false;
235         }
236 
237         LogEventMark other = (LogEventMark) otherObject;
238 
239         if (getId() != other.getId()) {
240             return false;
241         }
242         if (!getLevel().equals(other.getLevel())) {
243             return false;
244         }
245         boolean textEqual = getText() == null ? other.getText() == null : getText().equals(other.getText());
246         if (!textEqual) {
247             return false;
248         }
249         if (getTime() != other.getTime()) {
250             return false;
251         }
252         if (getDuration() != other.getDuration()) {
253             return false;
254         }
255         if (getType() != other.getType()) {
256             return false;
257         }
258 
259         return true;
260     }
261 
262     @Override
263     public int hashCode() {
264         int hash = 7;
265         hash = 67 * hash + this.id;
266         hash = 67 * hash + (this.level != null ? this.level.hashCode() : 0);
267         hash = 67 * hash + (this.text != null ? this.text.hashCode() : 0);
268         hash = 67 * hash + (int) (this.time ^ (this.time >>> 32));
269         hash = 67 * hash + (int) (this.duration ^ (this.duration >>> 32));
270         return hash;
271     }
272 }