-
Notifications
You must be signed in to change notification settings - Fork 0
The Request Class
The Request itself is its own Object where the "magic is happening" (creating and converting osm and map Files to the users liking).
For that, it uses the following environmental Tools :
These need to be installed! (If they are not, incoming requests will always end up throwing an Error. So please make sure to follow the Set Up first)
Name | Type | Standard Value | Description | Authors Note |
---|---|---|---|---|
coordinates | List | null (defined in Constructor) | Coordiantes used for the map boundaries | |
date | String | null (defined in Constructor) | requested map date | |
mapName | String | null (defined in Constructor) | individual mapName | |
requestedByID | String | null (defined in Constructor) | id that requested this request | |
startTime | LocalDateTime | LocalDateTime.now() | Time the Request was Created | |
runtimeStart | LocalDateTime | null | Time the Request was started | |
endTime | LocalDateTime | null | Time the Request was stopped or ran out | |
status | QueryRequestStatus | QueryRequestStatus.REQUESTED | status of the Request | |
errorMessage | String | "" | error mEssage of the Request (if empty then there is no error message to be found) | |
TAG | String | null (defined in Constructor) | TAG for the Logger | |
LOG | String | "" | LOG temporary String holder for the ".req" | |
osmDir | String | null (defined in Constructor) | Path, where the ".osm" File will be saved | |
mapDir | String | null (defined in Constructor) | Path where the ".map" File will be saved | |
sLogDir | String | null (defined in Constructor) | ".req" save File Path | |
renderingParameter | String | null (defined in Constructor) | renderingParameter File for the rendering of the osm file | |
ohdmConverter | String | null (defined in Constructor) | ohdmConverter path for the download of the osm map | |
javaJdkPath | String | null (defined in Constructor) | javaJdkPath for the execution of enviromental Tools that use java | |
jdbcDriverPath | String | null (defined in Constructor) | jdbcDriver for the OHDMConverter | |
individualLogFile | String | null (defined in Constructor) | individualLogFile name | |
stopThread | boolean | false | shows if the thread is stopped |
This object itself has 5 different kinds of States it can be in:
- REQUESTED
- just got Requested from the App or the Browser
- not yet started
- already created the individualLogFile (".req" File) for the Request
- DOWNLOADING
- just started (has a runtimeStart)
- just updated the individualLogFile
- just started, can be stopped
- currently using the OHDMConverter / OSMImportTool to download the osm File
- CONVERTING
- currently converting the downloaded .osm File to a usable .map File for the App to use
- .osm can already be downloaded from the website
- DONE
- The Request is done (has an endTime now)
- .osm and .map file were successfully created and now downloadable
- the Error String is empty
- the individual logFile will not be touched from now on
- the Thread has stopped
- ERROR
- The Request encountered an fatal Error during the download or conversion process (has an endTime now)
- the .map File will not be available ( the .osm file could be available if the Error occured in the Convertion process)
- the Error String is filled with the occured error full stacktrace
- the individual logFile will not be touched from now on
- the Thread has stopped
public QueryRequest(List<Coords> coordinates, String date, String mapName, String id, String osmDir, String mapDir, String sLogDir, String renderingParameter, String ohdmConverter, String javaJdkPath, String jdbcDriverPath) {
this.osmDir = osmDir;
this.mapDir = mapDir;
this.sLogDir = sLogDir;
this.renderingParameter = renderingParameter;
this.ohdmConverter = ohdmConverter;
this.javaJdkPath = javaJdkPath;
this.jdbcDriverPath = jdbcDriverPath;
this.coordinates = coordinates;
this.date = date;
this.mapName = mapName;
this.requestedByID = id;
this.individualLogFile = sLogDir + "/" + mapName + ".req";
TAG = mapName + "_" + getRequestedByID() + "-Thread";
}
The Enviromental Code Execution is one of the parts that shows the basis of what is maybe to come in this current project. It shows how to properly use outside tools to execute and influence the current Thread. For the execution of "Outside Tools" and the processing of the retun values, the Method "execCommadn" war written.
The main thing it does is this :
Process p = null;
p = Runtime.getRuntime.exec(command);
p.waitFor();
So it gets the enviromental runtime and executes a specific command wich gives back a process that is running. After that, the curren Thread is forced to wait, till this Process is done.
Authors Note: This excCommand() Method can be reused everywhere! You can get the input-streams of the process to get the outputs of it. You can also do many other things with the "Process Object". Try it four yourself, it's fun.
These two Methods are used, to run specific Commands with the before mentioned Enviromental Tool Execution (ETE) Method.
Basically the follwing 2 steps are taken to execute the two tools ( OHDMConverter / osmosis ) :
-
A template is created with the needed inputs for the ETE
-
download_map
String[] template = new String[]{javaJdkPath, "-classpath", jdbcDriverPath, "-jar", ohdmConverter, "-o", osmDir + "/" + mapName + ".osm", "-r", renderingParameter, "-p", rearrangeCoordsForScript(getCoordinates()), "-t", date};
-
convert_map
String[] template = new String[]{"/opt/osmosis/bin/osmosis", "--rx", "file=" + osmDir + "/" + mapName + ".osm", "--mw", "file=" + mapDir + "/" + mapName + ".map"};
-
-
the tempalte is then given to ETE and the results are then taken and put into the result Object (CommandReturn)
result = excCommand(template); assert result != null; Logger.instance.addLogEntry(LogType.INFO, TAG,"output: " + result.output); Logger.instance.addLogEntry(LogType.ERROR, TAG,"error: " + result.errOutput); Logger.instance.addLogEntry(LogType.INFO, TAG,"return code: " + result.returnCode); LOG += "map : \noutput : " + result.output + "\n"; LOG += "error : " + result.errOutput + "\n"; LOG += "return code : "+result.returnCode + "\n\n"; return result;
@Override
public void run() {
// setting the start time
runtimeStart = LocalDateTime.now();
try {
//Logger.instance.addLogEntry(LogType.INFO, TAG,"started request : " + date + " | " + getPrintableCoordsString());
// setting the status to "DOWNLOADING"
status = QueryRequestStatus.DOWNLOADING;
refreshIndivLogFile();
// declaring the Command returner ( here because of the scope of usage )
CommandReturn returnMessage = new CommandReturn(0, "", "", null);
try {
// calling the download_method app to start the map_download
// the return message is constructed in the download Method and is used here
returnMessage = download_map();
// In case the Method download_map was interrupted, because the Method "stopThread" was called.
// Then here the status will be set to error + the errorMessage will be set appropriately
// and the individual log file will be refreshed.
// After that, this Thread will be terminated
if (stopThread) {
status = QueryRequestStatus.ERROR;
endTime = LocalDateTime.now();
errorMessage = "Thread stopped manually";
refreshIndivLogFile();
return;
}
// Since some Tools use the error Output for Debugging purposes,
// the error will only be caught, if an Exception was thrown into the ErrorOutput.
// If the Exception is caught, the error message will be set accordingly to the errorOutput of the Process
// and the individual log file will be refreshed.
// After that, this Thread will be terminated
if (returnMessage.errOutput.contains("Exception")) {
errorMessage = returnMessage.errOutput;
status = QueryRequestStatus.ERROR;
endTime = LocalDateTime.now();
refreshIndivLogFile();
return;
}
// if any other exceptions where thrown, then these will be put into
// the error message and the the Thread will be terminated
} catch (Exception e) {
errorMessage = "Error in DOWNLOADING: " + returnMessage.errOutput;
endTime = LocalDateTime.now();
refreshIndivLogFile();
return;
} finally {
// whatever will happen, an update to the ".req" file will always happen
refreshIndivLogFile();
}
// after the download of the osm File was complete,
// this will be Logged and the status will be set to the next step
Logger.instance.addLogEntry(LogType.INFO, TAG,"download done - now converting");
status = QueryRequestStatus.CONVERTING;
try {
// calling the convert_map app to start the map conversion ( with osmosis )
// the return message is constructed in the download Method and is used here
returnMessage = convert_map();
// In case the Method download_map was interrupted, because the Method "stopThread" was called.
// Then here the status will be set to error + the errorMessage will be set appropriately
// and the individual log file will be refreshed.
// After that, this Thread will be terminated
if (stopThread) {
status = QueryRequestStatus.ERROR;
errorMessage = "Thread stopped manually";
endTime = LocalDateTime.now();
refreshIndivLogFile();
return;
}
// if any other exceptions where thrown, then these will be put into
// the error message and the the Thread will be terminated
} catch (Exception e) {
status = QueryRequestStatus.ERROR;
errorMessage = "Error in CONVERTING: " + returnMessage.errOutput + e.getStackTrace()[0];
endTime = LocalDateTime.now();
refreshIndivLogFile();
return;
} finally {
// whatever will happen, an update to the ".req" file will always happen
refreshIndivLogFile();
}
// If the last environmental Tool execution gave back some kind of error,
// this will be handled here
if (returnMessage.returnCode != 0) {
// the status will be set accordingly
status = QueryRequestStatus.ERROR;
// here the last return code will be processed
// the return code process is cookie-cut for this specific tool (osmosis)
// I hope that the return codes won't change
if (returnMessage.returnCode == -1) {
errorMessage = "ERROR in CONVERTING: File already exists. not overwriting it\n";
Logger.instance.addLogEntry(LogType.ERROR, TAG, errorMessage);
endTime = LocalDateTime.now();
refreshIndivLogFile();
return;
}
else if (returnMessage.returnCode == 2) {
errorMessage = "ERROR in CONVERTING: couldn't find File to convert";
Logger.instance.addLogEntry(LogType.ERROR, TAG, errorMessage);
endTime = LocalDateTime.now();
refreshIndivLogFile();
return;
// if the error code wasn't something normal or known
// the error will be logged here and put into the errorMessage as well
} else {
Logger.instance.addLogEntry(LogType.ERROR, TAG, "Error:" + returnMessage.errOutput + "\nOutput:" + returnMessage.output);
errorMessage = returnMessage.errOutput;
endTime = LocalDateTime.now();
refreshIndivLogFile();
return;
}
}
// if everything has gone good so far,
// the status will be set to DONE and the Thread will run out.
// of course the ".req" File will be updated
status = QueryRequestStatus.DONE;
endTime = LocalDateTime.now();
refreshIndivLogFile();
} catch (Exception e) {
// if any other exceptions where thrown, then these will be put into
// the error message and the the Thread will be terminated
status = QueryRequestStatus.ERROR;
Logger.instance.addLogEntry(LogType.ERROR, TAG, "Error:" + e.getStackTrace()[0]);
errorMessage = "ERROR | " + e.getStackTrace()[0];
endTime = LocalDateTime.now();
} finally {
try {
// whatever will happen, an update to the ".req" file will always happen
refreshIndivLogFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The Coords Class is used to save Coordinates. If there will ever be a change in how the Cooridantes will be saved, it can be schanged here.
public class Coords {
public Double x;
public Double y;
public Coords(double x, double y) {
this.x = Double.valueOf(new DecimalFormat("##.#####").format(x).replaceAll(",", "."));
this.y = Double.valueOf(new DecimalFormat("##.#####").format(y).replaceAll(",", "."));
}
@Override
public String toString() {
return String.valueOf(x.toString() + ' ' + y.toString());
}
}
The CommandReturn Object is used in the execution of enviromental Tools (listed in the beginning of this Doc File). It combines:
- The process used,
- the standard Output,
- the Error Output and ...
- the execution return Code.
public class CommandReturn {
public int returnCode;
public String output;
public String errOutput;
private Process originalProcess;
public CommandReturn(int returnCode, String output, String errOutput, Process originalProcess) {
this.returnCode = returnCode;
this.output = output;
this.errOutput = errOutput;
this.originalProcess = originalProcess;
}
public Process getOriginalProcess() {
return originalProcess;
}
}