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 cz.cuni.amis.pogamut.base3d.worldview.object.Location;
5   
6   import java.io.Serializable;
7   import java.util.Calendar;
8   import java.util.logging.Level;
9   import java.util.logging.LogRecord;
10  
11  /**
12   * DON'T USE THIS CLASS! Use methods in {@link LogCategory} to place mark on the map.
13   * <p/>
14   * This is an object that is passed through log infrastructure to appear on the other side
15   * through JMX and it is utilized there to add mark on the map.
16   * <p/>
17   * Basically, if you want to use it directly (DON'T), create LogMapMark using some of
18   * the create*Event method and pass it to log as parameter of log message.
19   * {@code
20   *  // create a mark that with text "text to show in map" that will be
21   *  // shown at the position of agent for its duration of 2secibds.
22   *  logger.info("Text to log" , new Object[]{LogMapMark.createFixedLengthEvent(Level.INFO, "text to show in map", null, 2000)});
23   * }
24   * @author Honza
25   */
26  public class LogMapMark implements Serializable {
27  
28      public enum Type {
29  
30          FIXED_DURATION,
31          START_EVENT,
32          END_EVENT
33      }
34      /**
35       * Generator of unique id. All create* methods are synchronized so you can't
36       * generate two marks with same id.
37       */
38      private static int lastAssignedID = 0;
39      /**
40       * Custom generated id. Start and end mark of variable elngth map mark have same id.
41       */
42      private final int id;
43      /**
44       * What level is this mark? 
45       */
46      private final Level level;
47      /**
48       * text shown by this mark
49       */
50      private final String message;
51      /**
52       * Location, where is mark placed. If null, follow agent.
53       */
54      private final Location location;
55      /**
56       * Timestamp when should mark first appear in the map.
57       */
58      private final long created;
59      /**
60       * For how long should map appear in the map.
61       */
62      private final long duration;
63      /**
64       * Type of mark. There are basically only two types: with fixed duration and
65       * varible length. Mark with variable length starts with START_EVENT and is finished
66       * by END_EVENT.
67       */
68      private Type type;
69  
70      /**
71       * Create new map mark.
72       * @param id unique id of map mark, only start and end mark of same map mark have same id.
73       * @param level what importance is this map mark? User can filter out some levels.
74       * @param message What is the text that should be displayed on the mark?
75       * @param location location, at which map mark should be located. If null, than mark will follow agent.
76       * @param created when should map mark first appear in map
77       * @param duration for how long should map mark be shown in the map.
78       * @param type What type is this mark.
79       */
80      private LogMapMark(int id, Level level, String message, Location location, long created, long duration, Type type) {
81          this.id = id;
82          this.level = level;
83          this.message = message;
84          this.location = location != null ? new Location(location) : null;
85          this.created = created;
86          this.duration = duration;
87          this.type = type;
88      }
89  
90      /**
91       * Create new map mark. For parameters see {@link LogMapMark#LogMapMark(int, java.util.logging.Level, java.lang.String, cz.cuni.amis.pogamut.base3d.worldview.object.Location, long, long, cz.cuni.amis.pogamut.base.utils.logging.marks.LogMapMark.Type)
92       */
93      private LogMapMark(Level level, String message, Location location, long created, long duration, Type type) {
94          this(++lastAssignedID, level, message, location, created, duration, type);
95      }
96  
97      /**
98       * Create mark on the map that will stay there for some time.
99       * @param level level of mark, should be same as the level of carrying {@link LogRecord}
100      * @param message text of map mark
101      * @param location location, at which map mark should be located. If null, than mark will follow agent.
102      * @param duration how long should map mark be shown in the map.
103      * @return
104      */
105     public synchronized static LogMapMark createFixedLengthEvent(Level level, String message, Location location, long duration) {
106         long time = Calendar.getInstance().getTimeInMillis();
107         return new LogMapMark(level, message, location, time, duration, Type.FIXED_DURATION);
108     }
109 
110     /**
111      * Create map mark that appear in the map for certain time and will be always shown
112      * at the current position of agent.
113      * @param level level of mark, should be same as the level of carrying {@link LogRecord}
114      * @param message text of mark 
115      * @param duration how long should be mark shown
116      * @return created mark.
117      */
118     public synchronized static LogMapMark createAgentFixedLengthEvent(Level level, String message, long duration) {
119         long time = Calendar.getInstance().getTimeInMillis();
120         return new LogMapMark(level, message, null, time, duration, Type.FIXED_DURATION);
121     }
122 
123     /**
124      * Create mark that will always be shown at the position of agent.
125      * <p/>
126      * If you don't want to show mark in the map anymore, you have to create 
127      * end mark and pass it to log infrastucture. You can create end mark
128      * by calling {@link LogMapMark#getEndMark()} on the starting mark (the one
129      * returned by this method).
130      * @param level level of mark, should be same as the level of carrying {@link LogRecord}
131      * @param message text to be shown
132      * @return created mark.
133      */
134     public synchronized static LogMapMark createAgentVariableLengthEvent(Level level, String message) {
135         long time = Calendar.getInstance().getTimeInMillis();
136         return new LogMapMark(level, message, null, time, Integer.MAX_VALUE, Type.START_EVENT);
137     }
138 
139     /**
140      * Create starting map mark.
141      * <p/>
142      * In order to end the map mark, create end mark by calling
143      * {@link LogMapMark#getEndMark()} on the starting mark (the one
144      * returned by this method) and pass it to same log as starting mark.
145      * @param message text of mark
146      * @param location location, at which map mark should be located. If null, than mark will follow agent.
147      * @return starting map mark
148      */
149     public synchronized static LogMapMark createVariableLengthEvent(Level level, String message, Location location) {
150         long time = Calendar.getInstance().getTimeInMillis();
151         return new LogMapMark(level, message, location, time, Integer.MAX_VALUE, Type.START_EVENT);
152     }
153 
154     @Override
155     public boolean equals(Object otherObject) {
156         if (this == otherObject) {
157             return true;
158         }
159         if (!(otherObject instanceof LogMapMark)) {
160             return false;
161         }
162 
163         LogMapMark other = (LogMapMark) otherObject;
164 
165         if (this.getId() != other.getId()) {
166             return false;
167         }
168         if (getType() != other.getType()) {
169             return false;
170         }
171         boolean msgEqual = this.getMessage() == null ? other.getMessage() == null : this.getMessage().equals(other.getMessage());
172         if (!msgEqual) {
173             return false;
174         }
175 
176         boolean locEqual = this.getLocation() == null ? other.getLocation() == null : this.getLocation().equals(other.getLocation());
177         if (!locEqual) {
178             return false;
179         }
180         if (getCreated() != other.getCreated()) {
181             return false;
182         }
183         if (getDuration() != other.getDuration()) {
184             return false;
185         }
186 
187         return true;
188     }
189 
190     @Override
191     public int hashCode() {
192         int hash = 5;
193         hash = 71 * hash + (this.message != null ? this.message.hashCode() : 0);
194         hash = 71 * hash + (this.location != null ? this.location.hashCode() : 0);
195         hash = 71 * hash + (int) (this.created ^ (this.created >>> 32));
196         hash = 71 * hash + (int) (this.duration ^ (this.duration >>> 32));
197         return hash;
198     }
199 
200     /**
201      * Get unique id of this map mark
202      * @return id of mark
203      */
204     public int getId() {
205         return id;
206     }
207 
208     /**
209      * Get level of mark, used mainly to send end marks at same level as starting.
210      * @return level of the mark.
211      */
212     public Level getLevel() {
213         return level;
214     }
215 
216     public String getMessage() {
217         return message;
218     }
219 
220     /**
221      * Get location of mark. If location is null, mark is supposed to
222      * follow agent.
223      * @see LogMapMark#getLocation(cz.cuni.amis.pogamut.base3d.worldview.object.Location) 
224      * @return copy of marks location or null.
225      */
226     public Location getLocation() {
227         return location != null ? new Location(location) : null;
228     }
229 
230     /**
231      * Get location, where mark is supposed to be.
232      * <p/>
233      * If marks location is null, return location of entity
234      * @param entityLoc location of agent this map mark belongs to
235      * @return copy of location, where mark is supposed to be.
236      */
237     public Location getLocation(Location entityLoc) {
238         Location markLocation = getLocation();
239         return markLocation != null ? markLocation : new Location(entityLoc);
240     }
241 
242     public long getCreated() {
243         return created;
244     }
245 
246     public long getDuration() {
247         return duration;
248     }
249 
250     public Type getType() {
251         return type;
252     }
253 
254     /**
255      * Get end mark to make some map mark disappear from map.
256      * <p/>
257      * This is method that should be used only by map marks without defined 
258      * duration (starting map marks).
259      * @return end mark to be passed to same log as the starting mark was.
260      */
261     public LogMapMark getEndMark() {
262         if (this.getType() == Type.START_EVENT || this.getType() == Type.END_EVENT) {
263             LogMapMark endMark = new LogMapMark(this.id, this.level, this.message, this.location, this.created, this.duration, Type.END_EVENT);
264             return endMark;
265         } else {
266             throw new IllegalStateException("Mark is not in a state that can be changed to END_EVENT, it is in " + getType());
267         }
268     }
269 }