1   /*
2    * Copyright (c) 2004-2009 QOS.ch All rights reserved.
3    * 
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   * 
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   * 
14   * THE SOFTWARE IS PROVIDED "AS  IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package org.slf4j.ext;
24  
25  import java.io.Serializable;
26  import java.io.ByteArrayInputStream;
27  import java.io.ByteArrayOutputStream;
28  import java.util.Date;
29  import java.util.HashMap;
30  import java.util.Iterator;
31  import java.util.Map;
32  import java.beans.XMLDecoder;
33  import java.beans.XMLEncoder;
34  import java.beans.ExceptionListener;
35  
36  /**
37   * Base class for Event Data. Event Data contains data to be logged about an
38   * event. Users may extend this class for each EventType they want to log.
39   * 
40   * @author Ralph Goers
41   */
42  public class EventData implements Serializable {
43    
44    private static final long serialVersionUID = 153270778642103985L;
45    
46    private Map<String, Object> eventData = new HashMap<String, Object>();
47    public static final String EVENT_MESSAGE = "EventMessage";
48    public static final String EVENT_TYPE = "EventType";
49    public static final String EVENT_DATETIME = "EventDateTime";
50    public static final String EVENT_ID = "EventId";
51  
52    /**
53     * Default Constructor
54     */
55    public EventData() {
56    }
57  
58    /**
59     * Constructor to create event data from a Map.
60     * 
61     * @param map
62     *          The event data.
63     */
64    public EventData(Map<String, Object> map) {
65      eventData.putAll(map);
66    }
67  
68    /**
69     * Construct from a serialized form of the Map containing the RequestInfo
70     * elements
71     * 
72     * @param xml
73     *          The serialized form of the RequestInfo Map.
74     */
75    @SuppressWarnings("unchecked")
76    public EventData(String xml) {
77      ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes());
78      try {
79        XMLDecoder decoder = new XMLDecoder(bais);
80        this.eventData = (Map<String, Object>) decoder.readObject();
81      } catch (Exception e) {
82        throw new EventException("Error decoding " + xml, e);
83      }
84    }
85  
86    /**
87     * Serialize all the EventData items into an XML representation.
88     * 
89     * @return an XML String containing all the EventDAta items.
90     */
91    public String toXML() {
92      return toXML(eventData);
93    }
94  
95    /**
96     * Serialize all the EventData items into an XML representation.
97     * 
98     * @return an XML String containing all the EventDAta items.
99     */
100   public static String toXML(Map<String, Object> map) {
101     ByteArrayOutputStream baos = new ByteArrayOutputStream();
102     try {
103       XMLEncoder encoder = new XMLEncoder(baos);
104       encoder.setExceptionListener(new ExceptionListener() {
105         public void exceptionThrown(Exception exception) {
106           exception.printStackTrace();
107         }
108       });
109       encoder.writeObject(map);
110       encoder.close();
111       return baos.toString();
112     } catch (Exception e) {
113       e.printStackTrace();
114       return null;
115     }
116   }
117 
118   /**
119    * Retrieve the event identifier.
120    * 
121    * @return The event identifier
122    */
123   public String getEventId() {
124     return (String) this.eventData.get(EVENT_ID);
125   }
126 
127   /**
128    * Set the event identifier.
129    * 
130    * @param eventId
131    *          The event identifier.
132    */
133   public void setEventId(String eventId) {
134     if (eventId == null) {
135       throw new IllegalArgumentException("eventId cannot be null");
136     }
137     this.eventData.put(EVENT_ID, eventId);
138   }
139 
140   /**
141    * Retrieve the message text associated with this event, if any.
142    * 
143    * @return The message text associated with this event or null if there is
144    *         none.
145    */
146   public String getMessage() {
147     return (String) this.eventData.get(EVENT_MESSAGE);
148   }
149 
150   /**
151    * Set the message text associated with this event.
152    * 
153    * @param message
154    *          The message text.
155    */
156   public void setMessage(String message) {
157     this.eventData.put(EVENT_MESSAGE, message);
158   }
159 
160   /**
161    * Retrieve the date and time the event occurred.
162    * 
163    * @return The Date associated with the event.
164    */
165   public Date getEventDateTime() {
166     return (Date) this.eventData.get(EVENT_DATETIME);
167   }
168 
169   /**
170    * Set the date and time the event occurred in case it is not the same as when
171    * the event was logged.
172    * 
173    * @param eventDateTime
174    *          The event Date.
175    */
176   public void setEventDateTime(Date eventDateTime) {
177     this.eventData.put(EVENT_DATETIME, eventDateTime);
178   }
179 
180   /**
181    * Set the type of event that occurred.
182    * 
183    * @param eventType
184    *          The type of the event.
185    */
186   public void setEventType(String eventType) {
187     this.eventData.put(EVENT_TYPE, eventType);
188   }
189 
190   /**
191    * Retrieve the type of the event.
192    * 
193    * @return The event type.
194    */
195   public String getEventType() {
196     return (String) this.eventData.get(EVENT_TYPE);
197   }
198 
199   /**
200    * Add arbitrary attributes about the event.
201    * 
202    * @param name
203    *          The attribute's key.
204    * @param obj
205    *          The data associated with the key.
206    */
207   public void put(String name, Serializable obj) {
208     this.eventData.put(name, obj);
209   }
210 
211   /**
212    * Retrieve an event attribute.
213    * 
214    * @param name
215    *          The attribute's key.
216    * @return The value associated with the key or null if the key is not
217    *         present.
218    */
219   public Serializable get(String name) {
220     return (Serializable) this.eventData.get(name);
221   }
222 
223   /**
224    * Populate the event data from a Map.
225    * 
226    * @param data
227    *          The Map to copy.
228    */
229   public void putAll(Map<String, Object> data) {
230     this.eventData.putAll(data);
231   }
232 
233   /**
234    * Returns the number of attributes in the EventData.
235    * 
236    * @return the number of attributes in the EventData.
237    */
238   public int getSize() {
239     return this.eventData.size();
240   }
241 
242   /**
243    * Returns an Iterator over all the entries in the EventDAta.
244    * 
245    * @return an Iterator that can be used to access all the event attributes.
246    */
247   public Iterator<Map.Entry<String, Object>> getEntrySetIterator() {
248     return this.eventData.entrySet().iterator();
249   }
250 
251   /**
252    * Retrieve all the attributes in the EventData as a Map. Changes to this map
253    * will be reflected in the EventData.
254    * 
255    * @return The Map of attributes in this EventData instance.
256    */
257   public Map<String, Object> getEventMap() {
258     return this.eventData;
259   }
260 
261   /**
262    * Convert the EventData to a String.
263    * 
264    * @return The EventData as a String.
265    */
266   @Override
267   public String toString() {
268     return toXML();
269   }
270 
271   /**
272    * Compare two EventData objects for equality.
273    * 
274    * @param o
275    *          The Object to compare.
276    * @return true if the objects are the same instance or contain all the same
277    *         keys and their values.
278    */
279   @SuppressWarnings("unchecked")
280   @Override
281   public boolean equals(Object o) {
282     if (this == o) {
283       return true;
284     }
285     if (!(o instanceof EventData || o instanceof Map)) {
286       return false;
287     }
288     Map<String, Object> map = (o instanceof EventData) ? ((EventData) o)
289         .getEventMap() : (Map<String, Object>) o;
290 
291     return this.eventData.equals(map);
292   }
293 
294   /**
295    * Compute the hashCode for this EventData instance.
296    * 
297    * @return The hashcode for this EventData instance.
298    */
299   @Override
300   public int hashCode() {
301     return this.eventData.hashCode();
302   }
303 }