package pl.eternalsh.simplecalc.controller;
import java.util.HashMap;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import pl.eternalsh.simplecalc.common.events.ApplicationEvent;
import pl.eternalsh.simplecalc.common.events.CalculateExpressionEvent;
import pl.eternalsh.simplecalc.model.Model;
import pl.eternalsh.simplecalc.view.View;
/**
* The controller - runs the application (view and model) and handles events incoming from application's GUI.
*
* @author Amadeusz Kosik
*/
public class Controller
{
/** Instance of the blocking queue for the upcoming events from the GUI. */
private final BlockingQueue<ApplicationEvent> blockingQueue;
/** Map of possible events and their respective handlers. */
private final HashMap<Class<? extends ApplicationEvent>, AbstractEventStrategy> eventStrategyMap;
/** Instance of the model. */
private final Model model;
/** Instance of view - the application's GUI. */
private final View view;
/**
* Creates and prepares BQ, event handling map, model and view, but doesn't run any of them yet.
*/
public Controller()
{
this.blockingQueue = new LinkedBlockingQueue<ApplicationEvent>();
this.eventStrategyMap = new HashMap<Class<? extends ApplicationEvent>, AbstractEventStrategy>();
this.model = new Model();
this.view = new View(blockingQueue);
/* Populate strategies map (since it's only one event, there's no need to create a separate method). */
eventStrategyMap.put(CalculateExpressionEvent.class, new CalculateExpressionEventStrategy(model, view));
}
/**
* Runs the application (starts GUI and listens for events).
*/
public void runApplication()
{
/* Show GUI. */
view.runGUI();
/* Event handling loop. */
while(true)
{
try
{
/* Take the first applicationEvent and handle it. */
ApplicationEvent applicationEvent = blockingQueue.take();
/* If somehow the controller has received an unknown applicationEvent - stop the application. */
if(! eventStrategyMap.containsKey(applicationEvent.getClass()))
{
throw new RuntimeException();
}
/* Handle the event. */
eventStrategyMap.get(applicationEvent.getClass()).handle(applicationEvent);
}
catch(InterruptedException exception)
{
throw new RuntimeException();
}
}
}
}