check point for arrays as Lists and new data types
[lwes-java.git] / src / main / java / org / lwes / db / EventTemplateDB.java
blobc0352621b4583b92f4133929bef7d487bc3c2960
1 package org.lwes.db;
3 import org.apache.commons.logging.Log;
4 import org.apache.commons.logging.LogFactory;
5 import org.lwes.BaseType;
6 import org.lwes.EventAttributeSizeException;
7 import org.lwes.EventSystemException;
8 import org.lwes.TypeID;
9 import org.lwes.util.IPAddress;
11 import java.io.File;
12 import java.io.InputStream;
13 import java.math.BigInteger;
14 import java.util.Arrays;
15 import java.util.Collections;
16 import java.util.Enumeration;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.TreeMap;
20 import java.util.concurrent.ConcurrentHashMap;
22 /**
23 * Provides type checking for the event system. Also provides a place for
24 * globally accessible information.
26 * @author Anthony Molinaro
27 * @author Michael P. Lum
28 * @author Frank Maritato
30 public class EventTemplateDB {
32 private static transient Log log = LogFactory.getLog(EventTemplateDB.class);
33 /**
34 * the meta event info inherent to every event
36 private static final String META_EVENT_INFO = "MetaEventInfo";
38 /**
39 * esfFile for this event system.
41 private File esfFile = null;
42 private InputStream esfInputStream = null;
44 /**
45 * System Attributes
47 private Map<String, Map<String, BaseType>> events = null;
48 private Map<String, BaseType> knownTypes = null;
49 private Map<String, BaseType> reservedWords = null;
51 /**
52 * This is the EventTemplateDB constructor.
54 public EventTemplateDB() {
55 events = new ConcurrentHashMap<String, Map<String, BaseType>>();
56 knownTypes = new ConcurrentHashMap<String, BaseType>();
57 reservedWords = new ConcurrentHashMap<String, BaseType>();
58 initializeKnownTypes();
61 /**
62 * Sets the Event Specification file for this system
64 * @param anEsfFile the ESF file for this system.
66 public void setESFFile(File anEsfFile) {
67 esfFile = anEsfFile;
70 /**
71 * Gets the ESF file, in case you want to look at it
73 * @return the ESF file used in this system.
75 public File getESFFile() {
76 return esfFile;
79 /**
80 * Sets the Event Specification file as an InputStream
82 * @param esfInputStream the InputStream representing an ESF file
84 public void setESFInputStream(InputStream esfInputStream) {
85 this.esfInputStream = esfInputStream;
88 /**
89 * Ges the ESF InputStream
91 * @return the ESF InputStream used in the system
93 public InputStream getESFInputStream() {
94 return esfInputStream;
97 /**
98 * Initializes the EventTemplateDB, assumes that setESFFile() has been
99 * called.
101 * @return true if the EventTemplateDB initializes correctly; false if it
102 * does not. false means the event system is unable to perform validation
104 public synchronized boolean initialize() {
106 * Call the parser to parse the file. Any errors cause the
107 * initialization to fail.
109 ESFParser parser;
110 try {
111 if (getESFInputStream() != null) {
112 parser = new ESFParser(getESFInputStream());
114 else if (getESFFile() != null) {
115 parser = new ESFParser(
116 new java.io.FileInputStream(getESFFile()));
118 else {
119 return false;
122 parser.setEventTemplateDB(this);
123 parser.eventlist();
125 catch (java.io.FileNotFoundException e) {
126 log.warn("File not found ", e);
129 * treat this as just a warning and allow things to continue, this
130 * allows an empty EventTemplateDB to work when type checking is
131 * turned off
134 catch (ParseException e) {
135 log.warn("Parser error in ESF file " + getESFFile(), e);
136 return false;
138 catch (Exception e) {
139 log.error("Error parsing ESF file " + getESFFile(), e);
140 /* catch IO, NPEs and other exceptions but still continue */
141 return false;
144 return true;
148 * Add an Event to the EventTemplateDB
150 * @param anEventName the name of the Event to add
151 * @return true if the event was added, false if it was not
153 public synchronized boolean addEvent(String anEventName) {
154 if (anEventName == null) {
155 return false;
158 try {
159 if (anEventName.equals(META_EVENT_INFO)) {
160 return true;
163 if (events.containsKey(anEventName)) {
164 if (log.isInfoEnabled()) {
165 log.info("Event " + anEventName + " already exists in event DB");
167 return false;
170 Map<String, BaseType> evtHash = new ConcurrentHashMap<String, BaseType>();
171 if (!(reservedWords.isEmpty())) {
172 /* insert reserved words into new event */
173 for (String key : reservedWords.keySet()) {
174 if (key != null) {
175 evtHash.put(key, reservedWords.get(key));
180 events.put(anEventName, evtHash);
182 catch (Exception e) {
183 log.warn("Error adding event to EventTemplateDB", e);
186 return true;
189 public synchronized boolean addEventAttribute(String anEventName,
190 String anAttributeName,
191 String anAttributeType) {
192 return addEventAttribute(anEventName,
193 anAttributeName,
194 anAttributeType,
196 false);
199 public synchronized boolean addEventAttribute(String anEventName,
200 String anAttributeName,
201 String anAttributeType,
202 Integer size,
203 boolean required) {
204 return addEventAttribute(anEventName, anAttributeName, anAttributeType, size, required, null);
208 * Add an attribute to an Event in the EventTemplateDB
210 * @param anEventName the name of the event to add this attribute to
211 * @param anAttributeName the name of the attribute to add
212 * @param anAttributeType the type of the attribute, should be the name of the type
213 * given in the ESF Specification.
214 * @param size The size restriction for this attribute
215 * @param required Is this attribute required
216 * @return true if the attribute can be added, false if it can not.
218 public synchronized boolean addEventAttribute(String anEventName,
219 String anAttributeName,
220 String anAttributeType,
221 Integer size,
222 boolean required,
223 Object defaultValue) {
225 if (anEventName == null || anAttributeName == null || anAttributeType == null) {
226 return false;
229 try {
230 if (anEventName.equals(META_EVENT_INFO)) {
231 if (checkForType(anAttributeType)) {
232 BaseType bt = knownTypes.get(anAttributeType).cloneBaseType();
233 bt.setRequired(required);
234 bt.setSizeRestriction(size);
235 if (defaultValue != null) {
236 bt.setDefaultValue(defaultValue);
238 reservedWords.put(anAttributeName, bt);
239 return true;
241 else {
242 if (log.isInfoEnabled()) {
243 log.info("Meta keyword " + anEventName + "." + anAttributeName +
244 "has unknown type " + anAttributeType + ", skipping");
246 return false;
250 if (reservedWords.containsKey(anEventName)) {
251 if (log.isWarnEnabled()) {
252 log.warn("Unable to add attribute named " + anAttributeName +
253 "as it is a reserved word, skipping");
255 return false;
258 if (events.containsKey(anEventName)) {
259 Map<String, BaseType> evtHash = events.get(anEventName);
260 if (checkForType(anAttributeType)) {
261 BaseType bt = knownTypes.get(anAttributeType).cloneBaseType();
262 bt.setRequired(required);
263 bt.setSizeRestriction(size);
264 if (defaultValue != null) {
265 bt.setDefaultValue(defaultValue);
267 evtHash.put(anAttributeName, bt);
268 return true;
270 else {
271 if (log.isWarnEnabled()) {
272 log.warn("Type " + anAttributeType + " does not exist for " +
273 anAttributeName + ", skipping");
275 return false;
278 else {
279 if (log.isWarnEnabled()) {
280 log.warn("No such event " + anEventName + ", skipping");
282 return false;
285 catch (Exception e) {
286 log.error("Error adding attribute " + anAttributeName + " to " + anEventName, e);
287 return false;
292 * Returns an enumeration of all defined events
294 * @return an enumeration of all defined events
296 public Enumeration<String> getEventNames() {
297 return Collections.enumeration(this.events.keySet());
301 * Returns true if the type given by aTypeName is a valid type in the DB.
303 * @param aTypeName a type name according to the ESF Specification
304 * @return true if the type exists in the DB, false otherwise
306 public boolean checkForType(String aTypeName) {
307 if (aTypeName == null) {
308 return false;
310 return knownTypes.containsKey(aTypeName);
313 public void checkForSize(String eventName,
314 String attributeName,
315 BaseType attributeValue) throws EventAttributeSizeException {
317 if (!attributeValue.getTypeName().startsWith("[L")) {
318 if (log.isDebugEnabled()) {
319 log.debug("value for attribute " + attributeName + " is not an array.");
321 return;
324 Map<String, BaseType> evtMap = events.get(eventName);
325 if (evtMap == null) {
326 log.error("event definition did not exist");
327 return;
329 BaseType attrBaseType = evtMap.get(attributeName);
330 if (attrBaseType == null) {
331 log.error("attribute definition did not exist");
332 return;
335 int sizeToCheck = 0;
336 int size = attrBaseType.getSizeRestriction();
337 Object o = attributeValue.getTypeObject();
338 if (o instanceof short[]) {
339 sizeToCheck = ((short[]) o).length;
341 else if (o instanceof int[]) {
342 sizeToCheck = ((int[]) o).length;
344 else if (o instanceof long[]) {
345 sizeToCheck = ((long[]) o).length;
347 else if (o instanceof boolean[]) {
348 sizeToCheck = ((boolean[]) o).length;
350 else if (o instanceof byte[]) {
351 sizeToCheck = ((byte[]) o).length;
353 else if (o instanceof double[]) {
354 sizeToCheck = ((double[]) o).length;
356 else if (o instanceof float[]) {
357 sizeToCheck = ((float[]) o).length;
359 else if (o instanceof List) {
360 List arr = (List) attributeValue.getTypeObject();
361 sizeToCheck = arr.size();
363 else {
364 throw new EventAttributeSizeException("Cannot determine size for "+attributeName);
366 if (log.isTraceEnabled()) {
367 log.trace("sizeToCheck: " + sizeToCheck + " size: " + size);
369 if (size > 0 && sizeToCheck > size) {
370 throw new EventAttributeSizeException(attributeName, sizeToCheck, size);
375 * Checks to see if an Event exists in the EventTemplateDB
377 * @param anEventName the name of the event to check the existence of
378 * @return true if the event with the name <tt>anEventName</tt> exists in
379 * the EventTemplateDB, false otherwise.
381 public boolean checkForEvent(String anEventName) {
382 if (anEventName == null) {
383 return false;
385 return events.containsKey(anEventName);
389 * Checks to see if an attribute <tt>anAttributeName</tt> exists for the
390 * event <tt>anEventName</tt>
392 * @param anEventName the name of an Event
393 * @param anAttributeName the name of an attribute of Event to check
394 * @return true if the attribute exists as a member of event, false
395 * otherwise
397 public boolean checkForAttribute(String anEventName, String anAttributeName) {
398 if (anEventName == null || anAttributeName == null) {
399 return false;
402 if (checkForEvent(anEventName)) {
403 Map<String, BaseType> evtHash = events.get(anEventName);
404 return evtHash.containsKey(anAttributeName);
406 return false;
410 * Checks to see if the type of an attribute is proper. (i.e. if the given
411 * attribute of the given event has the same type assigned to it as the type
412 * of the given objects value)
414 * @param anEventName the name of an Event.
415 * @param anAttributeName the name of the attribute whose type is being checked
416 * @param anAttributeValue the Object containing the possible value of the attribute.
417 * @return true if the event and attribute exist and if the type of the
418 * attribute matches the type assigned to this attribute in the
419 * EventTemplateDB, false otherwise.
421 public boolean checkTypeForAttribute(String anEventName,
422 String anAttributeName,
423 Object anAttributeValue) {
424 if (anEventName == null || anAttributeName == null || anAttributeValue == null) {
425 return false;
428 if (checkForAttribute(anEventName, anAttributeName)) {
429 Map<String, BaseType> evtHash = events.get(anEventName);
430 Object storedTypeObject = evtHash.get(anAttributeName);
431 byte type1 = ((BaseType) anAttributeValue).getTypeToken();
432 byte type2 = ((BaseType) storedTypeObject).getTypeToken();
433 if (type1 == type2) {
434 return true;
438 return false;
442 * Checks to see if the type of an attribute is proper. (i.e. if the given
443 * attribute of the given event has the same type assigned to it as the type
444 * given)
446 * @param anEventName the name of an Event.
447 * @param anAttributeName the name of the attribute whose type is being checked
448 * @param anAttributeType the String containing the possible type value of the
449 * attribute.
450 * @return true if the event and attribute exist and if the type of the
451 * attribute matches the type assigned to this attribute in the
452 * EventTemplateDB, false otherwise.
454 public boolean checkTypeForAttribute(String anEventName,
455 String anAttributeName, String anAttributeType) {
456 if (anEventName == null || anAttributeName == null || anAttributeType == null) {
457 return false;
460 if (checkForAttribute(anEventName, anAttributeName)) {
461 Map<String, BaseType> evtHash = events.get(anEventName);
462 String storedTypeName = evtHash.get(anAttributeName).getTypeName();
463 if (log.isDebugEnabled()) {
464 log.debug("attr: " +
465 anAttributeName +
466 " stored: " +
467 storedTypeName +
468 " passed in: " +
469 anAttributeType);
471 if (anAttributeType.equals(storedTypeName)) {
472 return true;
476 return false;
480 * Given an Object which is the attribute value of the attribute
481 * <tt>attributeName</tt> of event <tt>eventName</tt>, return the internal
482 * representation (i.e. <tt>BaseType</tt>) of this Object
484 * @param eventName the name of an Event.
485 * @param attributeName the name of an attribute of <tt>eventName</tt>
486 * @param attributeValue the value of the attribute
487 * @return the <tt>BaseType</tt> representation of <tt>attributeValue</tt>
489 public BaseType getBaseTypeForObjectAttribute(String eventName,
490 String attributeName,
491 Object attributeValue) {
492 if (eventName == null || attributeName == null || attributeValue == null) {
493 return null;
496 Map<String, BaseType> evtHash = events.get(eventName);
497 BaseType tmpBaseType = evtHash.get(attributeName);
498 BaseType retBaseType = tmpBaseType.cloneBaseType();
499 retBaseType.setTypeObject(attributeValue);
500 return retBaseType;
504 * Returns the base types for this event
506 * @param eventName
507 * @return a map of event fields to base types
509 public Map<String, BaseType> getBaseTypesForEvent(String eventName) {
510 if (eventName == null) {
511 return null;
514 Map<String, BaseType> map = events.get(eventName);
516 return map == null ? new ConcurrentHashMap<String, BaseType>() : map;
520 * Parses the string representation of an event attribute into the
521 * appropriate objectt.
523 * @param anEventName the name of an Event.
524 * @param anAttributeName the name of the attribute we are parsing
525 * @param stringAttributeValue a string representation of the value of the attribute given by
526 * anAttributeName.
527 * @return the object represented by the string
528 * <tt>stringAttributeValue</tt>
530 public Object parseAttribute(String anEventName, String anAttributeName,
531 String stringAttributeValue) {
532 Object retObject = null;
534 if (anEventName == null || anAttributeName == null || stringAttributeValue == null) {
535 return null;
538 if (log.isTraceEnabled()) {
539 log.trace("parseAttribute: " + anEventName + "." + anAttributeName + "=" +
540 stringAttributeValue);
543 if (checkForAttribute(anEventName, anAttributeName)) {
544 if (log.isTraceEnabled()) {
545 log.trace("parseAttribute: passed first if attribute exists");
548 Map<String, BaseType> evtHash = events.get(anEventName);
549 try {
550 BaseType bt = evtHash.get(anAttributeName);
551 if (bt == null) {
552 throw new EventSystemException("Null BaseType for "
553 + anAttributeName);
556 retObject = bt.parseFromString(stringAttributeValue);
557 if (log.isTraceEnabled()) {
558 log.trace("parseAttribute: parsed " + retObject);
561 catch (EventSystemException btpe) {
562 log.error("Unable to parseAttribute", btpe);
566 if (log.isTraceEnabled()) {
567 log.trace("parseAttribute: returning " + retObject);
569 return retObject;
573 * Returns a HTML rendering of the EventTemplateDB
575 * @return HTML string of the EventTemplateDB
577 public String toHtmlString() {
578 StringBuffer sb = new StringBuffer();
579 sb.append("<table>\n");
580 sb.append("<tr><th>" + META_EVENT_INFO
581 + "</th><th>Type</th><th>Name</th></tr>\n");
582 for (String key : reservedWords.keySet()) {
583 BaseType tv = reservedWords.get(key);
584 String type = tv.getTypeName();
585 sb.append("<tr><td></td><td>").append(type).append("</td><td>").append(key).append("</td></tr>\n");
587 for (String EventKey : events.keySet()) {
588 sb.append("<tr><th>").append(EventKey).append("</th><th>Type</th><th>Name</th></tr>\n");
589 if (EventKey != null) {
590 Map<String, BaseType> event = events.get(EventKey);
591 for (Enumeration<String> att = Collections.enumeration(event.keySet()); att
592 .hasMoreElements();) {
593 String key = att.nextElement();
594 BaseType tv = event.get(key);
595 String type = tv.getTypeName();
596 sb.append("<tr><td></td><td>")
597 .append(type)
598 .append("</td><td>")
599 .append(key).append("</td></tr>\n");
604 sb.append("</table>\n");
605 return sb.toString();
610 * Returns a rather long string Representation of the EventTemplateDB
612 * @return a string Representation of the EventTemplateDB
614 public String toString() {
615 StringBuffer sb = new StringBuffer();
616 sb.append("\n").append(META_EVENT_INFO).append("\n{\n");
617 String[] reservedKeys = new String[reservedWords.size()];
618 int i = 0, j = 0;
620 for (String s1 : reservedWords.keySet()) {
621 reservedKeys[i] = s1;
622 ++i;
624 Arrays.sort(reservedKeys);
626 for (i = 0; i < reservedKeys.length; ++i) {
627 BaseType tv = reservedWords.get(reservedKeys[i]);
628 String type = tv.getTypeName();
629 sb.append("\t").append(type).append(" ").append(reservedKeys[i]).append(";\n");
631 sb.append("}\n");
633 String[] eventKeys = new String[events.size()];
634 i = 0;
635 for (String s : events.keySet()) {
636 eventKeys[i] = s;
637 ++i;
639 Arrays.sort(eventKeys);
641 for (i = 0; i < eventKeys.length; ++i) {
642 sb.append(eventKeys[i]).append("\n{\n");
643 if (eventKeys[i] != null) {
644 Map<String, BaseType> event = events.get(eventKeys[i]);
645 j = 0;
646 String[] attributeKeys = new String[event.size()];
647 for (Enumeration<String> att = Collections.enumeration(event.keySet());
648 att.hasMoreElements();) {
649 attributeKeys[j] = att.nextElement();
650 ++j;
652 Arrays.sort(attributeKeys);
654 for (j = 0; j < attributeKeys.length; ++j) {
655 BaseType tv = event.get(attributeKeys[j]);
656 String type = tv.getTypeName();
657 sb.append("\t").append(type).append(" ").append(attributeKeys[j]).append(";\n");
660 sb.append("}\n");
662 return sb.toString();
665 public String toStringOneLine() {
666 return toString().replace("\n", " ");
670 * Creates a map of known types
672 private void initializeKnownTypes() {
673 /* initialize the list of known types */
674 knownTypes.put(TypeID.UINT16_STRING, new BaseType(TypeID.UINT16_STRING,
675 TypeID.UINT16_TOKEN, 0));
676 knownTypes.put(TypeID.INT16_STRING, new BaseType(TypeID.INT16_STRING,
677 TypeID.INT16_TOKEN, (short) 0));
678 knownTypes.put(TypeID.UINT32_STRING, new BaseType(TypeID.UINT32_STRING,
679 TypeID.UINT32_TOKEN, (long) 0));
680 knownTypes.put(TypeID.INT32_STRING, new BaseType(TypeID.INT32_STRING,
681 TypeID.INT32_TOKEN, 0));
682 knownTypes.put(TypeID.STRING_STRING, new BaseType(TypeID.STRING_STRING,
683 TypeID.STRING_TOKEN, ""));
684 knownTypes.put(TypeID.IPADDR_STRING, new BaseType(TypeID.IPADDR_STRING,
685 TypeID.IPADDR_TOKEN, new IPAddress()));
686 knownTypes.put(TypeID.INT64_STRING, new BaseType(TypeID.INT64_STRING,
687 TypeID.INT64_TOKEN, (long) 0));
688 knownTypes.put(TypeID.UINT64_STRING, new BaseType(TypeID.UINT64_STRING,
689 TypeID.UINT64_TOKEN, BigInteger.ZERO));
690 knownTypes.put(TypeID.BOOLEAN_STRING, new BaseType(TypeID.BOOLEAN_STRING,
691 TypeID.BOOLEAN_TOKEN, true));
692 knownTypes.put(TypeID.STRING_ARRAY_STRING,
693 new BaseType(TypeID.STRING_ARRAY_STRING,
694 TypeID.STRING_ARRAY_TOKEN, null));
695 knownTypes.put(TypeID.INT16_ARRAY_STRING,
696 new BaseType(TypeID.INT16_ARRAY_STRING,
697 TypeID.INT16_ARRAY_TOKEN, null));
698 knownTypes.put(TypeID.INT32_ARRAY_STRING,
699 new BaseType(TypeID.INT32_ARRAY_STRING,
700 TypeID.INT32_ARRAY_TOKEN, null));
701 knownTypes.put(TypeID.INT64_ARRAY_STRING,
702 new BaseType(TypeID.INT64_ARRAY_STRING,
703 TypeID.INT64_ARRAY_TOKEN, null));
704 knownTypes.put(TypeID.UINT16_ARRAY_STRING,
705 new BaseType(TypeID.UINT16_ARRAY_STRING,
706 TypeID.UINT16_ARRAY_TOKEN, null));
707 knownTypes.put(TypeID.UINT32_ARRAY_STRING,
708 new BaseType(TypeID.UINT32_ARRAY_STRING,
709 TypeID.UINT32_ARRAY_TOKEN, null));
710 knownTypes.put(TypeID.UINT64_ARRAY_STRING,
711 new BaseType(TypeID.UINT64_ARRAY_STRING,
712 TypeID.UINT64_ARRAY_TOKEN, null));
713 knownTypes.put(TypeID.BOOLEAN_ARRAY_STRING,
714 new BaseType(TypeID.BOOLEAN_ARRAY_STRING,
715 TypeID.BOOLEAN_ARRAY_TOKEN, null));
716 knownTypes.put(TypeID.BYTE_ARRAY_STRING,
717 new BaseType(TypeID.BYTE_ARRAY_STRING,
718 TypeID.BYTE_ARRAY_TOKEN, null));
719 knownTypes.put(TypeID.DOUBLE_ARRAY_STRING,
720 new BaseType(TypeID.DOUBLE_ARRAY_STRING,
721 TypeID.DOUBLE_ARRAY_TOKEN, null));
722 knownTypes.put(TypeID.FLOAT_ARRAY_STRING,
723 new BaseType(TypeID.FLOAT_ARRAY_STRING,
724 TypeID.FLOAT_ARRAY_TOKEN, null));
725 knownTypes.put(TypeID.DOUBLE_STRING,
726 new BaseType(TypeID.DOUBLE_STRING,
727 TypeID.DOUBLE_TOKEN, null));
728 knownTypes.put(TypeID.FLOAT_STRING,
729 new BaseType(TypeID.FLOAT_STRING,
730 TypeID.FLOAT_TOKEN, null));
733 public Map<String, BaseType> getMetaFields() {
734 Map<String, BaseType> m = new TreeMap<String, BaseType>();
735 m.putAll(reservedWords);
736 return m;
739 public Map<String, Map<String, BaseType>> getEvents() {
740 Map<String, Map<String, BaseType>> cp = new TreeMap<String, Map<String, BaseType>>();
741 cp.putAll(events);
742 return cp;