Another refactoring step...
This commit is contained in:
@@ -8,6 +8,7 @@ import java.util.Collections;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
@@ -69,6 +70,7 @@ public abstract class BaseClass implements Constants{
|
|||||||
private Contact contact;
|
private Contact contact;
|
||||||
private Direction direction;
|
private Direction direction;
|
||||||
private Integer waitTime;
|
private Integer waitTime;
|
||||||
|
List<EventListener> invalidationListeners = new LinkedList<>();
|
||||||
|
|
||||||
public Context(BaseClass object) {
|
public Context(BaseClass object) {
|
||||||
setMain(object);
|
setMain(object);
|
||||||
@@ -147,12 +149,18 @@ public abstract class BaseClass implements Constants{
|
|||||||
|
|
||||||
public void invalidate() {
|
public void invalidate() {
|
||||||
setMain(null);
|
setMain(null);
|
||||||
|
invalidationListeners.forEach(EventListener::fire);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean invalidated() {
|
public boolean invalidated() {
|
||||||
return isNull(main);
|
return isNull(main);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onInvalidate(EventListener listener) {
|
||||||
|
invalidationListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Context setMain(BaseClass object) {
|
public Context setMain(BaseClass object) {
|
||||||
main = object;
|
main = object;
|
||||||
LOG.debug("{}.setMain({})",this,object);
|
LOG.debug("{}.setMain({})",this,object);
|
||||||
|
|||||||
5
src/main/java/de/srsoftware/web4rail/EventListener.java
Normal file
5
src/main/java/de/srsoftware/web4rail/EventListener.java
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package de.srsoftware.web4rail;
|
||||||
|
|
||||||
|
public interface EventListener {
|
||||||
|
public void fire();
|
||||||
|
}
|
||||||
@@ -38,6 +38,7 @@ import de.srsoftware.web4rail.tags.Input;
|
|||||||
import de.srsoftware.web4rail.tags.Table;
|
import de.srsoftware.web4rail.tags.Table;
|
||||||
import de.srsoftware.web4rail.tags.Window;
|
import de.srsoftware.web4rail.tags.Window;
|
||||||
import de.srsoftware.web4rail.threads.BrakeProcess;
|
import de.srsoftware.web4rail.threads.BrakeProcess;
|
||||||
|
import de.srsoftware.web4rail.threads.RoutePrepper;
|
||||||
import de.srsoftware.web4rail.tiles.Block;
|
import de.srsoftware.web4rail.tiles.Block;
|
||||||
import de.srsoftware.web4rail.tiles.BlockContact;
|
import de.srsoftware.web4rail.tiles.BlockContact;
|
||||||
import de.srsoftware.web4rail.tiles.Contact;
|
import de.srsoftware.web4rail.tiles.Contact;
|
||||||
@@ -95,6 +96,8 @@ public class Route extends BaseClass {
|
|||||||
private HashSet<Contact> triggeredContacts = new HashSet<>();
|
private HashSet<Contact> triggeredContacts = new HashSet<>();
|
||||||
|
|
||||||
private Route nextPreparedRoute;
|
private Route nextPreparedRoute;
|
||||||
|
|
||||||
|
private RoutePrepper nextRoutePrepper;
|
||||||
|
|
||||||
public Route() {
|
public Route() {
|
||||||
conditions = new ConditionList();
|
conditions = new ConditionList();
|
||||||
@@ -394,8 +397,6 @@ public class Route extends BaseClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void free() {
|
private void free() {
|
||||||
context.invalidate(); // do not set to null:
|
|
||||||
// this action may be called from route.contact → finishRoute, which calls train.updateTrace afterwards, which in turn requires context
|
|
||||||
Train train = context.train();
|
Train train = context.train();
|
||||||
Vector<Tile> reversedPath = reverse(path());
|
Vector<Tile> reversedPath = reverse(path());
|
||||||
for (Tile tile : reversedPath) {
|
for (Tile tile : reversedPath) {
|
||||||
@@ -684,6 +685,19 @@ public class Route extends BaseClass {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean prepareNext(Context context) {
|
||||||
|
if (isSet(nextRoutePrepper)) return false;
|
||||||
|
nextRoutePrepper = new RoutePrepper(context);
|
||||||
|
nextRoutePrepper.onRoutePrepared(() -> {
|
||||||
|
nextPreparedRoute = nextRoutePrepper.route();
|
||||||
|
nextRoutePrepper = null;
|
||||||
|
});
|
||||||
|
nextRoutePrepper.onFail(() -> {
|
||||||
|
nextRoutePrepper = null;
|
||||||
|
});
|
||||||
|
return nextRoutePrepper.prepareRoute();
|
||||||
|
}
|
||||||
|
|
||||||
private Tag previewScript() {
|
private Tag previewScript() {
|
||||||
Tag script = new Tag("script").attr("type", "text/javascript");
|
Tag script = new Tag("script").attr("type", "text/javascript");
|
||||||
for (Tile tile : path) {
|
for (Tile tile : path) {
|
||||||
@@ -752,7 +766,7 @@ public class Route extends BaseClass {
|
|||||||
|
|
||||||
public boolean reserveFor(Context newContext) {
|
public boolean reserveFor(Context newContext) {
|
||||||
LOG.debug("{}.reserverFor({})",this,newContext);
|
LOG.debug("{}.reserverFor({})",this,newContext);
|
||||||
if (isSet(context)) return false; // route already has context!
|
// if (isSet(context)) return false; // route already has context!
|
||||||
context = newContext;
|
context = newContext;
|
||||||
for (Tile tile : path) {
|
for (Tile tile : path) {
|
||||||
if (newContext.invalidated() || !tile.reserveFor(newContext)) {
|
if (newContext.invalidated() || !tile.reserveFor(newContext)) {
|
||||||
@@ -765,6 +779,7 @@ public class Route extends BaseClass {
|
|||||||
|
|
||||||
public boolean reset() {
|
public boolean reset() {
|
||||||
LOG.debug("{}.reset()",this);
|
LOG.debug("{}.reset()",this);
|
||||||
|
resetNext();
|
||||||
setSignals(Signal.RED);
|
setSignals(Signal.RED);
|
||||||
Train train = context.train();
|
Train train = context.train();
|
||||||
free();
|
free();
|
||||||
@@ -773,6 +788,11 @@ public class Route extends BaseClass {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void resetNext() {
|
||||||
|
if (isSet(nextRoutePrepper)) nextRoutePrepper.stop();
|
||||||
|
if (isSet(nextPreparedRoute)) nextPreparedRoute.reset();
|
||||||
|
}
|
||||||
|
|
||||||
public static void saveAll(String filename) throws IOException {
|
public static void saveAll(String filename) throws IOException {
|
||||||
BufferedWriter file = new BufferedWriter(new FileWriter(filename));
|
BufferedWriter file = new BufferedWriter(new FileWriter(filename));
|
||||||
file.write("{\""+ROUTES+"\":[\n");
|
file.write("{\""+ROUTES+"\":[\n");
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ public class PreserveRoute extends Action {
|
|||||||
LOG.debug("Not preserving route, as train needs to stop for {} ms at {}!",waitTime,endBlock);
|
LOG.debug("Not preserving route, as train needs to stop for {} ms at {}!",waitTime,endBlock);
|
||||||
return false; // train is expected to wait in next block.
|
return false; // train is expected to wait in next block.
|
||||||
}
|
}
|
||||||
return isSet(route.getNextPreparedRoute()) || train.reserveRouteAfter(route);
|
if (isSet(route.getNextPreparedRoute())) return true;
|
||||||
|
Context nextContext = new Context(train).block(route.endBlock()).direction(route.endDirection);
|
||||||
|
context.onInvalidate(nextContext::invalidate);
|
||||||
|
return route.prepareNext(nextContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class BlockFree extends Condition {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean fulfilledBy(Context context) {
|
public boolean fulfilledBy(Context context) {
|
||||||
return block.isFreeFor(null) != inverted;
|
return block.isFreeFor(context) != inverted;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -36,10 +36,9 @@ import de.srsoftware.web4rail.tags.Label;
|
|||||||
import de.srsoftware.web4rail.tags.Select;
|
import de.srsoftware.web4rail.tags.Select;
|
||||||
import de.srsoftware.web4rail.tags.Table;
|
import de.srsoftware.web4rail.tags.Table;
|
||||||
import de.srsoftware.web4rail.tags.Window;
|
import de.srsoftware.web4rail.tags.Window;
|
||||||
import de.srsoftware.web4rail.threads.RouteManager.Callback;
|
|
||||||
import de.srsoftware.web4rail.threads.BrakeProcess;
|
import de.srsoftware.web4rail.threads.BrakeProcess;
|
||||||
import de.srsoftware.web4rail.threads.DelayedExecution;
|
import de.srsoftware.web4rail.threads.DelayedExecution;
|
||||||
import de.srsoftware.web4rail.threads.RouteManager;
|
import de.srsoftware.web4rail.threads.RoutePrepper;
|
||||||
import de.srsoftware.web4rail.tiles.Block;
|
import de.srsoftware.web4rail.tiles.Block;
|
||||||
import de.srsoftware.web4rail.tiles.Contact;
|
import de.srsoftware.web4rail.tiles.Contact;
|
||||||
import de.srsoftware.web4rail.tiles.Tile;
|
import de.srsoftware.web4rail.tiles.Tile;
|
||||||
@@ -92,7 +91,7 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
public int speed = 0;
|
public int speed = 0;
|
||||||
private static final String SHUNTING = "shunting";
|
private static final String SHUNTING = "shunting";
|
||||||
private boolean shunting = false;
|
private boolean shunting = false;
|
||||||
private RouteManager routeManager = null;
|
private RoutePrepper routePrepper = null;
|
||||||
|
|
||||||
private HashSet<Tile> stuckTrace = null;
|
private HashSet<Tile> stuckTrace = null;
|
||||||
|
|
||||||
@@ -422,7 +421,7 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
if (isSet(brake)) brake.updateTime();
|
if (isSet(brake)) brake.updateTime();
|
||||||
Integer waitTime = route.waitTime();
|
Integer waitTime = route.waitTime();
|
||||||
nextPreparedRoute = route.dropNextPreparedRoute();
|
nextPreparedRoute = route.dropNextPreparedRoute();
|
||||||
if (isNull(nextPreparedRoute) || (isSet(waitTime) && waitTime > 0)) setSpeed(0);
|
if ((!autopilot)|| isNull(nextPreparedRoute) || (isSet(waitTime) && waitTime > 0)) setSpeed(0);
|
||||||
route = null;
|
route = null;
|
||||||
direction = endDirection;
|
direction = endDirection;
|
||||||
endBlock.add(this, direction);
|
endBlock.add(this, direction);
|
||||||
@@ -490,7 +489,7 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
|
|
||||||
public boolean isStoppable() {
|
public boolean isStoppable() {
|
||||||
if (speed > 0) return true;
|
if (speed > 0) return true;
|
||||||
if (isSet(routeManager) && routeManager.isActive()) return true;
|
if (isSet(routePrepper)) return true;
|
||||||
if (isSet(route)) return true;
|
if (isSet(route)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -721,7 +720,8 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String quitAutopilot() {
|
public String quitAutopilot() {
|
||||||
if (isSet(routeManager)) routeManager.quit();
|
if (isSet(routePrepper)) routePrepper.stop();
|
||||||
|
// if (isSet(route)) route.resetNext();
|
||||||
autopilot = false;
|
autopilot = false;
|
||||||
return t("Autopilot already was disabled!");
|
return t("Autopilot already was disabled!");
|
||||||
}
|
}
|
||||||
@@ -747,7 +747,7 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
//if (child == nextRoute) nextRoute = null; // TODO
|
//if (child == nextRoute) nextRoute = null; // TODO
|
||||||
if (child == currentBlock) currentBlock = null;
|
if (child == currentBlock) currentBlock = null;
|
||||||
if (child == destination) destination = null;
|
if (child == destination) destination = null;
|
||||||
if (child == routeManager) routeManager = null;
|
if (child == routePrepper) routePrepper.stop();
|
||||||
cars.remove(child);
|
cars.remove(child);
|
||||||
trace.remove(child);
|
trace.remove(child);
|
||||||
super.removeChild(child);
|
super.removeChild(child);
|
||||||
@@ -758,21 +758,6 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
return tags().iterator();
|
return tags().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean reserveRouteAfter(Route route) {
|
|
||||||
LOG.debug("reserveRouteAfter({})",route);
|
|
||||||
if (isNull(routeManager)) routeManager = new RouteManager();
|
|
||||||
Context newContext = new Context(this).block(route.endBlock()).direction(route.endDirection);
|
|
||||||
if (routeManager.isSearching()) return false;
|
|
||||||
routeManager.setContext(newContext);
|
|
||||||
routeManager.setCallback(new Callback() {
|
|
||||||
@Override
|
|
||||||
public void routePrepared(Route nextRoute) {
|
|
||||||
route.setNextPreparedRoute(nextRoute);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return routeManager.prepareRoute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This turns the train as if it went through a loop. Example:
|
* This turns the train as if it went through a loop. Example:
|
||||||
* before: CabCar→ MiddleCar→ Loco→
|
* before: CabCar→ MiddleCar→ Loco→
|
||||||
@@ -921,24 +906,20 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
nextPreparedRoute = null;
|
nextPreparedRoute = null;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (isNull(routeManager)) routeManager = new RouteManager();
|
if (isSet(routePrepper)) return t("Already searching route for {}",this);
|
||||||
|
routePrepper = new RoutePrepper(new Context(this).block(currentBlock).direction(direction));
|
||||||
|
|
||||||
Callback callback = new Callback() {
|
routePrepper.onRoutePrepared(() -> {
|
||||||
@Override
|
routePrepper.route().start();
|
||||||
public void routePrepared(Route route) {
|
routePrepper = null;
|
||||||
route.start();
|
plan.stream(t("Started {}",Train.this));
|
||||||
plan.stream(t("Started {}",Train.this));
|
});
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (routeManager.isActive()) { // es wird bereits eine Anschlussroute gesucht
|
routePrepper.onFail(() -> {
|
||||||
// in diesem Fall muss bloß dass Callback des Route-Managers aktualisiert werden
|
routePrepper = null;
|
||||||
routeManager.setCallback(callback);
|
});
|
||||||
} else { // routeManager nicht aktiv →> neuen Context setzen und starten
|
|
||||||
routeManager.setContext(new Context(this).block(currentBlock).direction(direction));
|
|
||||||
routeManager.start(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
routePrepper.start();
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -950,7 +931,7 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
|
|
||||||
public void startBrake() {
|
public void startBrake() {
|
||||||
LOG.debug("{}.startBrake()",this);
|
LOG.debug("{}.startBrake()",this);
|
||||||
if (isSet(nextPreparedRoute)) return;
|
if (autopilot && isSet(nextPreparedRoute)) return;
|
||||||
brake = new BrakeProcess(this);
|
brake = new BrakeProcess(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,45 +1,42 @@
|
|||||||
package de.srsoftware.web4rail.threads;
|
package de.srsoftware.web4rail.threads;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import de.srsoftware.web4rail.Application;
|
import de.srsoftware.web4rail.Application;
|
||||||
import de.srsoftware.web4rail.BaseClass;
|
import de.srsoftware.web4rail.BaseClass;
|
||||||
|
import de.srsoftware.web4rail.EventListener;
|
||||||
import de.srsoftware.web4rail.Plan.Direction;
|
import de.srsoftware.web4rail.Plan.Direction;
|
||||||
import de.srsoftware.web4rail.Route;
|
import de.srsoftware.web4rail.Route;
|
||||||
import de.srsoftware.web4rail.moving.Train;
|
import de.srsoftware.web4rail.moving.Train;
|
||||||
import de.srsoftware.web4rail.tiles.Block;
|
import de.srsoftware.web4rail.tiles.Block;
|
||||||
import de.srsoftware.web4rail.tiles.Tile;
|
import de.srsoftware.web4rail.tiles.Tile;
|
||||||
|
|
||||||
public class RouteManager extends BaseClass {
|
public class RoutePrepper extends BaseClass implements Runnable{
|
||||||
|
private Context context;
|
||||||
|
private Route route;
|
||||||
|
private List<EventListener> failListeners = new LinkedList<>();
|
||||||
|
private List<EventListener> foundListeners = new LinkedList<>();
|
||||||
|
private List<EventListener> lockedListeners = new LinkedList<>();
|
||||||
|
private List<EventListener> preparedListeners= new LinkedList<>();
|
||||||
|
|
||||||
private enum State{
|
public RoutePrepper(Context c) {
|
||||||
IDLE,SEARCHING,PREPARING
|
List<String> errors = new LinkedList<>();
|
||||||
|
if (isNull(c.train())) errors.add(t("No train in context for {}",getClass().getSimpleName()));
|
||||||
|
if (isNull(c.block())) errors.add(t("No block in context for {}",getClass().getSimpleName()));
|
||||||
|
if (isNull(c.direction())) errors.add(t("No direction in context for {}",getClass().getSimpleName()));
|
||||||
|
if (!errors.isEmpty()) throw new NullPointerException(String.join(", ", errors));
|
||||||
|
context = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static abstract class Callback {
|
|
||||||
public abstract void routePrepared(Route route);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(RouteManager.class);
|
|
||||||
private Context ctx;
|
|
||||||
private State state;
|
|
||||||
private Callback callback;
|
|
||||||
|
|
||||||
public RouteManager() {
|
|
||||||
state =State.IDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TreeMap<Integer, List<Route>> availableRoutes(Context context, HashSet<Route> visitedRoutes) {
|
private static TreeMap<Integer, List<Route>> availableRoutes(Context context, HashSet<Route> visitedRoutes) {
|
||||||
String inset = "";
|
String inset = "";
|
||||||
for (int i = 0; i < visitedRoutes.size(); i++) inset += " ";
|
for (int i = 0; i < visitedRoutes.size(); i++) inset += " ";
|
||||||
LOG.debug("{}{}.availableRoutes({})", inset, RouteManager.class.getSimpleName(), context);
|
LOG.debug("{}{}.availableRoutes({})", inset, RoutePrepper.class.getSimpleName(), context);
|
||||||
|
|
||||||
Block block = context.block();
|
Block block = context.block();
|
||||||
Train train = context.train();
|
Train train = context.train();
|
||||||
@@ -135,9 +132,9 @@ public class RouteManager extends BaseClass {
|
|||||||
}
|
}
|
||||||
return availableRoutes;
|
return availableRoutes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Route chooseRoute(Context context) {
|
private static Route chooseRoute(Context context) {
|
||||||
LOG.debug("{}.chooseRoute({})", RouteManager.class.getSimpleName(), context);
|
LOG.debug("{}.chooseRoute({})", RoutePrepper.class.getSimpleName(), context);
|
||||||
TreeMap<Integer, List<Route>> availableRoutes = availableRoutes(context, new HashSet<Route>());
|
TreeMap<Integer, List<Route>> availableRoutes = availableRoutes(context, new HashSet<Route>());
|
||||||
while (!availableRoutes.isEmpty()) {
|
while (!availableRoutes.isEmpty()) {
|
||||||
if (context.invalidated()) break;
|
if (context.invalidated()) break;
|
||||||
@@ -158,63 +155,71 @@ public class RouteManager extends BaseClass {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isActive() {
|
|
||||||
return state != State.IDLE;
|
private void notify(List<EventListener> listeners) {
|
||||||
|
for (EventListener listener: listeners) {
|
||||||
|
listener.fire();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSearching() {
|
public void onFail(EventListener l) {
|
||||||
return state == State.SEARCHING;
|
failListeners.add(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onRouteFound(EventListener l) {
|
||||||
|
foundListeners.add(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRouteLocked(EventListener l) {
|
||||||
|
lockedListeners.add(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRoutePrepared(EventListener l) {
|
||||||
|
preparedListeners.add(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public boolean prepareRoute() {
|
public boolean prepareRoute() {
|
||||||
try {
|
try {
|
||||||
if (isNull(ctx) || ctx.invalidated()) return false;
|
if (isNull(context) || context.invalidated()) return false;
|
||||||
state = State.SEARCHING;
|
route = chooseRoute(context);
|
||||||
Route route = chooseRoute(ctx);
|
if (isNull(route)) return false;
|
||||||
if (isNull(route)) return false;
|
context.route(route);
|
||||||
ctx.route(route);
|
notify(foundListeners);
|
||||||
if (!route.reserveFor(ctx)) {
|
if (!route.reserveFor(context)) {
|
||||||
route.reset();
|
route.reset();
|
||||||
|
route = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
state = State.PREPARING;
|
notify(lockedListeners);
|
||||||
if (!route.prepareAndLock()) {
|
if (!route.prepareAndLock()) {
|
||||||
route.reset();
|
route.reset();
|
||||||
|
route = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (isNull(route) || isNull(callback)) return false;
|
notify(preparedListeners);
|
||||||
callback.routePrepared(route);
|
|
||||||
return true;
|
return true;
|
||||||
} finally {
|
} finally {
|
||||||
state = State.IDLE;
|
if (isNull(route)) notify(failListeners);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void quit() {
|
|
||||||
LOG.debug("{}.quit", this);
|
public Route route() {
|
||||||
callback = null;
|
return route;
|
||||||
if (isSet(ctx)) ctx.invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContext(Context context) {
|
|
||||||
ctx = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCallback(Callback callback) {
|
|
||||||
if (!ctx.invalidated()) this.callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start(Callback callback) {
|
|
||||||
setCallback(callback);
|
|
||||||
new Thread(Application.threadName(this)) {
|
|
||||||
public void run() {
|
|
||||||
prepareRoute();
|
|
||||||
};
|
|
||||||
}.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public void run() {
|
||||||
return getClass().getSimpleName() + "(" + ctx.train() + ")";
|
prepareRoute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
new Thread(this,Application.threadName(this)).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
context.invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user