View Javadoc
1   package xuml.tools.model.compiler.runtime;
2   
3   import java.util.List;
4   import java.util.Stack;
5   
6   import javax.persistence.EntityManager;
7   
8   import com.google.common.base.Optional;
9   import com.google.common.collect.Lists;
10  
11  import scala.concurrent.duration.Duration;
12  import xuml.tools.model.compiler.runtime.message.Signal;
13  
14  /**
15   * Each {@link Entity} has one instance of this.
16   * 
17   * @author dave
18   * 
19   */
20  @SuppressWarnings({ "unchecked", "rawtypes" })
21  public class EntityHelper {
22  
23      private final Entity entity;
24      private final Stack<Call> stack = new Stack<Call>();
25      private final List<Signal> signalsToOther = Lists.newArrayList();
26      private final Signaller signaller;
27  
28      public EntityHelper(Signaller signaller, Entity entity) {
29          this.signaller = signaller;
30          this.entity = entity;
31      }
32  
33      public void beforeEvent() {
34  
35          stack.push(new Call());
36          Info info = signaller.getInfo();
37          info.setCurrentEntity(entity);
38      }
39  
40      public <T extends Entity<T>> void signal(Event<T> event) {
41          signal(event, Optional.<Duration> absent());
42      }
43  
44      public <T extends Entity<T>> void signal(Event<T> event, Optional<Duration> delay) {
45          Info info = signaller.getInfo();
46          // do an object equals because RootActor will guarantee that only one
47          // instance is being used to refer to a database entity at any given
48          // time.
49          boolean isSignalToSelf = entity == info.getCurrentEntity();
50          if (isSignalToSelf && (!delay.isPresent() || delay.get().toMillis() == 0)) {
51              // delay is ignored signals to self
52              stack.peek().getEventsToSelf().add(event);
53          } else {
54              String fromEntityUniqueId;
55              if (info.getCurrentEntity() == null)
56                  fromEntityUniqueId = "Unknown";
57              else
58                  fromEntityUniqueId = info.getCurrentEntity().uniqueId();
59              signaller.signal(fromEntityUniqueId, entity, event, delay);
60          }
61      }
62  
63      public <T> void queueSignal(Signal<T> signal) {
64          signalsToOther.add(signal);
65      }
66  
67      public void sendQueuedSignals() {
68          for (Signal signal : signalsToOther) {
69              // signal has already been persisted so can send it
70              signaller.signal(signal);
71          }
72      }
73  
74      /**
75       * Just after each Entity.performEvent is called we perform the events to
76       * self that were called during that event.
77       */
78      public void afterEvent() {
79          Call call = stack.peek();
80          for (Event event : call.getEventsToSelf()) {
81              entity.event(event);
82          }
83          stack.pop();
84          if (stack.size() == 0) {
85              Info info = signaller.getInfo();
86              // reset the thread local variable so that the next use of this
87              // thread will not make an assumption about the current entity
88              info.setCurrentEntity(null);
89          }
90  
91      }
92  
93      private static class Call {
94          private final List<Event> eventsToSelf = Lists.newArrayList();
95  
96          public List<Event> getEventsToSelf() {
97              return eventsToSelf;
98          }
99      }
100 
101     public void setEntityManager(EntityManager em) {
102         signaller.getInfo().setCurrentEntityManager(em);
103     }
104 
105     public EntityManager getEntityManager() {
106         return signaller.getInfo().getCurrentEntityManager();
107     }
108 
109 }