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 }