View Javadoc

1   /*
2    * To change this template, choose Tools | Templates
3    * and open the template in the editor.
4    */
5   package cz.cuni.amis.pogamut.base.communication.worldview.impl;
6   
7   import java.util.ArrayList;
8   import java.util.List;
9   
10  import com.google.inject.Inject;
11  import com.google.inject.name.Named;
12  
13  import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldChangeEvent;
14  import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdatedEvent;
15  import cz.cuni.amis.pogamut.base.communication.worldview.ILockableWorldView;
16  import cz.cuni.amis.pogamut.base.component.bus.IComponentBus;
17  import cz.cuni.amis.pogamut.base.component.bus.exception.ComponentNotRunningException;
18  import cz.cuni.amis.pogamut.base.component.controller.ComponentDependencies;
19  import cz.cuni.amis.pogamut.base.utils.guice.AgentScoped;
20  import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
21  
22  /**
23   * WorldView that can be locked. If the world is locked all chages on objects are postponed
24   * and issued when the world is unlocked. The events aren't locked by default, but 
25   * there is a switch that enables locking of events.
26   * @author Ik
27   */
28  @AgentScoped
29  public class LockableWorldView extends EventDrivenWorldView implements ILockableWorldView {
30  
31  	public static final String WORLDVIEW_DEPENDENCY = "LockableWorldViewDependency";
32  	
33      private Boolean lock = false;
34      /** List of events received when the worldview was locked. */
35      protected List<IWorldChangeEvent> eventsToProcess = new ArrayList<IWorldChangeEvent>();
36      /** Lock non object update events? */
37      protected boolean lockEvents = false;
38  
39      @Inject
40      public LockableWorldView(@Named(WORLDVIEW_DEPENDENCY) ComponentDependencies dependencies, IComponentBus bus, IAgentLogger log) {
41          super(dependencies, bus, log);
42      }
43  
44      /**
45       * Prevent the WorldView from being changed.
46       */
47      public void lock() throws ComponentNotRunningException {
48      	if (!isRunning()) throw new ComponentNotRunningException(controller.getState().getFlag(), this);
49          synchronized (lock) {
50              lock = true;
51          }
52      }
53  
54      /**
55       * Unlock the WorldView and process all changes that happened when the world
56       * was locked.
57       */
58      public void unlock() {
59      	synchronized (lock) {
60              lock = false;
61  
62              // process postponed events
63              for (IWorldChangeEvent event : eventsToProcess) {
64                  super.notify(event);
65              }
66              eventsToProcess.clear();
67          }
68      }
69      
70      public boolean isLocked() {
71      	return lock;
72      }
73      
74      /**
75       * Should the event processing also be locked? The object updating isn't 
76       * affected by this switch.
77       * @param lockEvents
78       */
79      public void setLockEvents(boolean lockEvents) {
80          this.lockEvents = lockEvents;
81      }
82      
83      public boolean isLockEvents() {
84      	return this.lockEvents;
85      }
86  
87      /**
88       * Store all changes for later processing when the event is received in the
89       * while the world is locked. Otherwise immedeately process the change.
90       * @param event
91       */
92      public void notifyEvent(IWorldChangeEvent event) {
93      	if (!isRunning()) throw new ComponentNotRunningException(controller.getState().getFlag(), this);
94          synchronized (lock) {
95              if (lock) {
96                  if (!lockEvents && !(event instanceof IWorldObjectUpdatedEvent)) {
97                      eventsToProcess.add(event);
98                  } else {
99                      super.notify(event);
100                 }
101             }
102         }
103     }
104 }