Commit 2a3922b8 authored by bruse's avatar bruse
Browse files

Added the new prototype of the SimStadt<->novaFACTORY data connection.

parent 9017aa8f
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
package eu.simstadt.nf;
/**
* This is an intermediate representation for WGS 84 coordinates.
*
* @author Marcel Bruse
*/
public class Coord {
/** The latitude of the geographic position. */
public double latitude;
/** The longitude of the geographic position. */
public double longitude;
/** Standard constructor.
*
* @param latitude The latitude of the WGS 84 coordinate.
* @param longitude The longitude of the WGS 84 coordinate.
*/
public Coord(double latitude, double longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
}
package eu.simstadt.nf;
/**
* Enumeration of possible states of nF import and export jobs.
*
* @author Marcel Bruse
*/
public enum JobStatus {
UNKOWN(-1), PENDING(0), RUNNING(10), FAILED(20), FINISHED(30);
public static final String UNKNOWN_STATUS_MESSAGE = "The state of the job is unknown.";
public static final String PENDING_MESSAGE = "Job is pending.";
public static final String RUNNING_MESSAGE = "Job is running.";
public static final String FAILED_MESSAGE = "Job failed.";
public static final String FINISHED_MESSAGE = "Job is finished.";
private int jobId;
private int value;
private String message;
private JobStatus(int value) {
this.value = value;
if (value == 0) {
message = PENDING_MESSAGE;
} else if (value == 10) {
message = RUNNING_MESSAGE;
} else if (value == 20) {
message = FAILED_MESSAGE;
} else if (value == 30) {
message = FINISHED_MESSAGE;
} else {
message = UNKNOWN_STATUS_MESSAGE;
}
}
public static JobStatus getInstanceForStatus(int status) {
if (status == 0) {
return PENDING;
} else if (status == 10) {
return RUNNING;
} else if (status == 20) {
return FAILED;
} else if (status == 30) {
return FINISHED;
} else {
return UNKOWN;
}
}
public int getValue() {
return value;
}
public int getJobId() {
return jobId;
}
public void setJobId(int jobId) {
this.jobId = jobId;
}
public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public boolean isFinished() {
return this == FINISHED;
}
}
package eu.simstadt.nf;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
// List<Coord> regionPolygon = Arrays.asList(
// new Coord(48.879696, 9.215463),
// new Coord(48.878230, 9.215714),
// new Coord(48.878323, 9.216613),
// new Coord(48.879402, 9.216532)
// );
// String exportJobDescription = NFJobBuilder.buildExportJob(regionPolygon);
//
// String filename = "tmp.xml";
//
// try {
// PrintWriter writer = new PrintWriter(filename);
// writer.print(exportJobDescription);
// writer.close();
//
// File exportJobFile = new File(filename);
// NFConnector connector = new NFConnectorImpl("193.196.136.164");
// JobStatus status = connector.sendExportJob(exportJobFile);
// System.out.println(status + " - " + status.getMessage());
// } catch (FileNotFoundException ex) {
// // TODO Auto-generated catch block
// ex.printStackTrace();
// }
}
}
\ No newline at end of file
package eu.simstadt.nf;
import java.io.File;
/**
* NFConnector lets you communicate with your novaFACTORY (nF) server instance.
*
* @author Marcel Bruse
*/
public interface NFConnector {
/**
* Callers of this NFConnector want to know the actual version of the novaFACTORY and the versions of its
* HTTP/FTP/WPS/etc. interfaces against which this interface has been implemented.
*
* The various NovaFACTORY interfaces may change over time. Such changes force the SimStadt programmers to
* implement different versions of this NFConnector interface while keeping old implementations due to
* backward comparability.
*
* @return The supported version of the novaFACTORY.
*/
public String supportsNFVersion();
/**
* Sends an export job to nF. The job has to be passed and to be described in an appropriate XML format.
* The DTD of the XML format can be obtained from the nF installation or documentation.
*
* @param file The nF export job as a prepared XML file.
* @return The status of the job. Could be pending or failed.
*/
public JobStatus sendExportJob(File file);
/**
* Returns the status of any existing nF job.
*
* @param jobId The id of the job for which you want to request the status.
* @return The status of any existing nF job.
*/
public JobStatus requestJobStatus(int jobId);
/**
* Downloads the result for a given nF export job and hands over the corresponding file handle.
*
* @param jobId The id of the export job for which the result should be loaded.
* @return A file handle to the result of the nF export job.
*/
public File requestJobResult(int jobId);
}
package eu.simstadt.nf;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* NFConnector lets you communicate with your novaFACTORY (nF) server instance. It supports nF version 6.3.1.1.
* For more technical details about the NFConnector interface @see NFConnector.
*
* @author Marcel Bruse
*/
public class NFConnectorImpl implements NFConnector {
/** Supported version of the novaFACTORY. */
public static final String NOVA_FACTORY_VERSION = "6.3.1.1";
/** The default context of the nF web application. It is part of any request URL directed at the nF server. */
public static final String DEFAULT_CONTEXT = "novaFACTORY";
/** The default port number of the nF web application. */
public static final int DEFAULT_PORT = 80;
/** The default protocol for requests. */
public static final String DEFAULT_PROTOCOL = "http";
/** The standard char set for requests. */
public static final String DEFAULT_CHARSET = "UTF-8";
/** The standard line separator required for file transmission via multipart/form-data. */
public static final String CRLF = "\r\n";
/** The name of nF's remote order servlet. */
public static final String REMOTE_ORDER_SERVLET = "RemoteOrder";
/** The name of nF's remote status servlet. */
public static final String REMOTE_STATUS_SERVLET = "RemoteStatus";
/** The name of nF's remote import servlet. */
public static final String REMOTE_IMPORT_SERVLET = "RemoteImport";
/** Default parser error message. */
public static final String XML_PARSER_ERROR = "Request failed due to an unknown XML parser error.";
/** Default IO exception occurred message. */
public static final String IO_EXCEPTION_OCCURRED =
"Request failed due to an IO exception. Check the host and port.";
/** Default malformed URL message. */
public static final String MALFORMED_URL = "Request failed due to a malformed URL.";
/** Default unknown error message. */
public static final String UNKNOWN_ERROR_OCCURRED = "An unknown error occurred.";
/** The server or host name of the nF server. */
private String server;
/** The port of the nF server. */
private int port;
/** The protocol of the data connection. */
private String protocol;
/** The context of the nF web application. It is part of any request URL directed at the nF server. */
private String context;
/**
* Constructs your NFConnector instance.
*
* @param server The host name of the nF server with which you want to establish a data connection.
*/
public NFConnectorImpl(String server) {
this(server, DEFAULT_PORT, DEFAULT_CONTEXT, DEFAULT_PROTOCOL);
}
/**
* Constructs your NFConnector instance.
*
* @param server The host name of the nF server with which you want to establish a data connection.
* @param port The port of the nF web application.
* @param context The context of the nF web application. It is part of any request URL directed at the nF server.
*/
public NFConnectorImpl(String server, int port, String context, String protocol) {
this.server = server;
this.port = port;
this.context = context;
this.protocol = protocol;
}
/**
* Callers of this NFConnector want to know the actual version of the novaFACTORY and the versions of its
* HTTP/FTP/WPS/etc. interfaces against which this interface has been implemented.
*
* The NovaFACTORY interfaces may change over time. Such changes force the SimStadt programmers to
* implement different versions of this NFConnector interface while keeping old implementations in order to
* ensure backward compatibility.
*
* @return The supported version of the novaFACTORY.
*/
@Override
public String supportsNFVersion() {
return NOVA_FACTORY_VERSION;
}
/**
* Returns the status of any existing nF job.
*
* @param jobId The id of the job for which you want to request the status.
* @return The status of any existing nF job.
* @throws IOException An error occurred during the request. This could be a malformed URL or a network failure.
*/
@Override
public JobStatus requestJobStatus(int jobId) {
JobStatus result = JobStatus.UNKOWN;
try {
List<String> parameters = Arrays.asList(buildParameter("jobid", jobId));
result = getJobStatusFromResponse(getResponse(buildURL(REMOTE_STATUS_SERVLET, parameters)));
} catch (MalformedURLException ex) {
result.setMessage(MALFORMED_URL);
} catch (IOException ex) {
result.setMessage(IO_EXCEPTION_OCCURRED);
} catch (ParserConfigurationException | SAXException ex) {
result.setMessage(XML_PARSER_ERROR);
}
return result;
}
/**
* Downloads the result for a given nF export job and hands over the corresponding file handle.
*
* @param jobId The id of the export job for which the result should be loaded.
* @return A file handle to the result of the nF export job.
*/
@Override
public File requestJobResult(int jobId) {
File result = null;
try {
List<String> parameters = Arrays.asList(
buildParameter("request", "downloadJob"),
buildParameter("mode", 0),
buildParameter("jobId", jobId));
result = downloadFile(buildURL(REMOTE_ORDER_SERVLET, parameters));
} catch (MalformedURLException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
return result;
}
/**
* Builds a simple parameter string for a HTTP GET request string.
*
* @param key The parameter name.
* @param value The value of the parameter.
* @return The HTTP GET request parameter as concatenated key and value.
*/
private String buildParameter(String key, Object value) {
return key + "=" + value;
}
/**
* Builds a HTTP GET request URL out of the used protocol, nF server, port, context, servlet and existing
* parameters.
*
* @param servlet One of the supported nF servlets RemoteOrder, RemoteStatus or RemoteImport.
* @param parameters List of parameters to be send to the servlet.
* @return The built URL instance.
* @throws MalformedURLException You will get some of this, if you mess up any part of the URL.
*/
private URL buildURL(String servlet, List<String> parameters) throws MalformedURLException {
String url = String.format("%s://%s:%s/%s/%s", protocol, server, port, context, servlet);
if (Objects.nonNull(parameters) && !parameters.isEmpty()) {
url += "?" + String.join("&", parameters);
}
return new URL(url);
}
/**
* Requests a response from the given URL. The response is expected to be returned as nF XML report.
*
* @param url The URL of the nF servlet with all its necessary parameters. Read the nF handbook for more
* details about the usage of nF servlets.
* @return The response is expected to be a XML report, which will then be returned as a String.
* @throws IOException You will get some of this, if anything goes wrong with your data connection to your
* nF instance.
*/
private String getResponse(URL url) throws UnsupportedEncodingException, IOException {
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestProperty("Accept-Charset", DEFAULT_CHARSET);
return getResponse(httpConnection);
}
/**
* Requests a response from the given HTTP connection. The response is expected to be a XML document.
*
* @param httpConnection The HTTP Connection to the nF servlet. Read the nF handbook for more details
* about the usage of the nF servlets.
* @return The response is expected to be a XML report, which will then be returned as a String.
* @throws UnsupportedEncodingException You will get some of this, if your connection uses wrong encodings.
* @throws IOException You will get some of this, if anything goes wrong with your data connection to your
* nF instance.
*/
private String getResponse(HttpURLConnection httpConnection) throws UnsupportedEncodingException, IOException {
String xml = "";
if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
String contentType = httpConnection.getHeaderField("Content-Type");
String charset = null;
for (String param : contentType.replace(" ", "").split(";")) {
if (param.startsWith("charset=")) {
charset = param.split("=", 2)[1];
break;
}
}
InputStream response = httpConnection.getInputStream();
if (Objects.nonNull(charset)) {
BufferedReader reader = new BufferedReader(new InputStreamReader(response, charset));
String line;
while ((line = reader.readLine()) != null) {
xml += line;
}
}
response.close();
} else {
throw new IOException();
}
return xml;
}
/**
* If everything works as expected, then nF's servlets will respond with XML reports to your requests. The job
* status will be extracted from the response string. The XML reports have a certain structure. Read the nF
* manual for more information about the XML reports and have a look at the DTD of the XML reports.
*
* @param xml A XML string that is supposed to be a XML document.
* @return The status of the job which was encoded in the given XML string.
* @throws ParserConfigurationException Something went wrong.
* @throws SAXException Some parse error.
* @throws IOException Some parse error.
*/
private JobStatus getJobStatusFromResponse(String xml)
throws ParserConfigurationException, SAXException, IOException {
JobStatus result = JobStatus.UNKOWN;
SAXParserFactory saxFactory = SAXParserFactory.newInstance();
SAXParser parser = saxFactory.newSAXParser();
StringReader reader = new StringReader(xml);
ReportHandler handler = new ReportHandler();
parser.parse(new InputSource(reader), handler);
if (Objects.nonNull(handler.serviceException)) {
result.setMessage(handler.serviceException);
} else if (Objects.nonNull(handler.statusId)) {
result = JobStatus.getInstanceForStatus(handler.statusId);
}
if (Objects.nonNull(handler.jobId)) {
result.setJobId(handler.jobId);
}
return result;
}
/**
* Downloads a (zipped) CityGML file from the nF server. The file will be the result of an export job.
*
* @param url The URL of the remote order servlet that points at the CityGML file on the nF server.
* @return Returns a handle to the downloaded (zipped) CityGML file.
* @throws IOException Something went wrong with your data connection. Check your server and the port.
*/
private File downloadFile(URL url) throws IOException {
File handle = null;
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestProperty("Accept-Charset", DEFAULT_CHARSET);
if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
String filename = "result.gml";
String disposition = httpConnection.getHeaderField("Content-Disposition");
if (disposition != null) {
int index = disposition.indexOf("filename=");
if (index > -1) {
filename = disposition.
substring(index + 9, disposition.length()).
replaceAll("\"", "").
replaceAll(";", "");
}
}
InputStream inputStream = httpConnection.getInputStream();
FileOutputStream outputStream = new FileOutputStream(filename);
int bytesRead = -1;
byte[] buffer = new byte[4096];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
inputStream.close();
handle = new File(filename);
} else {
throw new IOException();
}
return handle;
}
/**
* Sends an export job to the nF. This job will be enqueued in the queue of export jobs.
*
* @param file The XML file which describes the nF export job.
* @return Returns the status of the export job you just sent.
*/
@Override
public JobStatus sendExportJob(File file) {
JobStatus result = JobStatus.UNKOWN;
try {
URL url = buildURL(REMOTE_ORDER_SERVLET, null);
JobStatus status = sendFile(url, file);
if (Objects.nonNull(status.getJobId())) {
status = requestJobStatus(status.getJobId());
} else {
status.setMessage(UNKNOWN_ERROR_OCCURRED);
}
result = status;
} catch (MalformedURLException ex) {
result.setMessage(MALFORMED_URL);
} catch (IOException ex) {
result.setMessage(IO_EXCEPTION_OCCURRED);
} catch (ParserConfigurationException | SAXException ex) {
result.setMessage(XML_PARSER_ERROR);
}
return result;
}
/**
* Does the actual job for the sendExportJob() method. sendExportJob() builds the URL for the remote servlet
* and calls this method.
*
* @param url The URL of the remote order servlet to which the file should be send to.
* @param file The file to be sent to nF.
* @return Returns the status of the export job you just sent.
* @throws IOException There was a problem with your data connection.
* @throws ParserConfigurationException There was a problem while parsing the response.
* @throws SAXException Some parse error while parsing the response.
*/
private JobStatus sendFile(URL url, File file) throws IOException, ParserConfigurationException, SAXException {
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setDoOutput(true); // Sends export job file
connection.setDoInput(true); // Expects XML response
connection.connect();
OutputStream os = connection.getOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(os, DEFAULT_CHARSET), true);
Files.copy(file.toPath(), os);
os.flush();
writer.append(CRLF).flush();
return getJobStatusFromResponse(getResponse(connection));
}
}
\ No newline at end of file
package eu.simstadt.nf;
import java.io.StringWriter;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.geotools.geometry.GeneralDirectPosition;
import org.geotools.referencing.CRS;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* Builds nF import and export jobs using nF's XML job format.
*
* @author Marcel Bruse
*/
public class NFJobBuilder {
/**
* This is an intermediate prototype.
*
* @param regionPolygon A polygon of geo coordinates which encloses the buildings to be downloaded.
* @return Returns a string representation of the nF export job.
*/
public static String buildExportJob(List<Coord> regionPolygon) {
String result = null;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.newDocument();
Element root = doc.createElement("EXPORT_JOB");
root.setAttribute("version", "1.0.0");
doc.appendChild(root);
Element job = doc.createElement("job");
root.appendChild(job);
Element initiator = doc.createElement("initiator");
initiator.appendChild(doc.createTextNode("2758"));
job.appendChild(initiator);
Element jobnumber = doc.createElement("jobnumber");
jobnumber.appendChild(doc.createTextNode("GR_EXPORT_CITYGML_LOD1"));
job.appendChild(jobnumber);
Element account = doc.createElement("account");
account.appendChild(doc.createTextNode("Habib"));
job.appendChild(account);
Element product = doc.createElement("product");
product.appendChild(doc.createTextNode("LBTEST"));
root.appendChild(product);
Element layers = doc.createElement("layers");
layers.setAttribute("color", "0");
layers.setAttribute("mono", "0");
layers.setAttribute("plotLabelSrs", "-1");
layers.setAttribute("plotframe", "0");
layers.setAttribute("single", "1");
root.appendChild(layers);
Element layer = doc.createElement("layer");
layer.setAttribute("name", "GML");
layer.setAttribute("product", "LBTEST");
layer.setAttribute("style", "#000000");
layers.appendChild(layer);
Element srs = doc.createElement("srs");
srs.appendChild(doc.createTextNode("31467"));
root.appendChild(srs);
Element extent = doc.createElement("extent");
extent.setAttribute("merge_mapsheets", "off");
extent.setAttribute("tile1asgn", "false");
root.appendChild(extent);
Element polygon = appendRegionPolygon(doc, regionPolygon);
extent.appendChild(polygon);
Element resolution = doc.createElement("resolution");
resolution.appendChild(doc.createTextNode("100.0"));
root.appendChild(resolution);
Element scale = doc.createElement("scale");
scale.appendChild(doc.createTextNode("10000.0"));
root.appendChild(scale);
Element format = doc.createElement("format");
format.setAttribute("alphalinscale", "0.0");
format.setAttribute("alphascale", "1.0");
format.setAttribute("citygml_actfunc", "tolod1");
format.setAttribute("citygml_apptheme", "");
format.setAttribute("citygml_elemclasses", "true");
format.setAttribute("citygml_lodmode", "all");
format.setAttribute("citygml_lods", "1");
format.setAttribute("citygml_metadata", "true");
format.setAttribute("citygml_outmode", "normal");
format.setAttribute("dtm", "false");
format.setAttribute("foredit", "false");
format.setAttribute("materialcopymode", "none");
format.setAttribute("polyopts_reverse", "false");
format.setAttribute("relcoords", "false");
format.setAttribute("rooftxr", "false");
format.setAttribute("roundcoords", "3");
format.setAttribute("schemetxr", "false");
format.setAttribute("solar", "false");
format.setAttribute("solargeoplex", "false");
format.setAttribute("tex", "false");
format.setAttribute("tolod1", "true");
format.setAttribute("tolod1_add", "false");
format.setAttribute("tolod1_delrest", "false");
format.setAttribute("tolod1_dstattrabsgrnd", "");
format.setAttribute("tolod1_dstattrabsheight", "");
format.setAttribute("tolod1_dstattrrelheight", "");
format.setAttribute("tolod1_dstattrzmode", "");
format.setAttribute("tolod1_geommode", "lod1solid");
format.setAttribute("tolod1_lodsrcmode", "all");
format.setAttribute("tolod1_triangulate", "false");
format.setAttribute("tolod1_zroofmode", "mid");
format.setAttribute("tolod1_zusegenattrs", "");
format.setAttribute("tolod1_zusemeasuredheight", "false");
format.setAttribute("xyz", "false");
format.appendChild(doc.createTextNode("CityGML"));
root.appendChild(format);
Element exportmetadata = doc.createElement("exportmetadata");
exportmetadata.setAttribute("calibration", "0");
exportmetadata.setAttribute("xmetadata", "0");
exportmetadata.appendChild(doc.createTextNode("1"));
root.appendChild(exportmetadata);
Element addfile = doc.createElement("addfile");
addfile.setAttribute("col", "0");
addfile.setAttribute("eck", "");
root.appendChild(addfile);
Element usenodatamask = doc.createElement("usenodatamask");
usenodatamask.appendChild(doc.createTextNode("0"));
root.appendChild(usenodatamask);
Element usepdctborderpoly = doc.createElement("usepdctborderpoly");
usepdctborderpoly.appendChild(doc.createTextNode("0"));
root.appendChild(usepdctborderpoly);
Element dhkresolvereferences = doc.createElement("dhkresolvereferences");
dhkresolvereferences.appendChild(doc.createTextNode("1"));
root.appendChild(dhkresolvereferences);
Element zipresult = doc.createElement("zipresult");
zipresult.appendChild(doc.createTextNode("0"));
root.appendChild(zipresult);
Element userdescription = doc.createElement("userdescription");
root.appendChild(userdescription);
Element namingpattern = doc.createElement("namingpattern");
root.appendChild(namingpattern);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
StringWriter writer = new StringWriter();
StreamResult streamResult = new StreamResult(writer);
transformer.transform(new DOMSource(doc), streamResult);
result = writer.toString();
} catch (ParserConfigurationException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
} catch (TransformerConfigurationException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
} catch (TransformerException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
return result;
}
/**
* Transforms a global WGS 84 position into a coordinate of the given target SRS.
*
* @param wgs84Position The WGS 84 position to be transformed to a position within the target SRS.
* @param targetCRS The target SRS for the transformation.
* @return The transformed target position within the target SRS.
*/
public static DirectPosition transformCoordinate(DirectPosition wgs84Position,
CoordinateReferenceSystem targetCRS) {
DirectPosition result = null;
try {
CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:4326"); // WGS 84 (used by Google Maps)
MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
result = transform.transform(wgs84Position, null);
} catch (NoSuchAuthorityCodeException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
} catch (FactoryException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
} catch (MismatchedDimensionException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
} catch (TransformException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
return result;
}
/**
* Appends the region polygon to the XML export job document. In order to do this, the given WGS 84 region
* polygon will be transformed into a DHDN Gauss-Kruger zone 3 polygon.
*
* @param doc The XML export job document.
* @param regionPolygon The polygon of the region which has been selected to be exported.
* @return The w3c.dom.Element of the XML export job which describes the region polygon.
*/
private static Element appendRegionPolygon(Document doc, List<Coord> regionPolygon) {
Element polygon = doc.createElement("polygon");
polygon.setAttribute("srs", "31467");
try {
CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:31467"); // DHDN Gauss-Kruger zone 3
for (Coord coord : regionPolygon) {
DirectPosition sourcePosition = new GeneralDirectPosition(coord.latitude, coord.longitude);
DirectPosition targetPosition = transformCoordinate(sourcePosition, targetCRS);
Element vertex = doc.createElement("vertex");
vertex.setAttribute("x", String.valueOf(targetPosition.getCoordinate()[1]));
vertex.setAttribute("y", String.valueOf(targetPosition.getCoordinate()[0]));
polygon.appendChild(vertex);
}
} catch (FactoryException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
return polygon;
}
}
package eu.simstadt.nf;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* This SAX handler scans a nF XML status report instance and searches for the nF job id and the status of a
* nF job.
*
* @author Marcel Bruse
*/
public class ReportHandler extends DefaultHandler {
/** The XML tag which tells you the status of a nF job. */
public static final String STATUS_TAG = "status";
/** The XML tag which holds the id of the nF job. */
public static final String JOB_ID = "jobId";
/** If there was a problem on the nF server, then this XML tag gives you some hints. */
public static final String SERVICE_EXCEPTION_TAG = "ServiceException";
/** The id of the status of the nF job. */
public Integer statusId = null;
/** The id of the nF job. */
public Integer jobId = null;
/** If there was any problem, then you will find an exception message here. */
public String serviceException = null;
/** Scanned string will be stored here temporarily. */
private String currentString;
/**
* If a tag has been read, its contents will be tested here. If it contains either a status id, job id or
* service exception messege, then the contents will be stored in the appropriate member variable.
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equalsIgnoreCase(STATUS_TAG)) {
statusId = Integer.valueOf(currentString);
} else if (qName.equalsIgnoreCase(SERVICE_EXCEPTION_TAG)) {
serviceException = currentString;
} else if (qName.equalsIgnoreCase(JOB_ID)) {
jobId = Integer.valueOf(currentString);
}
}
/**
* The scanner of the XML document.
*
* @see DefaultHandler
*/
@Override
public void characters(char[] ch, int start, int length) {
currentString = new String(ch, start, length);
}
}
package eu.simstadt.regionchooser;
import java.util.Arrays;
import java.util.List;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import com.lynden.gmapsfx.GoogleMapView;
import com.lynden.gmapsfx.MapComponentInitializedListener;
import com.lynden.gmapsfx.javascript.object.GoogleMap;
......@@ -13,9 +17,11 @@
import com.lynden.gmapsfx.javascript.object.Marker;
import com.lynden.gmapsfx.javascript.object.MarkerOptions;
import eu.simstadt.nf.Coord;
import eu.simstadt.nf.NFJobBuilder;
public class RegionChooserController implements MapComponentInitializedListener
{
public class RegionChooserController implements MapComponentInitializedListener {
@FXML
private Button button;
......@@ -31,10 +37,10 @@ public void initialize() {
@Override
public void mapInitialized() {
LatLong bochumLoc = new LatLong(51.482, 7.225);
LatLong hamburgLoc = new LatLong(53.551, 9.994);
LatLong stuttgartLoc = new LatLong(48.778, 9.176);
LatLong dresdenLoc = new LatLong(51.049, 13.741);
LatLong bochumLoc = new LatLong(48.879696, 9.215463);
LatLong hamburgLoc = new LatLong(48.878230, 9.215714);
LatLong stuttgartLoc = new LatLong(48.878323, 9.216613);
LatLong dresdenLoc = new LatLong(48.879402, 9.216532);
//Set the initial properties of the map.
......@@ -80,5 +86,15 @@ public void mapInitialized() {
InfoWindow bochumInfoWindow = new InfoWindow(infoWindowOptions);
bochumInfoWindow.open(map, bochumMarker);
// Build the nF export job description from a region polygon
List<Coord> regionPolygon = Arrays.asList(
new Coord(bochumLoc.getLatitude(), bochumLoc.getLongitude()),
new Coord(hamburgLoc.getLatitude(), bochumLoc.getLongitude()),
new Coord(stuttgartLoc.getLatitude(), bochumLoc.getLongitude()),
new Coord(dresdenLoc.getLatitude(), bochumLoc.getLongitude())
);
String exportJobDescription = NFJobBuilder.buildExportJob(regionPolygon);
System.out.println(exportJobDescription);
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment