Browse Source

added javadoc comments to some classes

lookup-tables
Stephan Richter 5 years ago
parent
commit
4441b012fa
  1. 2
      pom.xml
  2. 83
      src/main/java/de/srsoftware/web4rail/Application.java
  3. 63
      src/main/java/de/srsoftware/web4rail/Command.java
  4. 8
      src/main/java/de/srsoftware/web4rail/Constants.java
  5. 76
      src/main/java/de/srsoftware/web4rail/ControlUnit.java
  6. 50
      src/main/java/de/srsoftware/web4rail/Page.java
  7. 271
      src/main/java/de/srsoftware/web4rail/Plan.java

2
pom.xml

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>de.srsoftware</groupId>
<artifactId>web4rail</artifactId>
<version>0.7.12</version>
<version>0.7.13</version>
<name>Web4Rail</name>
<packaging>jar</packaging>
<description>Java Model Railway Control</description>

83
src/main/java/de/srsoftware/web4rail/Application.java

@ -32,10 +32,29 @@ import de.srsoftware.web4rail.moving.Car; @@ -32,10 +32,29 @@ import de.srsoftware.web4rail.moving.Car;
import de.srsoftware.web4rail.moving.Locomotive;
import de.srsoftware.web4rail.moving.Train;
/**
* Entry point class for the Web4Rail application
*
* @author Stephan Richter, SRSoftware
*
*/
public class Application implements Constants{
private static Plan plan;
private static Plan plan; // the track layout in use
private static final Logger LOG = LoggerFactory.getLogger(Application.class);
/**
* entry point for the application:<br/>
* creates a http server, loads a plan and directs a browser to the respective page
* @param args
* @throws IOException
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
* @throws NoSuchMethodException
* @throws SecurityException
*/
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
Configuration config = new Configuration(Configuration.dir("Web4Rail")+"/app.config");
LOG.debug("config: {}",config);
@ -55,6 +74,10 @@ public class Application implements Constants{ @@ -55,6 +74,10 @@ public class Application implements Constants{
Desktop.getDesktop().browse(URI.create("http://"+InetAddress.getLocalHost().getHostName()+":"+config.getInt(PORT)+"/plan"));
}
/**
* helper class creating unique ids for use throuout the application
* @return
*/
public static int createId() {
try {
Thread.sleep(1);
@ -64,6 +87,19 @@ public class Application implements Constants{ @@ -64,6 +87,19 @@ public class Application implements Constants{
return new Date().hashCode();
}
/**
* handles request from clients by delegating them to respective classes
* @param params
* @return
* @throws IOException
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
* @throws NoSuchMethodException
* @throws SecurityException
*/
private static Object handle(HashMap<String, String> params) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
String realm = params.get(REALM);
@ -94,6 +130,11 @@ public class Application implements Constants{ @@ -94,6 +130,11 @@ public class Application implements Constants{
return t("Unknown realm: {}",params.get(REALM));
}
/**
* creates a map from url-encoded data
* @param data
* @return
*/
private static HashMap<String, String> inflate(String data) {
//LOG.debug("inflate({})",data);
HashMap<String, String> params = new HashMap<String, String>();
@ -108,10 +149,21 @@ public class Application implements Constants{ @@ -108,10 +149,21 @@ public class Application implements Constants{
return params;
}
/**
* creates a map from url-encoded data
* @param data
* @return
*/
private static HashMap<String, String> inflate(byte[] data) {
return inflate(new String(data,UTF8));
}
/**
* sends a response generated from the application to a given client
* @param client
* @param response
* @throws IOException
*/
private static void send(HttpExchange client, Object response) throws IOException {
byte[] html;
if (response instanceof Page) {
@ -145,6 +197,13 @@ public class Application implements Constants{ @@ -145,6 +197,13 @@ public class Application implements Constants{
os.close();
}
/**
* sends an error to a given client
* @param client
* @param code
* @param msg
* @throws IOException
*/
private static void sendError(HttpExchange client, int code, String msg) throws IOException {
client.sendResponseHeaders(code, msg.length());
LOG.error(msg);
@ -153,6 +212,11 @@ public class Application implements Constants{ @@ -153,6 +212,11 @@ public class Application implements Constants{
out.close();
}
/**
* sends a requested file to the given client
* @param client
* @throws IOException
*/
private static void sendFile(HttpExchange client) throws IOException {
URI uri = client.getRequestURI();
File file = new File(System.getProperty("user.dir")+"/resources"+uri);
@ -170,6 +234,11 @@ public class Application implements Constants{ @@ -170,6 +234,11 @@ public class Application implements Constants{
sendError(client,404,t("Could not find \"{}\"",uri));
}
/**
* sends a response to a given client
* @param client
* @throws IOException
*/
private static void sendPlan(HttpExchange client) throws IOException {
try {
HashMap<String, String> params = inflate(client.getRequestBody().readAllBytes());
@ -189,6 +258,12 @@ public class Application implements Constants{ @@ -189,6 +258,12 @@ public class Application implements Constants{
send(client,new Page().append(e.getMessage()));
}
}
/**
* establishes an event stream connection between the application and a given client
* @param client
* @throws IOException
*/
private static void stream(HttpExchange client) throws IOException {
client.getResponseHeaders().set("content-type", "text/event-stream");
client.sendResponseHeaders(200, 0);
@ -196,6 +271,12 @@ public class Application implements Constants{ @@ -196,6 +271,12 @@ public class Application implements Constants{
plan.addClient(sseWriter);
}
/**
* shorthand for Translations.get(text,fills)
* @param text
* @param fills
* @return
*/
private static String t(String text, Object...fills) {
return Translation.get(Application.class, text, fills);
}

63
src/main/java/de/srsoftware/web4rail/Command.java

@ -7,18 +7,31 @@ import java.util.concurrent.TimeoutException; @@ -7,18 +7,31 @@ import java.util.concurrent.TimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* handles SRCP commands and their replies received from the SRCP daemon
* @author Stephan Richter, SRSoftware
*
*/
public class Command {
private static final Logger LOG = LoggerFactory.getLogger(Command.class);
private String command;
private Reply reply = null;
/**
* encapsulates a reply received from the SRCP daemon
*
*/
public static class Reply{
private long secs;
private int milis;
private int code;
private String message;
/**
* parses a reply from the SRCP daemon
* @param scanner
*/
public Reply(Scanner scanner) {
String word = scanner.next();
secs = Long.parseLong(word.substring(0, word.length()-4));
@ -28,6 +41,11 @@ public class Command { @@ -28,6 +41,11 @@ public class Command {
LOG.info("recv {}.{} {} {}.",secs,milis,code,message);
}
/**
* creates a reply with given data
* @param code
* @param message
*/
public Reply(int code, String message) {
secs = new Date().getTime();
milis = (int) (secs % 1000);
@ -36,14 +54,25 @@ public class Command { @@ -36,14 +54,25 @@ public class Command {
this.message = message;
}
/**
* checks if a response has a specific code
* @param code
* @return true if the given code equals the response's code
*/
public boolean is(int code) {
return code == this.code;
}
/**
* @return true, if the response code is between 200 and 300
*/
public boolean succeeded() {
return (code > 199 && code < 300);
}
/**
* @return the message passed along with the response from the SRCP deameon
*/
public String message() {
return message;
}
@ -54,15 +83,27 @@ public class Command { @@ -54,15 +83,27 @@ public class Command {
}
}
/**
* encapsulates a command to be send to the SRCP daemon
* @param command
*/
public Command(String command) {
this.command = command;
LOG.debug("Created new Command({}).",command);
}
/**
* called, if the response indicates an error
* @param reply
*/
protected void onFailure(Reply reply) {
LOG.warn("onFailure({})",command);
}
/**
* called, when a response from the SRCP daemon is received
* @param reply
*/
public void onResponse(Reply reply) {
this.reply = reply;
if (reply.succeeded()) {
@ -70,18 +111,36 @@ public class Command { @@ -70,18 +111,36 @@ public class Command {
} else onFailure(reply);
}
/**
* called, when the response from the SRCP daemon indicates success of the operation
*/
public void onSuccess(){
LOG.debug("onSuccess({})",command);
}
/**
* parses the reply from the SRCP daemon
* @param scanner
*/
public void readReplyFrom(Scanner scanner) {
onResponse(new Reply(scanner));
}
/**
* waits for the reply from the SRCP daemon for one second
* @return
* @throws TimeoutException
*/
public Reply reply() throws TimeoutException {
return reply(100);
}
/**
* waits for the reply from the SRCP daemon for a given timeout
* @param timeout time (in 10ms units) to wait, before a timeout is thrown
* @return
* @throws TimeoutException
*/
public Reply reply(int timeout) throws TimeoutException {
int counter = 0;
while (reply == null) try {
@ -93,6 +152,10 @@ public class Command { @@ -93,6 +152,10 @@ public class Command {
return reply;
}
/**
* generate a timeout exception
* @throws TimeoutException
*/
private void timeout() throws TimeoutException {
String msg = command;
command = null;

8
src/main/java/de/srsoftware/web4rail/Constants.java

@ -3,6 +3,14 @@ package de.srsoftware.web4rail; @@ -3,6 +3,14 @@ package de.srsoftware.web4rail;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import de.keawe.tools.translations.Translation;
/**
* this interface collects constants inherited to other classes of this application
*
* @author Stephan Richter, SRSoftware
*
*/
public interface Constants {
public static final String ACTION = "action";
public static final String ACTION_ADD = "add";

76
src/main/java/de/srsoftware/web4rail/ControlUnit.java

@ -23,6 +23,12 @@ import de.srsoftware.web4rail.tags.Form; @@ -23,6 +23,12 @@ import de.srsoftware.web4rail.tags.Form;
import de.srsoftware.web4rail.tags.Input;
import de.srsoftware.web4rail.tags.Label;
/**
* abstraction of a SRCP daemon (control unit)
*
* @author Stephan Richter, SRSoftware
*
*/
public class ControlUnit extends Thread implements Constants{
private static final Logger LOG = LoggerFactory.getLogger(ControlUnit.class);
private static final String DEFAULT_HOST = "localhost";
@ -53,6 +59,11 @@ public class ControlUnit extends Thread implements Constants{ @@ -53,6 +59,11 @@ public class ControlUnit extends Thread implements Constants{
return this;
}
/**
* performs a handshake as specified in the SRCP protocol
* @throws TimeoutException
* @throws IOException
*/
private void handshake() throws TimeoutException, IOException {
String proto = null;
if (scanner.hasNext()) {
@ -79,6 +90,9 @@ public class ControlUnit extends Thread implements Constants{ @@ -79,6 +90,9 @@ public class ControlUnit extends Thread implements Constants{
if (!command.reply().succeeded()) throw new IOException("Handshake failed: "+command.reply());
}
/**
* @return json string containing the connection information
*/
private JSONObject json() {
JSONObject json = new JSONObject();
json.put(HOST, host);
@ -87,6 +101,11 @@ public class ControlUnit extends Thread implements Constants{ @@ -87,6 +101,11 @@ public class ControlUnit extends Thread implements Constants{
return json;
}
/**
* load connection information from file
* @param filename
* @throws IOException
*/
public void load(String filename) throws IOException {
BufferedReader file = new BufferedReader(new FileReader(filename));
JSONObject json = new JSONObject(file.readLine());
@ -96,6 +115,11 @@ public class ControlUnit extends Thread implements Constants{ @@ -96,6 +115,11 @@ public class ControlUnit extends Thread implements Constants{
if (json.has(HOST)) host = json.getString(HOST);
}
/**
* test method
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
ControlUnit cu = new ControlUnit(null).setEndpoint("Modellbahn", DEFAULT_PORT).setBus(1).restart();
Thread.sleep(1000);
@ -116,6 +140,11 @@ public class ControlUnit extends Thread implements Constants{ @@ -116,6 +140,11 @@ public class ControlUnit extends Thread implements Constants{
cu.end();
}
/**
* process actions related to the SRCP daemon
* @param params
* @return
*/
public Object process(HashMap<String, String> params) {
switch (params.get(ACTION)) {
case ACTION_CONNECT:
@ -134,11 +163,19 @@ public class ControlUnit extends Thread implements Constants{ @@ -134,11 +163,19 @@ public class ControlUnit extends Thread implements Constants{
return t("Unknown action: {}",params.get(ACTION));
}
/**
* turn of power immediately
* @return
*/
public Object emergency() {
power = true;
return togglePower();
}
/**
* generate a properties view for the client
* @return
*/
public Object properties() {
Window win = new Window("cu-props", t("Properties of the control unit"));
Form form = new Form();
@ -155,6 +192,11 @@ public class ControlUnit extends Thread implements Constants{ @@ -155,6 +192,11 @@ public class ControlUnit extends Thread implements Constants{
return win;
}
/**
* add a command to the queue of commands to be sent to the server
* @param command
* @return
*/
public Command queue(Command command) {
queue.add(command);
return command;
@ -170,6 +212,9 @@ public class ControlUnit extends Thread implements Constants{ @@ -170,6 +212,9 @@ public class ControlUnit extends Thread implements Constants{
return this;
}
/**
* thread, that repeatedly checks the queue for new commands and sends them to the SRCP daemon
*/
@Override
public void run() {
while (!stopped) {
@ -191,6 +236,11 @@ public class ControlUnit extends Thread implements Constants{ @@ -191,6 +236,11 @@ public class ControlUnit extends Thread implements Constants{
}
}
/**
* save settings to file
* @param filename
* @throws IOException
*/
public void save(String filename) throws IOException {
BufferedWriter file = new BufferedWriter(new FileWriter(filename));
file.write(json()+"\n");
@ -211,11 +261,22 @@ public class ControlUnit extends Thread implements Constants{ @@ -211,11 +261,22 @@ public class ControlUnit extends Thread implements Constants{
command.readReplyFrom(scanner);
}
/**
* defines the bus on the SRCP deamon, to which commands shall be assigned
* @param bus
* @return
*/
private ControlUnit setBus(int bus) {
this.bus = bus;
return this;
}
/**
* set up the connection endpoint
* @param newHost
* @param newPort
* @return
*/
public ControlUnit setEndpoint(String newHost, int newPort){
host = newHost;
port = newPort;
@ -235,10 +296,20 @@ public class ControlUnit extends Thread implements Constants{ @@ -235,10 +296,20 @@ public class ControlUnit extends Thread implements Constants{
super.start();
}
/**
* shorthand for Translation.get(text,fills)
* @param text
* @param fills
* @return
*/
private static String t(String text,Object...fills) {
return Translation.get(Application.class, text, fills);
}
/**
* togge power on/off at the SRCP daemon
* @return
*/
private Command togglePower() {
power = !power;
String PW = power?"ON":"OFF";
@ -259,6 +330,11 @@ public class ControlUnit extends Thread implements Constants{ @@ -259,6 +330,11 @@ public class ControlUnit extends Thread implements Constants{
}
/**
* update connection parameters
* @param params
* @return
*/
public String update(HashMap<String, String> params) {
if (params.containsKey(HOST)) host = params.get(HOST);
if (params.containsKey(PORT)) port = Integer.parseInt(params.get(PORT));

50
src/main/java/de/srsoftware/web4rail/Page.java

@ -4,8 +4,12 @@ import java.util.Vector; @@ -4,8 +4,12 @@ import java.util.Vector;
import de.srsoftware.tools.Tag;
/**
*
* helper class to create html pages
* @author Stephan Richter, SRSoftware
*
*/
public class Page {
private StringBuffer buf;
private Vector<String> cssFiles = new Vector<String>();
@ -15,11 +19,19 @@ public class Page { @@ -15,11 +19,19 @@ public class Page {
buf = new StringBuffer();
}
@Override
public String toString() {
return head().append(body(buf)).toString();
public Page append(Object code) {
buf.append(code);
return this;
}
private StringBuffer body(StringBuffer content) {
return new StringBuffer()
.append("\t<body>\n")
.append(content)
.append("\t</body>\n")
.append("</html>\n");
}
private StringBuffer head() {
StringBuffer sb = new StringBuffer()
.append("<html>\n")
@ -33,31 +45,23 @@ public class Page { @@ -33,31 +45,23 @@ public class Page {
}
return sb.append("\t</head>\n");
}
private StringBuffer body(StringBuffer content) {
return new StringBuffer()
.append("\t<body>\n")
.append(content)
.append("\t</body>\n")
.append("</html>\n");
}
public StringBuffer html() {
return head().append(body(buf));
}
public Page append(Object code) {
buf.append(code);
public Page js(String jsPath) {
jsFiles.add(jsPath);
return this;
}
public Page style(String cssPath) {
cssFiles.add(cssPath);
return this;
}
public Page js(String jsPath) {
jsFiles.add(jsPath);
return this;
@Override
public String toString() {
return head().append(body(buf)).toString();
}
}

271
src/main/java/de/srsoftware/web4rail/Plan.java

@ -58,7 +58,21 @@ import de.srsoftware.web4rail.tiles.TurnoutRN; @@ -58,7 +58,21 @@ import de.srsoftware.web4rail.tiles.TurnoutRN;
import de.srsoftware.web4rail.tiles.TurnoutRS;
import de.srsoftware.web4rail.tiles.TurnoutRW;
/**
* This class is a central part of the Application, as it loads, holds and saves all kinds of information:
* <ul>
* <li>Tack layout</li>
* <li>Trains and Cars</li>
* <li>Routes</li>
* <li>...</li>
* </ul>
* @author Stephan Richter, SRSoftware
*
*/
public class Plan implements Constants{
/**
* The four directions Trains can be within blocks
*/
public enum Direction{
NORTH, SOUTH, EAST, WEST;
@ -73,6 +87,9 @@ public class Plan implements Constants{ @@ -73,6 +87,9 @@ public class Plan implements Constants{
}
}
/**
* This thread sends a heartbea to the client
*/
private class Heartbeat extends Thread {
@Override
public void run() {
@ -96,15 +113,31 @@ public class Plan implements Constants{ @@ -96,15 +113,31 @@ public class Plan implements Constants{
private static final HashMap<OutputStreamWriter,Integer> clients = new HashMap<OutputStreamWriter, Integer>();
private static final String ACTION_QR = "qrcode";
public HashMap<String,Tile> tiles = new HashMap<String,Tile>();
private HashSet<Block> blocks = new HashSet<Block>();
private HashMap<Integer, Route> routes = new HashMap<Integer, Route>();
private ControlUnit controlUnit = new ControlUnit(this);
public HashMap<String,Tile> tiles = new HashMap<String,Tile>(); // The list of tiles of this plan, i.e. the Track layout
private HashSet<Block> blocks = new HashSet<Block>(); // the list of tiles, that are blocks
private HashMap<Integer, Route> routes = new HashMap<Integer, Route>(); // the list of routes of the track layout
private ControlUnit controlUnit = new ControlUnit(this); // the control unit, to which the plan is connected
/**
* creates a new plan, starts to send heart beats
*/
public Plan() {
new Heartbeat().start();
}
/**
* manages plan-related commands
* @param params the parameters passed from the client
* @return Object returned to the client
* @throws IOException
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
* @throws NoSuchMethodException
* @throws SecurityException
*/
public Object action(HashMap<String, String> params) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
switch (params.get(ACTION)) {
case ACTION_ADD:
@ -123,6 +156,11 @@ public class Plan implements Constants{ @@ -123,6 +156,11 @@ public class Plan implements Constants{
return t("Unknown action: {}",params.get(ACTION));
}
/**
* generates the action menu that is appended to the plan
* @return
* @throws IOException
*/
private Tag actionMenu() throws IOException {
Tag actionMenu = new Tag("div").clazz("actions").content(t("Actions"));
Tag actions = new Tag("div").clazz("list").content("");
@ -133,17 +171,45 @@ public class Plan implements Constants{ @@ -133,17 +171,45 @@ public class Plan implements Constants{
return actions.addTo(actionMenu);
}
/**
* attaches a new client to the event stream of the plan
* @param client
*/
public void addClient(OutputStreamWriter client) {
LOG.debug("Client connected.");
clients.put(client, 0);
}
/**
* helper function: creates a list element with a link that will call the <it>clickTile</it> function of the client side javascript.
* @param tile the tile a click on which shall be simulated
* @param content the text to be displayed to the user
* @param list the tag to which the link tag shall be added
* @return returns the list element itself
* TODO: replace occurences by calls to <it>return request({...});</li>, then remove clickTile from the client javascript
*/
public static Tag addLink(Tile tile,String content,Tag list) {
Tag li = new Tag("li");
new Tag("span").clazz("link").attr("onclick", "return clickTile("+tile.x+","+tile.y+");").content(content).addTo(li).addTo(list);
return li;
}
/**
* add a tile of the specified class to the track layout
* @param clazz
* @param xs
* @param ys
* @param configJson
* @return
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
* @throws NoSuchMethodException
* @throws SecurityException
* @throws IOException
*/
private String addTile(String clazz, String xs, String ys, String configJson) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, IOException {
int x = Integer.parseInt(xs);
int y = Integer.parseInt(ys);
@ -161,6 +227,10 @@ public class Plan implements Constants{ @@ -161,6 +227,10 @@ public class Plan implements Constants{
return t("Added {}",tile.getClass().getSimpleName());
}
/**
* search all possible routes in the plan
* @return a string giving information how many routes have been found
*/
private String analyze() {
Vector<Route> routes = new Vector<Route>();
for (Block block : blocks) {
@ -175,19 +245,38 @@ public class Plan implements Constants{ @@ -175,19 +245,38 @@ public class Plan implements Constants{
return t("Found {} routes.",routes.size());
}
/**
* @return the list of blocks known to the plan
*/
public Collection<Block> blocks() {
return blocks;
}
/**
* calls tile.click()
* @param tile
* @return
* @throws IOException
*/
private Object click(Tile tile) throws IOException {
if (tile == null) return null;
return tile.click();
}
/**
* @return the control unit currently connected to the plan
*/
public ControlUnit controlUnit() {
return controlUnit;
}
/**
* completes a given route during a call to {@link #analyze()}.
* It therefore traces where the current part of the route comes from and where it may go.
* @param route an incomplete route, that shall be completed
* @param connector
* @return the set of routes, that result from the tracing operation
*/
private Collection<Route> follow(Route route, Connector connector) {
Tile tile = get(Tile.id(connector.x,connector.y),false);
Vector<Route> results = new Vector<>();
@ -209,7 +298,6 @@ public class Plan implements Constants{ @@ -209,7 +298,6 @@ public class Plan implements Constants{
}
Map<Connector, State> connectors = tile.connections(connector.from);
List<Route>routes = route.multiply(connectors.size());
LOG.debug("{}",tile);
if (connectors.size()>1) LOG.debug("SPLITTING @ {}",tile);
for (Entry<Connector, State> entry: connectors.entrySet()) {
@ -223,6 +311,12 @@ public class Plan implements Constants{ @@ -223,6 +311,12 @@ public class Plan implements Constants{
return results;
}
/**
* returns the tile referenced by the tile id
* @param tileId a combination of the coordinates of the requested tile
* @param resolveShadows if this is set to true, this function will return the overlaying tiles, if the id belongs to a shadow tile.
* @return the tile belonging to the id, or the overlaying tile if the respective tile is a shadow tile.
*/
public Tile get(String tileId,boolean resolveShadows) {
Tile tile = tiles.get(tileId);
if (resolveShadows && tile instanceof Shadow) tile = ((Shadow)tile).overlay();
@ -230,6 +324,11 @@ public class Plan implements Constants{ @@ -230,6 +324,11 @@ public class Plan implements Constants{
}
/**
* generates the hardware menu attached to the plan
* @return
* @throws IOException
*/
private Tag hardwareMenu() throws IOException {
Tag tileMenu = new Tag("div").clazz("hardware").content(t("Hardware"));
Tag list = new Tag("div").clazz("list").content("");
@ -237,14 +336,26 @@ public class Plan implements Constants{ @@ -237,14 +336,26 @@ public class Plan implements Constants{
return list.addTo(tileMenu);
}
/**
* prepares the hardware div of the plan
* @return
*/
private Tag heartbeat() {
return new Div("heartbeat").content("");
}
/**
* send a heatbeat to the client
*/
public void heatbeat() {
stream("heartbeat @ "+new Date().getTime());
}
/**
* generates a html document of this plan
* @return
* @throws IOException
*/
public Page html() throws IOException {
Page page = new Page().append("<div id=\"plan\">");
for (Tile tile: tiles.values()) {
@ -261,6 +372,19 @@ public class Plan implements Constants{ @@ -261,6 +372,19 @@ public class Plan implements Constants{
.js("js/plan.js");
}
/**
* loads a track layout from a file, along with its assigned cars, trains, routes and control unit settings
* @param filename
* @return
* @throws IOException
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
* @throws NoSuchMethodException
* @throws SecurityException
*/
public static Plan load(String filename) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
Plan plan = new Plan();
try {
@ -292,6 +416,11 @@ public class Plan implements Constants{ @@ -292,6 +416,11 @@ public class Plan implements Constants{
return plan;
}
/**
* creates the main menu attached to the plan
* @return
* @throws IOException
*/
private Tag menu() throws IOException {
Tag menu = new Tag("div").clazz("menu");
new Tag("div").clazz("emergency").content(t("Emergency")).attr("onclick","return request({realm:'"+REALM_CU+"',action:'"+ACTION_EMERGENCY+"'});").addTo(menu);
@ -303,10 +432,18 @@ public class Plan implements Constants{ @@ -303,10 +432,18 @@ public class Plan implements Constants{
return menu;
}
/**
* prepares the messages div of the plan
* @return
*/
private Tag messages() {
return new Div("messages").content("");
}
/**
* creates the move-tile menu of the plan
* @return
*/
private Tag moveMenu() {
Tag tileMenu = new Tag("div").clazz("move").title(t("Move tiles")).content(t("↹"));
Tag tiles = new Tag("div").clazz("list").content("");
@ -317,6 +454,14 @@ public class Plan implements Constants{ @@ -317,6 +454,14 @@ public class Plan implements Constants{
return tiles.addTo(tileMenu);
}
/**
* processes move-tile instructions sent from the client
* @param direction
* @param tileId
* @return
* @throws NumberFormatException
* @throws IOException
*/
private String moveTile(String direction, String tileId) throws NumberFormatException, IOException {
switch (direction) {
case "south":
@ -331,6 +476,13 @@ public class Plan implements Constants{ @@ -331,6 +476,13 @@ public class Plan implements Constants{
throw new InvalidParameterException(t("\"{}\" is not a known direction!"));
}
/**
* processes move-tile instructions sent from the client (subroutine)
* @param tile
* @param direction
* @return
* @throws IOException
*/
private String moveTile(Tile tile, Direction direction) throws IOException {
boolean moved = false;
if (tile != null) {
@ -353,6 +505,14 @@ public class Plan implements Constants{ @@ -353,6 +505,14 @@ public class Plan implements Constants{
return t(moved ? "Tile(s) moved.":"No tile(s) moved.");
}
/**
* processes move-tile instructions sent from the client (subroutine)
* @param tile
* @param xstep
* @param ystep
* @return
* @throws IOException
*/
private boolean moveTile(Tile tile,int xstep,int ystep) throws IOException {
LOG.error("moveTile({} +{}/+{})",tile,xstep,ystep);
Stack<Tile> stack = new Stack<Tile>();
@ -372,29 +532,53 @@ public class Plan implements Constants{ @@ -372,29 +532,53 @@ public class Plan implements Constants{
return false;
}
/**
* adds a new tile to the plan on the client side
* @param tile
* @return
* @throws IOException
*/
public Tile place(Tile tile) throws IOException {
stream("place "+tile.tag(null));
return tile;
}
/**
* adds a command to the control unit's command queue
* @param command
* @return
*/
public Command queue(Command command) {
return controlUnit.queue(command);
}
/**
* adds a new route to the plan
* @param route
* @return
*/
Route registerRoute(Route route) {
for (Tile tile: route.path()) tile.add(route);
routes.put(route.id(), route);
return route;
}
/**
* removes a tile from the track layout
* @param tile
*/
private void remove(Tile tile) {
remove_intern(tile.x,tile.y);
removeTile(tile.x,tile.y);
if (tile instanceof Block) blocks.remove(tile);
for (int i=1; i<tile.len(); i++) remove_intern(tile.x+i, tile.y); // remove shadow tiles
for (int i=1; i<tile.height(); i++) remove_intern(tile.x, tile.y+i); // remove shadow tiles
for (int i=1; i<tile.len(); i++) removeTile(tile.x+i, tile.y); // remove shadow tiles
for (int i=1; i<tile.height(); i++) removeTile(tile.x, tile.y+i); // remove shadow tiles
if (tile != null) stream("remove "+tile.id());
}
/**
* removes a route from the track layout
* @param route
*/
public void remove(Route route) {
for (Tile tile : route.path()) tile.remove(route);
for (Train train : Train.list()) {
@ -404,10 +588,20 @@ public class Plan implements Constants{ @@ -404,10 +588,20 @@ public class Plan implements Constants{
stream(t("Removed {}.",route));
}
private void remove_intern(int x, int y) {
/**
* removes a tile from the track layout (subroutine)
* @param x
* @param y
*/
private void removeTile(int x, int y) {
LOG.debug("removed {} from tile list",tiles.remove(Tile.id(x, y)));
}
/**
* returns a specific route from the list of routes assigned to this plan
* @param routeId the id of the route requestd
* @return
*/
public Route route(int routeId) {
return routes.get(routeId);
}
@ -425,6 +619,12 @@ public class Plan implements Constants{ @@ -425,6 +619,12 @@ public class Plan implements Constants{
return t("Unknown action: {}",params.get(ACTION));
}
/**
* saves the plan to a set of files, along with its cars, tiles, trains, routes and control unit settings
* @param name
* @return
* @throws IOException
*/
private String saveTo(String name) throws IOException {
if (name == null || name.isEmpty()) throw new NullPointerException("Name must not be empty!");
Car.saveAll(name+".cars");
@ -435,20 +635,38 @@ public class Plan implements Constants{ @@ -435,20 +635,38 @@ public class Plan implements Constants{
return t("Plan saved as \"{}\".",name);
}
/**
* adds a tile to the plan at a specific position
* @param x
* @param y
* @param tile
* @throws IOException
*/
public void set(int x,int y,Tile tile) throws IOException {
if (tile == null) return;
if (tile instanceof Block) blocks.add((Block) tile);
for (int i=1; i<tile.len(); i++) set(x+i,y,new Shadow(tile));
for (int i=1; i<tile.height(); i++) set(x,y+i,new Shadow(tile));
set_intern(x,y,tile);
setIntern(x,y,tile);
place(tile);
}
private void set_intern(int x, int y, Tile tile) {
/**
* adds a tile to the plan at a specific position (subroutine)
* @param x
* @param y
* @param tile
*/
private void setIntern(int x, int y, Tile tile) {
tile.position(x, y).plan(this);
tiles.put(tile.id(),tile);
}
/**
* shows the properties of an entity specified in the params.context value
* @param params
* @return
*/
public Window showContext(HashMap<String, String> params) {
String[] parts = params.get(CONTEXT).split(":");
String realm = parts[0];
@ -460,6 +678,10 @@ public class Plan implements Constants{ @@ -460,6 +678,10 @@ public class Plan implements Constants{
return null;
}
/**
* sends some data to the clients
* @param data
*/
public synchronized void stream(String data) {
data = data.replaceAll("\n", "").replaceAll("\r", "");
//if (!data.startsWith("heartbeat")) LOG.debug("streaming: {}",data);
@ -488,10 +710,21 @@ public class Plan implements Constants{ @@ -488,10 +710,21 @@ public class Plan implements Constants{
}
}
/**
* shorthand for Translations.get(message,fills)
* @param message
* @param fills
* @return
*/
private String t(String message, Object...fills) {
return Translation.get(Application.class, message, fills);
}
/**
* generates the menu for selecting tiles to be added to the layout
* @return
* @throws IOException
*/
private Tag tileMenu() throws IOException {
Tag tileMenu = new Tag("div").clazz("addtile").title(t("Add tile")).content("╦");
@ -529,6 +762,11 @@ public class Plan implements Constants{ @@ -529,6 +762,11 @@ public class Plan implements Constants{
return tiles.addTo(tileMenu);
}
/**
* generates the train menu
* @return
* @throws IOException
*/
private Tag trainMenu() throws IOException {
Tag tileMenu = new Tag("div").clazz("trains").content(t("Trains"));
Tag tiles = new Tag("div").clazz("list").content("");
@ -537,10 +775,21 @@ public class Plan implements Constants{ @@ -537,10 +775,21 @@ public class Plan implements Constants{
return tiles.addTo(tileMenu);
}
/**
* updates a tile
* @param tile
* @param params
* @return
* @throws IOException
*/
private Tile update(Tile tile, HashMap<String, String> params) throws IOException {
return tile == null ? null : tile.update(params);
}
/**
* sends a Ghost train warning to the client
* @param contact
*/
public void warn(Contact contact) {
stream(t("Warning: {}",t("Ghost train @ {}",contact)));
}

Loading…
Cancel
Save