View Javadoc

1   package cz.cuni.amis.pogamut.base3d.worldview.impl;
2   
3   import java.util.HashSet;
4   import java.util.Set;
5   
6   import com.google.inject.name.Named;
7   
8   import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldChangeEvent;
9   import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdatedEvent;
10  import cz.cuni.amis.pogamut.base.component.bus.IComponentBus;
11  import cz.cuni.amis.pogamut.base.component.bus.exception.ComponentNotRunningException;
12  import cz.cuni.amis.pogamut.base.component.bus.exception.ComponentPausedException;
13  import cz.cuni.amis.pogamut.base.component.controller.ComponentDependencies;
14  import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
15  import cz.cuni.amis.pogamut.base3d.worldview.object.IViewable;
16  
17  /**
18   * World view that is updated by protocol utilizing concept of batches. Each batch
19   * is separated by some message. After receiving this message additional events
20   * may be raised (eg. visibility update etc.).
21   * @author ik
22   */
23  public abstract class BatchAwareWorldView extends VisionWorldView {
24  
25  	public static final String WORLDVIEW_DEPENDENCY = "BatchAwareWorldViewDependency";
26  	
27      protected Set<IViewable> lastObjectBatch = new HashSet<IViewable>();
28      protected Set<IViewable> currentObjectBatch = new HashSet<IViewable>();
29  
30      public BatchAwareWorldView(@Named(WORLDVIEW_DEPENDENCY) ComponentDependencies dependencies, IComponentBus bus, IAgentLogger log) {
31          super(dependencies, bus, log);
32      }
33  
34      /**
35       * Is this event a batch end event? If so some extra events may be generated
36       * in processing this message.
37       * @param evt
38       * @return true if this is a batch ending event
39       */
40      protected abstract boolean isBatchEndEvent(IWorldChangeEvent evt);
41      
42  	/**
43  	 * Is this event a batch begin event? It is needed for the locking to be
44  	 * working correctly.
45  	 * 
46  	 * @param evt
47  	 * @return true if this is a batch ending event
48  	 */
49  	protected abstract boolean isBatchBeginEvent(IWorldChangeEvent evt);    
50  
51      /**
52       * Sets the visible flag to true on {@link IViewable} objects.
53       * @param obj Object that disappeared
54       */
55      protected abstract void setDisappearedFlag(IViewable obj);
56      
57  //    long lastBatch = 0;
58  
59      protected void batchAwareWorldViewNotify(IWorldChangeEvent event) {
60      	if (isBatchEndEvent(event)) {
61      		
62  //    		if (lastBatch == 0) {
63  //    			lastBatch = System.currentTimeMillis();
64  //    		} else {
65  //    			long currTime = System.currentTimeMillis();
66  //    			log.warning("LAST BATCH: " + (currTime - lastBatch) + " ms | event.getSimTime() == " + event.getSimTime());
67  //    			lastBatch = currTime;    			
68  //    		}
69      		
70              // handle disappeared objects
71              lastObjectBatch.removeAll(currentObjectBatch);
72              for (IViewable obj : lastObjectBatch) {
73                  // set the visibility flag to false
74                  setDisappearedFlag(obj);
75                  // first generate update event
76                  objectUpdated(obj);                
77                  // IMPORTANT:               
78                  // then generate disappear event ... usually appeared/disappeared events will 
79                  // wrap the update event processing (e.g. like html tags they must open/...updates.../close)
80                  super.objectDisappeared(obj);                
81              }            
82              // exchange the two sets and clear current batch
83              Set<IViewable> swp = lastObjectBatch;
84              lastObjectBatch = currentObjectBatch;
85              currentObjectBatch = swp;
86              currentObjectBatch.clear();
87          } else {
88              if (event instanceof IWorldObjectUpdatedEvent && event instanceof IViewable) {
89                  IViewable viewable = (IViewable)get(((IWorldObjectUpdatedEvent)event).getId());
90                  if (viewable != null && viewable.isVisible()) {
91                      currentObjectBatch.add(viewable);
92                  }
93              }
94          }
95      }
96      
97      @Override
98      public synchronized void notify(IWorldChangeEvent event) {
99      	batchAwareWorldViewNotify(event);
100     	super.notify(event);
101     }
102     
103     @Override
104     public synchronized void notifyImmediately(IWorldChangeEvent event)
105     		throws ComponentNotRunningException, ComponentPausedException {
106     	batchAwareWorldViewNotify(event);
107     	super.notifyImmediately(event);
108     }
109     
110     @Override
111     protected void objectAppeared(IViewable obj) {
112     	super.objectAppeared(obj);
113     	currentObjectBatch.add(obj);
114     }
115     
116     @Override
117     protected void objectDisappeared(IViewable obj) {
118     	super.objectDisappeared(obj);
119     	lastObjectBatch.remove(obj);
120     	currentObjectBatch.remove(obj);
121     }
122     
123     /**
124      * Any objects waiting in {@link BatchAwareWorldView#currentObjectBatch} for processing?
125      * @return true if there is at least one object to process
126      */
127     public boolean hasObjectsToProcess() {
128     	return !currentObjectBatch.isEmpty();
129     }
130     
131 }