(no commit message)
[sw/motorsim] / src / com / billkuker / rocketry / motorsim / ChangeListening.aj
1 package com.billkuker.rocketry.motorsim;
2
3 import java.beans.PropertyChangeEvent;
4 import java.beans.PropertyChangeListener;
5 import java.beans.PropertyChangeSupport;
6 import java.lang.reflect.Method;
7
8 import org.apache.log4j.Logger;
9
10 public aspect ChangeListening {
11
12         private static Logger log = Logger.getLogger(ChangeListening.class);
13         public interface Subject {
14                 // public void addPropertyChangeListener(PropertyChangeListener l);
15         }
16
17         private PropertyChangeSupport Subject.pcs;
18
19         public void Subject.addPropertyChangeListener(PropertyChangeListener l) {
20                 pcs.addPropertyChangeListener(l);
21         }
22         
23         public void Subject.removePropertyChangeListener(PropertyChangeListener l) {
24                 pcs.removePropertyChangeListener(l);
25         }
26         
27         public void Subject.firePropertyChange(PropertyChangeEvent e) {
28                 pcs.firePropertyChange(e);
29         }
30
31         declare parents: Motor || Grain || Chamber || Nozzle || Fuel implements Subject;
32
33         void around(Subject s, Object newVal):
34                 execution(void Subject+.set*(..)) && target(s) && args(newVal) {
35                 String name = thisJoinPointStaticPart.getSignature().getName();
36                 name = name.replaceFirst("set", "");
37                 Object old = null;
38                 try {
39                         String pre = "get";
40                         if (newVal instanceof Boolean)
41                                 pre = "is";
42                         Method m = s.getClass().getMethod(pre + name);
43                         old = m.invoke(s);
44
45                 } catch (Throwable t) {
46                         log.warn("Error getting old value for " + name);
47                 }
48                 proceed(s, newVal);
49                 if (old != newVal) {
50                         s.pcs.firePropertyChange(name, old, newVal);
51                 }
52         }
53
54         after(Subject s) returning: this(s) && initialization(Subject.new(..)) {
55                 s.pcs = new PropertyChangeSupport(s);
56         }
57 }