View Javadoc

1   package cz.cuni.amis.pogamut.base.communication.translator.impl;
2   
3   import java.util.LinkedList;
4   import java.util.Queue;
5   import java.util.logging.Logger;
6   
7   import com.google.inject.Inject;
8   
9   import cz.cuni.amis.pogamut.base.communication.messages.InfoMessage;
10  import cz.cuni.amis.pogamut.base.communication.parser.IWorldMessageParser;
11  import cz.cuni.amis.pogamut.base.communication.translator.IWorldMessageTranslator;
12  import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldChangeEvent;
13  import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldChangeEventOutput;
14  import cz.cuni.amis.pogamut.base.communication.translator.exception.TranslatorException;
15  import cz.cuni.amis.pogamut.base.component.IComponent;
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.bus.exception.ComponentPausedException;
19  import cz.cuni.amis.pogamut.base.component.controller.ComponentControlHelper;
20  import cz.cuni.amis.pogamut.base.component.controller.ComponentController;
21  import cz.cuni.amis.pogamut.base.component.controller.ComponentDependencyType;
22  import cz.cuni.amis.pogamut.base.component.controller.IComponentControlHelper;
23  import cz.cuni.amis.pogamut.base.utils.guice.AgentScoped;
24  import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
25  import cz.cuni.amis.pogamut.base.utils.logging.LogCategory;
26  import cz.cuni.amis.utils.NullCheck;
27  import cz.cuni.amis.utils.token.Token;
28  import cz.cuni.amis.utils.token.Tokens;
29  
30  /**
31   * Abstract class for translators between world messages (InfoObjects) and IWorldEvents. 
32   * It implements IWorldEventOutput interface meaning
33   * it can be given to the mediator as the source for IWorldEvents. It is constructed
34   * with parser that should provide parsed messages (translated text messages from the world
35   * to the java object wrappers) + IWorldMessageHandler that is given those parsed messages
36   * to produce IWorldEvents. It should process those messages into IWorldEvents and return them.
37   * <p><p>
38   * Ignores {@link IComponentControlHelper#startPaused()}, performs {@link IComponentControlHelper#start()} in both start cases.
39   * 
40   * @author Jimmy
41   */
42  @AgentScoped
43  public class WorldMessageTranslator implements IWorldChangeEventOutput {
44  	
45  	public static final Token COMPONENT_ID = Tokens.get("WorldMessageTranslator");
46  
47  	/**
48  	 * Parser of the world messages, may be used to get additional messages.
49  	 */
50  	protected IWorldMessageParser parser = null;
51  	
52  	protected LogCategory log = null;
53  	
54  	protected IWorldMessageTranslator handler = null;
55  
56  	private IComponentBus eventBus;
57  
58  	private ComponentController<IComponent> controller;
59  	
60  	@Inject
61  	public WorldMessageTranslator(IWorldMessageParser parser, IWorldMessageTranslator messageHandler, IComponentBus eventBus, IAgentLogger logger) {
62  		log = logger.getCategory(getComponentId().getToken());				
63  		this.parser = parser;
64  		NullCheck.check(this.parser, "parser");
65  		this.handler = messageHandler;
66  		NullCheck.check(this.handler, "handler");
67  		
68  		this.eventBus = eventBus;
69  		this.controller = new ComponentController(this, control, eventBus, log, ComponentDependencyType.STARTS_AFTER, parser);
70  	}
71  	
72  	private IComponentControlHelper control = new ComponentControlHelper() {
73  
74  		@Override
75  		public void startPaused() {
76  			start();
77  		}
78  		
79  		@Override
80  		public void start() {
81  			handler.reset();
82  		}
83  	};
84  
85  	@Override
86  	public Token getComponentId() {
87  		return COMPONENT_ID;
88  	}
89  	
90  	public Logger getLog() {
91  		return log;
92  	}
93  	
94  	/**
95  	 * Method for translating messages into events.
96  	 * 
97  	 * @param message
98  	 * @return
99  	 * @throws WorldMessageHandlerException
100 	 */
101 	protected IWorldChangeEvent[] processMessage(InfoMessage message) throws TranslatorException {
102 		return handler.processMessage(message);
103 	}
104 	
105 	/**
106 	 * Method processMessage() may produce more events per message - if it does so, we will store those events
107 	 * in this queue. If queue is not empty - getEvent() will return events from this queue.
108 	 */
109 	private Queue<IWorldChangeEvent> worldEventQueue = new LinkedList<IWorldChangeEvent>();
110 
111 	@Override
112 	public synchronized IWorldChangeEvent getEvent() throws ComponentNotRunningException, ComponentPausedException {
113 		if (controller.isPaused()) throw new ComponentPausedException(controller.getState().getFlag(), this);
114 		if (!controller.isRunning()) throw new ComponentNotRunningException(controller.getState().getFlag(), this);
115 		if (worldEventQueue.size() > 0) return worldEventQueue.poll();
116 		InfoMessage message;
117 		IWorldChangeEvent[] worldEvents = null;
118 		while (worldEvents == null || worldEvents.length == 0) {
119 			message = null;
120 			while (message == null) {
121 				message = parser.parse();
122 			}
123 			worldEvents = processMessage(message);			
124 		}
125 		for (int i = 1; i < worldEvents.length; ++i) {
126 			worldEventQueue.add(worldEvents[i]);
127 		}
128 		return worldEvents[0];
129 	}
130 	
131 	public String toString() {
132 		if (this == null) return "WorldMessageParser";
133 		else return getClass().getSimpleName() + "[parser=" + parser + ", handler=" + handler + "]";
134 	}
135 	
136 }