changing license to BSD, assigning Yahoo copyrights where appropriate
[lwes-java.git] / src / main / java / org / lwes / db / EventTemplateDB.java
blob6fa5322d82d5b039856979aad8101ae2d06f2f96
1 /*======================================================================*
2 * Copyright (c) 2008, Yahoo! Inc. All rights reserved. *
3 * *
4 * Licensed under the New BSD License (the "License"); you may not use *
5 * this file except in compliance with the License. Unless required *
6 * by applicable law or agreed to in writing, software distributed *
7 * under the License is distributed on an "AS IS" BASIS, WITHOUT *
8 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
9 * See the License for the specific language governing permissions and *
10 * limitations under the License. See accompanying LICENSE file. *
11 *======================================================================*/
13 package org.lwes.db;
15 import org.apache.commons.logging.Log;
16 import org.apache.commons.logging.LogFactory;
17 import org.lwes.BaseType;
18 import org.lwes.EventAttributeSizeException;
19 import org.lwes.EventSystemException;
20 import org.lwes.TypeID;
21 import org.lwes.util.IPAddress;
23 import java.io.File;
24 import java.io.InputStream;
25 import java.math.BigInteger;
26 import java.util.Arrays;
27 import java.util.Collections;
28 import java.util.Enumeration;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.TreeMap;
32 import java.util.concurrent.ConcurrentHashMap;
34 /**
35 * Provides type checking for the event system. Also provides a place for
36 * globally accessible information.
38 * @author Anthony Molinaro
39 * @author Michael P. Lum
40 * @author Frank Maritato
42 public class EventTemplateDB {
44 private static transient Log log = LogFactory.getLog(EventTemplateDB.class);
45 /**
46 * the meta event info inherent to every event
48 private static final String META_EVENT_INFO = "MetaEventInfo";
50 /**
51 * esfFile for this event system.
53 private File esfFile = null;
54 private InputStream esfInputStream = null;
56 /**
57 * System Attributes
59 private Map<String, Map<String, BaseType>> events = null;
60 private Map<String, BaseType> knownTypes = null;
61 private Map<String, BaseType> reservedWords = null;
63 /**
64 * This is the EventTemplateDB constructor.
66 public EventTemplateDB() {
67 events = new ConcurrentHashMap<String, Map<String, BaseType>>();
68 knownTypes = new ConcurrentHashMap<String, BaseType>();
69 reservedWords = new ConcurrentHashMap<String, BaseType>();
70 initializeKnownTypes();
73 /**
74 * Sets the Event Specification file for this system
76 * @param anEsfFile the ESF file for this system.
78 public void setESFFile(File anEsfFile) {
79 esfFile = anEsfFile;
82 /**
83 * Gets the ESF file, in case you want to look at it
85 * @return the ESF file used in this system.
87 public File getESFFile() {
88 return esfFile;
91 /**
92 * Sets the Event Specification file as an InputStream
94 * @param esfInputStream the InputStream representing an ESF file
96 public void setESFInputStream(InputStream esfInputStream) {
97 this.esfInputStream = esfInputStream;
101 * Ges the ESF InputStream
103 * @return the ESF InputStream used in the system
105 public InputStream getESFInputStream() {
106 return esfInputStream;
110 * Initializes the EventTemplateDB, assumes that setESFFile() has been
111 * called.
113 * @return true if the EventTemplateDB initializes correctly; false if it
114 * does not. false means the event system is unable to perform validation
116 public synchronized boolean initialize() {
118 * Call the parser to parse the file. Any errors cause the
119 * initialization to fail.
121 ESFParser parser;
122 try {
123 if (getESFInputStream() != null) {
124 parser = new ESFParser(getESFInputStream());
126 else if (getESFFile() != null) {
127 parser = new ESFParser(
128 new java.io.FileInputStream(getESFFile()));
130 else {
131 return false;
134 parser.setEventTemplateDB(this);
135 parser.eventlist();
137 catch (java.io.FileNotFoundException e) {
138 log.warn("File not found ", e);
141 * treat this as just a warning and allow things to continue, this
142 * allows an empty EventTemplateDB to work when type checking is
143 * turned off
146 catch (ParseException e) {
147 log.warn("Parser error in ESF file " + getESFFile(), e);
148 return false;
150 catch (Exception e) {
151 log.error("Error parsing ESF file " + getESFFile(), e);
152 /* catch IO, NPEs and other exceptions but still continue */
153 return false;
156 return true;
160 * Add an Event to the EventTemplateDB
162 * @param anEventName the name of the Event to add
163 * @return true if the event was added, false if it was not
165 public synchronized boolean addEvent(String anEventName) {
166 if (anEventName == null) {
167 return false;
170 try {
171 if (anEventName.equals(META_EVENT_INFO)) {
172 return true;
175 if (events.containsKey(anEventName)) {
176 if (log.isInfoEnabled()) {
177 log.info("Event " + anEventName + " already exists in event DB");
179 return false;
182 Map<String, BaseType> evtHash = new ConcurrentHashMap<String, BaseType>();
183 if (!(reservedWords.isEmpty())) {
184 /* insert reserved words into new event */
185 for (String key : reservedWords.keySet()) {
186 if (key != null) {
187 evtHash.put(key, reservedWords.get(key));
192 events.put(anEventName, evtHash);
194 catch (Exception e) {
195 log.warn("Error adding event to EventTemplateDB", e);
198 return true;
201 public synchronized boolean addEventAttribute(String anEventName,
202 String anAttributeName,
203 String anAttributeType) {
204 return addEventAttribute(anEventName,
205 anAttributeName,
206 anAttributeType,
208 false);
211 public synchronized boolean addEventAttribute(String anEventName,
212 String anAttributeName,
213 String anAttributeType,
214 Integer size,
215 boolean required) {
216 return addEventAttribute(anEventName, anAttributeName, anAttributeType, size, required, null);
220 * Add an attribute to an Event in the EventTemplateDB
222 * @param anEventName the name of the event to add this attribute to
223 * @param anAttributeName the name of the attribute to add
224 * @param anAttributeType the type of the attribute, should be the name of the type
225 * given in the ESF Specification.
226 * @param size The size restriction for this attribute
227 * @param required Is this attribute required
228 * @return true if the attribute can be added, false if it can not.
230 public synchronized boolean addEventAttribute(String anEventName,
231 String anAttributeName,
232 String anAttributeType,
233 Integer size,
234 boolean required,
235 Object defaultValue) {
237 if (anEventName == null || anAttributeName == null || anAttributeType == null) {
238 return false;
241 try {
242 if (anEventName.equals(META_EVENT_INFO)) {
243 if (checkForType(anAttributeType)) {
244 BaseType bt = knownTypes.get(anAttributeType).cloneBaseType();
245 bt.setRequired(required);
246 bt.setSizeRestriction(size);
247 if (defaultValue != null) {
248 bt.setDefaultValue(defaultValue);
250 reservedWords.put(anAttributeName, bt);
251 return true;
253 else {
254 if (log.isInfoEnabled()) {
255 log.info("Meta keyword " + anEventName + "." + anAttributeName +
256 "has unknown type " + anAttributeType + ", skipping");
258 return false;
262 if (reservedWords.containsKey(anEventName)) {
263 if (log.isWarnEnabled()) {
264 log.warn("Unable to add attribute named " + anAttributeName +
265 "as it is a reserved word, skipping");
267 return false;
270 if (events.containsKey(anEventName)) {
271 Map<String, BaseType> evtHash = events.get(anEventName);
272 if (checkForType(anAttributeType)) {
273 BaseType bt = knownTypes.get(anAttributeType).cloneBaseType();
274 bt.setRequired(required);
275 bt.setSizeRestriction(size);
276 if (defaultValue != null) {
277 bt.setDefaultValue(defaultValue);
279 evtHash.put(anAttributeName, bt);
280 return true;
282 else {
283 if (log.isWarnEnabled()) {
284 log.warn("Type " + anAttributeType + " does not exist for " +
285 anAttributeName + ", skipping");
287 return false;
290 else {
291 if (log.isWarnEnabled()) {
292 log.warn("No such event " + anEventName + ", skipping");
294 return false;
297 catch (Exception e) {
298 log.error("Error adding attribute " + anAttributeName + " to " + anEventName, e);
299 return false;
304 * Returns an enumeration of all defined events
306 * @return an enumeration of all defined events
308 public Enumeration<String> getEventNames() {
309 return Collections.enumeration(this.events.keySet());
313 * Returns true if the type given by aTypeName is a valid type in the DB.
315 * @param aTypeName a type name according to the ESF Specification
316 * @return true if the type exists in the DB, false otherwise
318 public boolean checkForType(String aTypeName) {
319 if (aTypeName == null) {
320 return false;
322 return knownTypes.containsKey(aTypeName);
325 public void checkForSize(String eventName,
326 String attributeName,
327 BaseType attributeValue) throws EventAttributeSizeException {
329 if (!attributeValue.getTypeName().startsWith("[L")) {
330 if (log.isDebugEnabled()) {
331 log.debug("value for attribute " + attributeName + " is not an array.");
333 return;
336 Map<String, BaseType> evtMap = events.get(eventName);
337 if (evtMap == null) {
338 log.error("event definition did not exist");
339 return;
341 BaseType attrBaseType = evtMap.get(attributeName);
342 if (attrBaseType == null) {
343 log.error("attribute definition did not exist");
344 return;
347 int sizeToCheck = 0;
348 int size = attrBaseType.getSizeRestriction();
349 Object o = attributeValue.getTypeObject();
350 if (o instanceof short[]) {
351 sizeToCheck = ((short[]) o).length;
353 else if (o instanceof int[]) {
354 sizeToCheck = ((int[]) o).length;
356 else if (o instanceof long[]) {
357 sizeToCheck = ((long[]) o).length;
359 else if (o instanceof boolean[]) {
360 sizeToCheck = ((boolean[]) o).length;
362 else if (o instanceof byte[]) {
363 sizeToCheck = ((byte[]) o).length;
365 else if (o instanceof double[]) {
366 sizeToCheck = ((double[]) o).length;
368 else if (o instanceof float[]) {
369 sizeToCheck = ((float[]) o).length;
371 else if (o instanceof List) {
372 List arr = (List) attributeValue.getTypeObject();
373 sizeToCheck = arr.size();
375 else {
376 throw new EventAttributeSizeException("Cannot determine size for "+attributeName);
378 if (log.isTraceEnabled()) {
379 log.trace("sizeToCheck: " + sizeToCheck + " size: " + size);
381 if (size > 0 && sizeToCheck > size) {
382 throw new EventAttributeSizeException(attributeName, sizeToCheck, size);
387 * Checks to see if an Event exists in the EventTemplateDB
389 * @param anEventName the name of the event to check the existence of
390 * @return true if the event with the name <tt>anEventName</tt> exists in
391 * the EventTemplateDB, false otherwise.
393 public boolean checkForEvent(String anEventName) {
394 if (anEventName == null) {
395 return false;
397 return events.containsKey(anEventName);
401 * Checks to see if an attribute <tt>anAttributeName</tt> exists for the
402 * event <tt>anEventName</tt>
404 * @param anEventName the name of an Event
405 * @param anAttributeName the name of an attribute of Event to check
406 * @return true if the attribute exists as a member of event, false
407 * otherwise
409 public boolean checkForAttribute(String anEventName, String anAttributeName) {
410 if (anEventName == null || anAttributeName == null) {
411 return false;
414 if (checkForEvent(anEventName)) {
415 Map<String, BaseType> evtHash = events.get(anEventName);
416 return evtHash.containsKey(anAttributeName);
418 return false;
422 * Checks to see if the type of an attribute is proper. (i.e. if the given
423 * attribute of the given event has the same type assigned to it as the type
424 * of the given objects value)
426 * @param anEventName the name of an Event.
427 * @param anAttributeName the name of the attribute whose type is being checked
428 * @param anAttributeValue the Object containing the possible value of the attribute.
429 * @return true if the event and attribute exist and if the type of the
430 * attribute matches the type assigned to this attribute in the
431 * EventTemplateDB, false otherwise.
433 public boolean checkTypeForAttribute(String anEventName,
434 String anAttributeName,
435 Object anAttributeValue) {
436 if (anEventName == null || anAttributeName == null || anAttributeValue == null) {
437 return false;
440 if (checkForAttribute(anEventName, anAttributeName)) {
441 Map<String, BaseType> evtHash = events.get(anEventName);
442 Object storedTypeObject = evtHash.get(anAttributeName);
443 byte type1 = ((BaseType) anAttributeValue).getTypeToken();
444 byte type2 = ((BaseType) storedTypeObject).getTypeToken();
445 if (type1 == type2) {
446 return true;
450 return false;
454 * Checks to see if the type of an attribute is proper. (i.e. if the given
455 * attribute of the given event has the same type assigned to it as the type
456 * given)
458 * @param anEventName the name of an Event.
459 * @param anAttributeName the name of the attribute whose type is being checked
460 * @param anAttributeType the String containing the possible type value of the
461 * attribute.
462 * @return true if the event and attribute exist and if the type of the
463 * attribute matches the type assigned to this attribute in the
464 * EventTemplateDB, false otherwise.
466 public boolean checkTypeForAttribute(String anEventName,
467 String anAttributeName, String anAttributeType) {
468 if (anEventName == null || anAttributeName == null || anAttributeType == null) {
469 return false;
472 if (checkForAttribute(anEventName, anAttributeName)) {
473 Map<String, BaseType> evtHash = events.get(anEventName);
474 String storedTypeName = evtHash.get(anAttributeName).getTypeName();
475 if (log.isDebugEnabled()) {
476 log.debug("attr: " +
477 anAttributeName +
478 " stored: " +
479 storedTypeName +
480 " passed in: " +
481 anAttributeType);
483 if (anAttributeType.equals(storedTypeName)) {
484 return true;
488 return false;
492 * Given an Object which is the attribute value of the attribute
493 * <tt>attributeName</tt> of event <tt>eventName</tt>, return the internal
494 * representation (i.e. <tt>BaseType</tt>) of this Object
496 * @param eventName the name of an Event.
497 * @param attributeName the name of an attribute of <tt>eventName</tt>
498 * @param attributeValue the value of the attribute
499 * @return the <tt>BaseType</tt> representation of <tt>attributeValue</tt>
501 public BaseType getBaseTypeForObjectAttribute(String eventName,
502 String attributeName,
503 Object attributeValue) {
504 if (eventName == null || attributeName == null || attributeValue == null) {
505 return null;
508 Map<String, BaseType> evtHash = events.get(eventName);
509 BaseType tmpBaseType = evtHash.get(attributeName);
510 BaseType retBaseType = tmpBaseType.cloneBaseType();
511 retBaseType.setTypeObject(attributeValue);
512 return retBaseType;
516 * Returns the base types for this event
518 * @param eventName
519 * @return a map of event fields to base types
521 public Map<String, BaseType> getBaseTypesForEvent(String eventName) {
522 if (eventName == null) {
523 return null;
526 Map<String, BaseType> map = events.get(eventName);
528 return map == null ? new ConcurrentHashMap<String, BaseType>() : map;
532 * Parses the string representation of an event attribute into the
533 * appropriate objectt.
535 * @param anEventName the name of an Event.
536 * @param anAttributeName the name of the attribute we are parsing
537 * @param stringAttributeValue a string representation of the value of the attribute given by
538 * anAttributeName.
539 * @return the object represented by the string
540 * <tt>stringAttributeValue</tt>
542 public Object parseAttribute(String anEventName, String anAttributeName,
543 String stringAttributeValue) {
544 Object retObject = null;
546 if (anEventName == null || anAttributeName == null || stringAttributeValue == null) {
547 return null;
550 if (log.isTraceEnabled()) {
551 log.trace("parseAttribute: " + anEventName + "." + anAttributeName + "=" +
552 stringAttributeValue);
555 if (checkForAttribute(anEventName, anAttributeName)) {
556 if (log.isTraceEnabled()) {
557 log.trace("parseAttribute: passed first if attribute exists");
560 Map<String, BaseType> evtHash = events.get(anEventName);
561 try {
562 BaseType bt = evtHash.get(anAttributeName);
563 if (bt == null) {
564 throw new EventSystemException("Null BaseType for "
565 + anAttributeName);
568 retObject = bt.parseFromString(stringAttributeValue);
569 if (log.isTraceEnabled()) {
570 log.trace("parseAttribute: parsed " + retObject);
573 catch (EventSystemException btpe) {
574 log.error("Unable to parseAttribute", btpe);
578 if (log.isTraceEnabled()) {
579 log.trace("parseAttribute: returning " + retObject);
581 return retObject;
585 * Returns a HTML rendering of the EventTemplateDB
587 * @return HTML string of the EventTemplateDB
589 public String toHtmlString() {
590 StringBuffer sb = new StringBuffer();
591 sb.append("<table>\n");
592 sb.append("<tr><th>" + META_EVENT_INFO
593 + "</th><th>Type</th><th>Name</th></tr>\n");
594 for (String key : reservedWords.keySet()) {
595 BaseType tv = reservedWords.get(key);
596 String type = tv.getTypeName();
597 sb.append("<tr><td></td><td>").append(type).append("</td><td>").append(key).append("</td></tr>\n");
599 for (String EventKey : events.keySet()) {
600 sb.append("<tr><th>").append(EventKey).append("</th><th>Type</th><th>Name</th></tr>\n");
601 if (EventKey != null) {
602 Map<String, BaseType> event = events.get(EventKey);
603 for (Enumeration<String> att = Collections.enumeration(event.keySet()); att
604 .hasMoreElements();) {
605 String key = att.nextElement();
606 BaseType tv = event.get(key);
607 String type = tv.getTypeName();
608 sb.append("<tr><td></td><td>")
609 .append(type)
610 .append("</td><td>")
611 .append(key).append("</td></tr>\n");
616 sb.append("</table>\n");
617 return sb.toString();
622 * Returns a rather long string Representation of the EventTemplateDB
624 * @return a string Representation of the EventTemplateDB
626 public String toString() {
627 StringBuffer sb = new StringBuffer();
628 sb.append("\n").append(META_EVENT_INFO).append("\n{\n");
629 String[] reservedKeys = new String[reservedWords.size()];
630 int i = 0, j = 0;
632 for (String s1 : reservedWords.keySet()) {
633 reservedKeys[i] = s1;
634 ++i;
636 Arrays.sort(reservedKeys);
638 for (i = 0; i < reservedKeys.length; ++i) {
639 BaseType tv = reservedWords.get(reservedKeys[i]);
640 String type = tv.getTypeName();
641 sb.append("\t").append(type).append(" ").append(reservedKeys[i]).append(";\n");
643 sb.append("}\n");
645 String[] eventKeys = new String[events.size()];
646 i = 0;
647 for (String s : events.keySet()) {
648 eventKeys[i] = s;
649 ++i;
651 Arrays.sort(eventKeys);
653 for (i = 0; i < eventKeys.length; ++i) {
654 sb.append(eventKeys[i]).append("\n{\n");
655 if (eventKeys[i] != null) {
656 Map<String, BaseType> event = events.get(eventKeys[i]);
657 j = 0;
658 String[] attributeKeys = new String[event.size()];
659 for (Enumeration<String> att = Collections.enumeration(event.keySet());
660 att.hasMoreElements();) {
661 attributeKeys[j] = att.nextElement();
662 ++j;
664 Arrays.sort(attributeKeys);
666 for (j = 0; j < attributeKeys.length; ++j) {
667 BaseType tv = event.get(attributeKeys[j]);
668 String type = tv.getTypeName();
669 sb.append("\t").append(type).append(" ").append(attributeKeys[j]).append(";\n");
672 sb.append("}\n");
674 return sb.toString();
677 public String toStringOneLine() {
678 return toString().replace("\n", " ");
682 * Creates a map of known types
684 private void initializeKnownTypes() {
685 /* initialize the list of known types */
686 knownTypes.put(TypeID.UINT16_STRING, new BaseType(TypeID.UINT16_STRING,
687 TypeID.UINT16_TOKEN, 0));
688 knownTypes.put(TypeID.INT16_STRING, new BaseType(TypeID.INT16_STRING,
689 TypeID.INT16_TOKEN, (short) 0));
690 knownTypes.put(TypeID.UINT32_STRING, new BaseType(TypeID.UINT32_STRING,
691 TypeID.UINT32_TOKEN, (long) 0));
692 knownTypes.put(TypeID.INT32_STRING, new BaseType(TypeID.INT32_STRING,
693 TypeID.INT32_TOKEN, 0));
694 knownTypes.put(TypeID.STRING_STRING, new BaseType(TypeID.STRING_STRING,
695 TypeID.STRING_TOKEN, ""));
696 knownTypes.put(TypeID.IPADDR_STRING, new BaseType(TypeID.IPADDR_STRING,
697 TypeID.IPADDR_TOKEN, new IPAddress()));
698 knownTypes.put(TypeID.INT64_STRING, new BaseType(TypeID.INT64_STRING,
699 TypeID.INT64_TOKEN, (long) 0));
700 knownTypes.put(TypeID.UINT64_STRING, new BaseType(TypeID.UINT64_STRING,
701 TypeID.UINT64_TOKEN, BigInteger.ZERO));
702 knownTypes.put(TypeID.BOOLEAN_STRING, new BaseType(TypeID.BOOLEAN_STRING,
703 TypeID.BOOLEAN_TOKEN, true));
704 knownTypes.put(TypeID.STRING_ARRAY_STRING,
705 new BaseType(TypeID.STRING_ARRAY_STRING,
706 TypeID.STRING_ARRAY_TOKEN, null));
707 knownTypes.put(TypeID.INT16_ARRAY_STRING,
708 new BaseType(TypeID.INT16_ARRAY_STRING,
709 TypeID.INT16_ARRAY_TOKEN, null));
710 knownTypes.put(TypeID.INT32_ARRAY_STRING,
711 new BaseType(TypeID.INT32_ARRAY_STRING,
712 TypeID.INT32_ARRAY_TOKEN, null));
713 knownTypes.put(TypeID.INT64_ARRAY_STRING,
714 new BaseType(TypeID.INT64_ARRAY_STRING,
715 TypeID.INT64_ARRAY_TOKEN, null));
716 knownTypes.put(TypeID.UINT16_ARRAY_STRING,
717 new BaseType(TypeID.UINT16_ARRAY_STRING,
718 TypeID.UINT16_ARRAY_TOKEN, null));
719 knownTypes.put(TypeID.UINT32_ARRAY_STRING,
720 new BaseType(TypeID.UINT32_ARRAY_STRING,
721 TypeID.UINT32_ARRAY_TOKEN, null));
722 knownTypes.put(TypeID.UINT64_ARRAY_STRING,
723 new BaseType(TypeID.UINT64_ARRAY_STRING,
724 TypeID.UINT64_ARRAY_TOKEN, null));
725 knownTypes.put(TypeID.BOOLEAN_ARRAY_STRING,
726 new BaseType(TypeID.BOOLEAN_ARRAY_STRING,
727 TypeID.BOOLEAN_ARRAY_TOKEN, null));
728 knownTypes.put(TypeID.BYTE_ARRAY_STRING,
729 new BaseType(TypeID.BYTE_ARRAY_STRING,
730 TypeID.BYTE_ARRAY_TOKEN, null));
731 knownTypes.put(TypeID.DOUBLE_ARRAY_STRING,
732 new BaseType(TypeID.DOUBLE_ARRAY_STRING,
733 TypeID.DOUBLE_ARRAY_TOKEN, null));
734 knownTypes.put(TypeID.FLOAT_ARRAY_STRING,
735 new BaseType(TypeID.FLOAT_ARRAY_STRING,
736 TypeID.FLOAT_ARRAY_TOKEN, null));
737 knownTypes.put(TypeID.DOUBLE_STRING,
738 new BaseType(TypeID.DOUBLE_STRING,
739 TypeID.DOUBLE_TOKEN, null));
740 knownTypes.put(TypeID.FLOAT_STRING,
741 new BaseType(TypeID.FLOAT_STRING,
742 TypeID.FLOAT_TOKEN, null));
743 knownTypes.put(TypeID.IPV4_STRING,
744 new BaseType(TypeID.IPV4_STRING,
745 TypeID.IPV4_TOKEN, null));
746 knownTypes.put(TypeID.IPV4_ARRAY_STRING,
747 new BaseType(TypeID.IPV4_ARRAY_STRING,
748 TypeID.IPV4_ARRAY_TOKEN, null));
751 public Map<String, BaseType> getMetaFields() {
752 Map<String, BaseType> m = new TreeMap<String, BaseType>();
753 m.putAll(reservedWords);
754 return m;
757 public Map<String, Map<String, BaseType>> getEvents() {
758 Map<String, Map<String, BaseType>> cp = new TreeMap<String, Map<String, BaseType>>();
759 cp.putAll(events);
760 return cp;