001 package org.LiveGraph.events; 002 003 import java.lang.reflect.Field; 004 import java.util.ArrayList; 005 import java.util.Collections; 006 import java.util.List; 007 008 import com.softnetConsult.utils.exceptions.Bug; 009 010 011 public class Event<ET extends EventType> { 012 013 public static final boolean SAFE_EVENT_CAST = true; 014 015 private EventProducer producer; 016 private Class<? extends ET> domain; 017 private ET type; 018 019 private boolean hasValidated; 020 021 public boolean infoBoolean; 022 public long infoLong; 023 public double infoDouble; 024 public Object infoObject; 025 026 private List<EventAnnotation> annotations; 027 private List<EventAnnotation> exposedAnnotations; 028 029 public Event(EventProducer producer, Class<? extends ET> domain, ET type) { 030 031 if (null == producer) throw new NullPointerException("Cannot construct event for a null producer"); 032 if (null == domain) throw new NullPointerException("Cannot construct event for a null domain"); 033 if (null == type) throw new NullPointerException("Cannot construct event for a null type"); 034 035 this.producer = producer; 036 this.domain = domain; 037 this.type = type; 038 039 this.hasValidated = false; 040 041 this.infoBoolean = false; 042 this.infoLong = 0L; 043 this.infoDouble = Double.NaN; 044 this.infoObject = null; 045 046 this.annotations = null; 047 this.exposedAnnotations = null; 048 } 049 050 public Event(EventProducer producer, Class<? extends ET> domain, ET type, boolean info) { 051 this(producer, domain, type); 052 this.infoBoolean = info; 053 } 054 055 public Event(EventProducer producer, Class<? extends ET> domain, ET type, long info) { 056 this(producer, domain, type); 057 this.infoLong = info; 058 } 059 060 public Event(EventProducer producer, Class<? extends ET> domain, ET type, double info) { 061 this(producer, domain, type); 062 this.infoDouble = info; 063 } 064 065 public Event(EventProducer producer, Class<? extends ET> domain, ET type, Object info) { 066 this(producer, domain, type); 067 this.infoObject = info; 068 } 069 070 public Event(EventProducer producer, Class<? extends ET> domain, ET type, 071 boolean infoBoolean, long infoLong, double infoDouble, Object infoObject) { 072 this(producer, domain, type); 073 this.infoBoolean = infoBoolean; 074 this.infoLong = infoLong; 075 this.infoDouble = infoDouble; 076 this.infoObject = infoObject; 077 } 078 079 @SuppressWarnings("unchecked") 080 public <T extends EventType> Event<T> cast(Class<T> domain) { 081 082 if (SAFE_EVENT_CAST) { 083 084 if (null == domain) 085 throw new NullPointerException("Cannot cast event to a null target domain"); 086 087 if (!getDomain().isAssignableFrom(domain)) { 088 throw new ClassCastException("Cannot cast this event of type " 089 + this.getClass().getName() + "<" + getDomain().getName() + "> " 090 + "to Event<" + domain.getName() + ">"); 091 } 092 } 093 094 return (Event<T>) this; 095 } 096 097 public EventProducer getProducer() { 098 return producer; 099 } 100 101 public Class<? extends ET> getDomain() { 102 return domain; 103 } 104 105 public ET getType() { 106 return type; 107 } 108 109 public boolean validated() { 110 return hasValidated; 111 } 112 113 protected void setValidated(boolean validated) { 114 hasValidated = validated; 115 } 116 117 public Validation.Requirement getValidationRequirement() { 118 119 Class<? extends EventType> typeClass = type.getClass(); 120 Validation validation = typeClass.getAnnotation(Validation.class); 121 if (null != validation) 122 return validation.value(); 123 124 // If the event type is an enum, the annotation may have been attached not to the 125 // class itself, but to the "field", i.e. the enum constant: 126 if (typeClass.isEnum()) { 127 128 try { 129 Field declaringField = typeClass.getField(type.toString()); 130 validation = declaringField.getAnnotation(Validation.class); 131 } catch(NoSuchFieldException e) { 132 throw new Bug("This should never happen!", e); 133 } 134 135 if (null != validation) 136 return validation.value(); 137 } 138 139 return Validation.Requirement.MAY_VALIDATE; 140 } 141 142 public boolean getInfoBoolean() { 143 return infoBoolean; 144 } 145 146 public long getInfoLong() { 147 return infoLong; 148 } 149 150 public double getInfoDouble() { 151 return infoDouble; 152 } 153 154 public Object getInfoObject() { 155 return infoObject; 156 } 157 158 public void addAnnotation(EventListener listener, Object annotationInfo) { 159 if (null == listener) 160 throw new NullPointerException("A null EventListener cannot add an EventAnnotation"); 161 if (null == annotations) 162 annotations = new ArrayList<EventAnnotation>(); 163 annotations.add(new EventAnnotation(listener, annotationInfo)); 164 exposedAnnotations = null; 165 } 166 167 168 public List<EventAnnotation> getAnnotations() { 169 if (null == exposedAnnotations) { 170 171 if (null == annotations) 172 return Collections.emptyList(); 173 174 exposedAnnotations = new ArrayList<EventAnnotation>(); 175 for (EventAnnotation annotation : annotations) 176 exposedAnnotations.add(annotation); 177 exposedAnnotations = Collections.unmodifiableList(exposedAnnotations); 178 } 179 return exposedAnnotations; 180 } 181 182 public List<EventAnnotation> getAnnotations(EventListener byListener) { 183 184 if (null == annotations) 185 return Collections.emptyList(); 186 187 if (null == byListener) 188 return getAnnotations(); 189 190 List<EventAnnotation> listenerAnnotations = new ArrayList<EventAnnotation>(); 191 for (EventAnnotation annotation : annotations) { 192 if (annotation.getListener() == byListener) 193 listenerAnnotations.add(annotation); 194 } 195 return Collections.unmodifiableList(listenerAnnotations); 196 } 197 198 @Override 199 public String toString() { 200 String s = super.toString() + "{"; 201 s += "type=(" + getType().toString() + ");"; 202 s += "producer=(" + getProducer().toString() + ");"; 203 s += "info=("; 204 s += "bool:" + getInfoBoolean() + ";"; 205 s += "long:" + getInfoLong() + ";"; 206 s += "dble:" + getInfoDouble() + ";"; 207 s += "objt:" + getInfoObject() + ";"; 208 s += ");"; 209 s += "validated=(" + (validated() ? "Y" : "N") + ");"; 210 s += "valid-reqr=(" + getValidationRequirement() + ");"; 211 s += "annotations=(" + (null == annotations ? 0 : annotations.size()) + ");"; 212 s += "}"; 213 return s; 214 } 215 216 }