Commit f1a210af authored by Eric Duminil's avatar Eric Duminil
Browse files

RegionChooser: Remove novafactory code

parent 6d96f1b5
package eu.simstadt.nf4j.async;
import java.io.File;
import eu.simstadt.nf4j.ExportJobDescriptor;
import eu.simstadt.nf4j.ImportJobDescriptor;
import eu.simstadt.nf4j.InvalidJobDescriptorException;
/**
* Implementations of JobBuilder build nF import and export jobs using nF's XML job format. There should be
* one implementation for each version of novaFACTORY. The supported version should be returned by
* supportsNFVersion().
*
* @param <I> The import job descriptor implementation for this builder.
* @param <E> The export job descriptor implementation for this builder.
*
* @author Marcel Bruse
*/
public interface JobFileBuilder<I extends ImportJobDescriptor, E extends ExportJobDescriptor> {
/**
* @return Tells the caller the supported version of novaFACTORY.
*/
public String supportsNFVersion();
/**
* @return The supported version of the XML export job format.
*/
public String supportsExportJobVersion();
/**
* @return The supported version of the XML import job format.
*/
public String supportsImportJobVersion();
/**
* Builds a XML export job document. This file can be sent to a nF server instance by the caller afterwards.
*
* @param jobDescriptor A job descriptor which describes the export job with all its attributes according to
* a valid nF export job DTD.
* @return Returns a XML export job document.
*/
public File buildExportJobFile(E exportJobDescriptor) throws InvalidJobDescriptorException;
/**
* Builds a zipped import job file. This file can be sent to a nF server instance by the caller afterwards.
*
* @param jobDescriptor A job descriptor which describes the import job with all its attributes according to
* the nF manual.
* @return Returns a zipped import job file.
*/
public File buildImportJobFile(I importJobDescriptor) throws InvalidJobDescriptorException;
}
package eu.simstadt.nf4j.async;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
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.osgeo.proj4j.BasicCoordinateTransform;
import org.osgeo.proj4j.CRSFactory;
import org.osgeo.proj4j.CoordinateReferenceSystem;
import org.osgeo.proj4j.ProjCoordinate;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import eu.simstadt.nf4j.InvalidJobDescriptorException;
/**
* Builds nF import and export jobs using nF's XML job format. Please read the nF manual if you want more details about
* the numerous job attributes listed below.
*
* @author Marcel Bruse
*/
public class JobFileBuilderImpl implements JobFileBuilder<ImportJobDescription, ExportJobDescription>
{
/** Supported version of the novaFACTORY. */
public static final String NOVA_FACTORY_VERSION = "6.3.1.1";
/** The version of the XML export job format. */
public static final String EXPORT_JOB_VERSION = "1.0.0";
/**
* @return Returns the supported novaFACTORY version.
*/
@Override
public String supportsNFVersion() {
return NOVA_FACTORY_VERSION;
}
/**
* @return Returns the supported XML export job version.
*/
@Override
public String supportsExportJobVersion() {
return EXPORT_JOB_VERSION;
}
/**
* @return Returns the supported XML import job version.
*/
@Override
public String supportsImportJobVersion() {
return null;
}
/**
* This is an intermediate prototype.
*
* @param jobDescriptor A job descriptor which describes the export job with all its attributes according to a valid
* nF export job DTD.
* @return Returns a string representation of the nF export job.
* @throws FailedJobTransmissionException
*/
@Override
public File buildExportJobFile(ExportJobDescription jobDescriptor) throws InvalidJobDescriptorException {
File result = null;
if (Objects.nonNull(jobDescriptor) && jobDescriptor.isValid()) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.newDocument();
Element root = doc.createElement("EXPORT_JOB");
root.setAttribute("version", supportsExportJobVersion());
doc.appendChild(root);
Element job = doc.createElement("job");
root.appendChild(job);
Element initiator = doc.createElement("initiator");
initiator.appendChild(doc.createTextNode(jobDescriptor.getInitiator()));
job.appendChild(initiator);
Element jobnumber = doc.createElement("jobnumber");
jobnumber.appendChild(doc.createTextNode(jobDescriptor.getJobnumber()));
job.appendChild(jobnumber);
Element account = doc.createElement("account");
account.appendChild(doc.createTextNode(System.getProperty("user.name")));
job.appendChild(account);
Element product = doc.createElement("product");
product.appendChild(doc.createTextNode(jobDescriptor.getProduct()));
root.appendChild(product);
Element layers = doc.createElement("layers");
layers.setAttribute("color", jobDescriptor.getColor());
layers.setAttribute("mono", jobDescriptor.getMono());
layers.setAttribute("plotLabelSrs", jobDescriptor.getPlotLabelSrs());
layers.setAttribute("plotframe", jobDescriptor.getPlotframe());
layers.setAttribute("single", jobDescriptor.getSingle());
root.appendChild(layers);
appendLayers(doc, layers, jobDescriptor.getLayerList());
Element srs = doc.createElement("srs");
srs.appendChild(doc.createTextNode(jobDescriptor.getSrs()));
root.appendChild(srs);
Element extent = doc.createElement("extent");
extent.setAttribute("merge_mapsheets", jobDescriptor.getMergeMapsheets());
root.appendChild(extent);
if (!jobDescriptor.getUnitList().isEmpty()) {
extent.setAttribute("tile1asgn", jobDescriptor.getTile1asgn());
for (Unit unit : jobDescriptor.getUnitList()) {
Element unitElement = doc.createElement("unit");
unitElement.setAttribute("exterior", unit.getExterior());
unitElement.setAttribute("frame", unit.getFrame());
unitElement.setAttribute("select_mapsheets", unit.getSelectMapsheets());
unitElement.setAttribute("subdivision", unit.getSubdivision());
unitElement.appendChild(doc.createTextNode(unit.getValue()));
extent.appendChild(unitElement);
}
} else {
Element polygon = createRegionPolygonElement(doc, jobDescriptor.regionPolygon);
extent.appendChild(polygon);
}
Element resolution = doc.createElement("resolution");
resolution.appendChild(doc.createTextNode(jobDescriptor.getResolution()));
root.appendChild(resolution);
Element scale = doc.createElement("scale");
scale.appendChild(doc.createTextNode(jobDescriptor.getScale()));
root.appendChild(scale);
Element format = doc.createElement("format");
format.setAttribute("alphalinscale", "0.0");
format.setAttribute("alphascale", "1.0");
format.setAttribute("citygml_actfunc", "undef");
format.setAttribute("citygml_apptheme", "");
format.setAttribute("citygml_elemclasses", "true");
format.setAttribute("citygml_lodmode", "all");
format.setAttribute("citygml_lods", jobDescriptor.getLODs());
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", "false");
format.setAttribute("xyz", "false");
format.appendChild(doc.createTextNode("CityGML"));
root.appendChild(format);
Element exportmetadata = doc.createElement("exportmetadata");
exportmetadata.setAttribute("calibration", jobDescriptor.getCalibration());
exportmetadata.setAttribute("xmetadata", jobDescriptor.getXmetadata());
exportmetadata.appendChild(doc.createTextNode(jobDescriptor.getExportmetadata()));
root.appendChild(exportmetadata);
Element addfile = doc.createElement("addfile");
addfile.setAttribute("col", jobDescriptor.getCol());
addfile.setAttribute("eck", jobDescriptor.getEck());
root.appendChild(addfile);
Element usenodatamask = doc.createElement("usenodatamask");
usenodatamask.appendChild(doc.createTextNode(jobDescriptor.getUsenodatamask()));
root.appendChild(usenodatamask);
Element usepdctborderpoly = doc.createElement("usepdctborderpoly");
usepdctborderpoly.appendChild(doc.createTextNode(jobDescriptor.getUsepdctborderpoly()));
root.appendChild(usepdctborderpoly);
Element dhkresolvereferences = doc.createElement("dhkresolvereferences");
dhkresolvereferences.appendChild(doc.createTextNode(jobDescriptor.getDhkresolvereferences()));
root.appendChild(dhkresolvereferences);
Element zipresult = doc.createElement("zipresult");
zipresult.appendChild(doc.createTextNode(jobDescriptor.getZipresult()));
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);
File tempfile = File.createTempFile(jobDescriptor.getProduct() + "_", ".xml");
PrintWriter printWriter = new PrintWriter(tempfile);
printWriter.print(writer.toString());
printWriter.close();
return tempfile;
} 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();
} catch (FileNotFoundException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
} catch (IOException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
} else {
throw new InvalidJobDescriptorException();
}
return result;
}
/**
* Appends layers to the XML job document.
*
* @param doc The XML document.
* @param layers The XML layers element where new layers should be appended.
* @param layerList The user defined list of layers.
*/
private void appendLayers(Document doc, Element layers,
ArrayList<Layer> layerList) {
for (Layer layer : layerList) {
Element layerElement = doc.createElement("layer");
layerElement.setAttribute("name", layer.getName());
String product = layer.getProduct();
if (Objects.nonNull(product) && !product.isEmpty()) {
layerElement.setAttribute("product", product);
}
String style = layer.getStyle();
if (Objects.nonNull(style) && !style.isEmpty()) {
layerElement.setAttribute("style", style);
}
layers.appendChild(layerElement);
}
}
/**
* 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 ProjCoordinate transformCoordinate(ProjCoordinate wgs84Position,
CoordinateReferenceSystem targetCRS) {
ProjCoordinate result = new ProjCoordinate();
CRSFactory f = new CRSFactory();
CoordinateReferenceSystem sourceCRS = f.createFromName(CRSWKT.EPSG_4326.wkt); // WGS 84 (used by Google Maps / OpenStreetMap)
BasicCoordinateTransform transform = new BasicCoordinateTransform(sourceCRS, targetCRS);
transform.transform(wgs84Position, result);
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 createRegionPolygonElement(Document doc, List<Coord> regionPolygon) {
Element polygon = doc.createElement("polygon");
polygon.setAttribute("srs", "31467");
CRSFactory f = new CRSFactory();
CoordinateReferenceSystem targetCRS = f.createFromName(CRSWKT.EPSG_31467.wkt); // DHDN Gauss-Kruger zone 3
for (Coord coord : regionPolygon) {
ProjCoordinate sourcePosition = new ProjCoordinate(coord.longitude, coord.latitude);
ProjCoordinate targetPosition = transformCoordinate(sourcePosition, targetCRS);
Element vertex = doc.createElement("vertex");
vertex.setAttribute("x", String.valueOf(targetPosition.x));
vertex.setAttribute("y", String.valueOf(targetPosition.y));
polygon.appendChild(vertex);
}
return polygon;
}
/**
* Builds a zipped import job file. This file can be sent to a nF server instance by the caller afterwards.
*
* @param jobDescriptor A job descriptor which describes the import job with all its attributes according to a valid
* nF import job DTD.
* @return Returns a XML import job document.
*/
@Override
public File buildImportJobFile(ImportJobDescription jobDescriptor)
throws InvalidJobDescriptorException {
if (Objects.nonNull(jobDescriptor) && jobDescriptor.isValid()) {
try {
// Write the nF start file which triggers and controls the processing of the CityGML file.
String startFilename = jobDescriptor.getProduct() + "_" + jobDescriptor.getLeaf() + ".start";
File startfile = new File(System.getProperty("java.io.tmpdir"), startFilename);
PrintWriter writer = new PrintWriter(startfile);
writer.print(jobDescriptor.getLevel());
writer.close();
// Zip start file, CityGML file and ADE schemata
File zippedCityGMLFile = File.createTempFile("nF_Import_", ".zip");
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zippedCityGMLFile));
String zipFileName = jobDescriptor.getProduct() + "_" + jobDescriptor.getLeaf() + "_"
+ jobDescriptor.getLevel();
if (Objects.nonNull(jobDescriptor.getOperation())) {
zipFileName += "_" + jobDescriptor.getOperation();
}
zipFileName += ".gml";
File cityGMLFile = jobDescriptor.getCityGMLFile();
writeBytesToZipFile(new FileInputStream(cityGMLFile), zos, zipFileName);
writeBytesToZipFile(new FileInputStream(startfile), zos, startFilename);
for (File adeSchemaFile : jobDescriptor.getADESchemaFileList()) {
writeBytesToZipFile(new FileInputStream(adeSchemaFile), zos, adeSchemaFile.getName());
}
zos.close();
return zippedCityGMLFile;
} catch (IOException ex) {
ex.printStackTrace();
}
} else {
throw new InvalidJobDescriptorException();
}
return null;
}
/**
* Writes a file to the given ZipOutputStream which compresses the file.
*
* @param fis The file input stream to be compressed.
* @param zos The zip output stream.
* @param zipEntry The new zip entry for the file to be compressed.
* @throws IOException You will get some of this, if your streams point to nirvana.
*/
private void writeBytesToZipFile(FileInputStream fis, ZipOutputStream zos, String zipEntry)
throws IOException {
zos.putNextEntry(new ZipEntry(zipEntry));
byte[] b = new byte[1024];
int chunkSize;
while ((chunkSize = fis.read(b)) > 0) {
zos.write(b, 0, chunkSize);
}
fis.close();
}
}
package eu.simstadt.nf4j.async;
import java.util.EventObject;
import java.util.Optional;
import eu.simstadt.nf4j.Job;
import eu.simstadt.nf4j.JobStatus;
/**
* Every time when the status of a job progresses, one of this events will be created and sent
* to all of the job status listeners registered at the job. Job status listeners implement
* the jobStatusChanged() method which takes this JobStatusEvent as its argument. This event will
* contain the job status as the event source and listener can read the source and decide how to
* deal with the new status of its observed job.
*
* Note, the job status, job and additional event messages will be referenced in extra object members of this event,
* because the status of referenced job may change during the notification of the listeners. Therefore, obtaining
* the job status directly from the job is not reliable, if the listener wants to know the actual source of this
* event.
*
* @author Marcel Bruse
*/
public class JobStatusEvent extends EventObject {
private static final long serialVersionUID = -1800246486543538087L;
/** The job for which this event will be sent to the job status listeners. */
private Job job;
/** There might be an additional (error) message provided with the new job status. */
private Optional<String> message;
/**
* Constructor with job status as event source. The source can be read by the job status listeners.
*
* @param source The new job status, which triggers this event.
*/
public JobStatusEvent(JobStatus source, Job job) {
this(source, job, null);
}
/**
* Constructor with job status as event source and an additional (error) message. The source can be read
* by the job status listeners.
*
* @param source The new job status, which triggers this event.
* @param message an additional (error) message for this event and job status.
*/
public JobStatusEvent(JobStatus source, Job job, Optional<String> message) {
super(source);
this.job = job;
this.message = message;
}
/**
* @return Returns the job for which this event will be sent to the job status listeners.
*/
public Job getJob() {
return job;
}
/**
* @return Returns an additional (error) message, if present.
*/
public Optional<String> getMessage() {
return message;
}
}
package eu.simstadt.nf4j.async;
import java.util.EventListener;
/**
* Your main application may become a job status listener in order to get updates about the status changes of its
* ongoing jobs. Job listeners of asynchronous export and import jobs will receive event objects for most of the
* job status' listed in the job status enumeration.
*
* @author Marcel Bruse
*/
public interface JobStatusListener extends EventListener {
/**
* This callback method will be called by your asynchronous export and import jobs during their send, poll
* and download operations in order to keep you updated about job status changes.
*
* @param event The latest job status event for one of your export or import jobs.
*/
public void jobStatusChanged(JobStatusEvent event);
}
package eu.simstadt.nf4j.async;
/**
* A layer describes an aspect of a nF product and the type of its data. For instance, a layer could contain
* all house numbers of all buildings of the product.
*
* @author Marcel Bruse
*/
public class Layer {
private static final String DEFAULT_NAME = "GML";
private static final String DEFAULT_PRODUCT = "WU3";
private static final String DEFAULT_STYLE = "#000000";
/** The name of the layer. */
private String name;
/** The name of the product to which this layer belongs. */
private String product;
/** The style of this layer. Should be a color code (?). */
private String style;
/**
* The standard constructor.
*/
public Layer() {}
/**
* A convenience constructor for layers.
*
* @param name The name of the layer. This layer has to exist within the product.
* @param product The name of the product. This product has to exist in the database.
* @param style The purpose of this field is unknown.
*/
public Layer(String name, String product, String style) {
this.name = name;
this.product = product;
this.style = style;
}
/**
* @return Returns the name of the layer.
*/
public String getName() {
return name;
}
/**
* Sets the name of the layer.
*
* @param name The name of the layer.
*/
public void setName(String name) {
this.name = name;
}
/**
* @return Returns the name of the layer's product.
*/
public String getProduct() {
return product;
}
/**
* Sets the product of this layer.
*
* @param product The product of this layer.
*/
public void setProduct(String product) {
this.product = product;
}
/**
* @return Returns the style of the layer.
*/
public String getStyle() {
return style;
}
/**
* Sets the style of this layer. Should be a color code (?).
*
* @param style The style of this layer.
*/
public void setStyle(String style) {
this.style = style;
}
public static Layer getDefaultLayer() {
Layer layer = new Layer();
layer.setName(DEFAULT_NAME);
layer.setProduct(DEFAULT_PRODUCT);
layer.setStyle(DEFAULT_STYLE);
return layer;
}
}
package eu.simstadt.nf4j.async;
/**
* These are the known operation modes of the nF import servlet.
*
* @author Marcel Bruse
*/
public enum Operation {
REP, // Replaces whole existing buildings,
REPUPD, // Replaces whole existing buildings and adds new buildings,
UPD, // Update, same as REP,
CHG, // Change, same as REPUPD,
DEL, // Deletes the geometry of a particular LOD,
DELALL // Deletes a whole building
}
package eu.simstadt.nf4j.async;
import eu.simstadt.nf4j.FailedTransmissionException;
/**
* This task frequently polls the status of an asynchronous job within a separate poll thread. Changes of the
* jobs status will be signaled to all of the job status listeners registered at the job.
* You can cancel this task by calling job.cancel().
*
* @author Marcel Bruse
*/
public class PollJobStatusTask implements Runnable {
/** The job for which you want to poll status changes for. */
private AsyncJob job;
/**
* Don't flood your nF server with status request. This interval ensures that your server will receive
* a status request within every time interval.
*/
private int interval;
/**
* Constructor with asynchronous job and the poll interval.
*
* @param job The job to update frequently.
* @param interval The time interval for one request.
*/
public PollJobStatusTask(AsyncJob job, int interval) {
this.job = job;
this.interval = interval;
}
/**
* This method performs the poll operation asynchronously in the jobs separate poll thread.
* Job status listeners will be notified upon status changes.
*/
@Override
public void run() {
try {
while (!job.hasFinished() && !job.hasFailed() && job.keepPolling()) {
job.triggerStatusUpdate();
Thread.sleep(interval * 1000l);
}
// At this line the job may have finished or failed before the job listeners could be notified.
// Therefore, we have to ensure that all listeners know the current status.
job.notifyJobStatusListeners();
} catch (FailedTransmissionException ex) {
job.cancel();
} catch (InterruptedException ex) {
// Canceled by the main thread
}
}
}
\ No newline at end of file
package eu.simstadt.nf4j.async;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* This SAX handler scans nF XML status reports and exception reports and searches for the nF job id, the status of a
* nF job and service exception messages.
*
* @author Marcel Bruse
*/
public class ReportHandler extends DefaultHandler {
/** The XML tag which tells you the status of a nF export job. */
public static final String STATUS_TAG = "status";
/** The XML tag which tells you the status of a nF import job. */
public static final String RESULT_STATUS_TAG = "ResultStatus";
/** The XML attribute which tells you the status of a nF import job. */
public static final String STATUS_ATTRIBUTE = "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;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
if (qName.equalsIgnoreCase(RESULT_STATUS_TAG)) {
statusId = Integer.valueOf(attributes.getValue(STATUS_ATTRIBUTE));
}
}
/**
* If a tag has been read, its contents will be tested here. If it contains either a status id, job id or
* service exception message, 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.nf4j.async;
import java.util.Optional;
import eu.simstadt.nf4j.FailedTransmissionException;
import eu.simstadt.nf4j.InvalidJobDescriptorException;
import eu.simstadt.nf4j.JobStatus;
/**
* This task sends an export job to your nF server asynchronously within a separate send thread. Once the send
* operation has finished all of the jobs status listeners will be notified. You can cancel this task by calling
* job.cancel().
*
* @author Marcel Bruse
*/
public class SendExportJobTask implements Runnable {
/** The job to be sent to your nF server. */
private AsyncExportJob job;
/**
* Constructor with the export job to be sent.
*
* @param job The export job to be sent.
*/
public SendExportJobTask(AsyncExportJob job) {
this.job = job;
}
/**
* This methods performs the actual send operation asynchronously in a separate send thread.
* Job status listeners will be notified once the operation finishes or fails.
*/
@Override
public void run() {
try {
HTTPConnection connector = (HTTPConnection) job.getConnector();
connector.sendAndUpdateExportJob(job);
job.poll();
} catch (InvalidJobDescriptorException ex) {
signalError("Job cancel because of an invalid job description!");
} catch (FailedTransmissionException ex) {
signalError("The job transmission failed. There seams to be a problem with the connector!");
}
}
/**
* This method is superfluous I guess? TODO: Please check and refactor it.
*/
private void signalError(String errorMessage) {
job.setStatus(JobStatus.UNKNOWN, Optional.of(errorMessage));
}
}
\ No newline at end of file
package eu.simstadt.nf4j.async;
import java.util.Optional;
import eu.simstadt.nf4j.FailedTransmissionException;
import eu.simstadt.nf4j.InvalidJobDescriptorException;
import eu.simstadt.nf4j.JobStatus;
/**
* This task sends an import job to your nF server asynchronously within a separate send thread. Once the send
* operation has finished all of the jobs status listeners will be notified. You can cancel this task by calling
* job.cancel().
*
* @author Marcel Bruse
*/
public class SendImportJobTask implements Runnable {
/** The job to be sent to your nF server. */
private AsyncImportJob job;
/**
* Constructor with the import job to be sent.
*
* @param job The import job to be sent.
*/
public SendImportJobTask(AsyncImportJob job) {
this.job = job;
}
/**
* This methods performs the actual send operation asynchronously in a separate send thread.
* Job status listeners will be notified once the operation finishes or fails.
*/
@Override
public void run() {
try {
HTTPConnection connector = (HTTPConnection) job.getConnector();
connector.sendAndUpdateImportJob(job);
job.poll();
} catch (InvalidJobDescriptorException ex) {
signalError("Job cancel because of an invalid job description!");
} catch (FailedTransmissionException ex) {
signalError("The job transmission failed. There seams to be a problem with the connector!");
}
}
/**
* This method is superfluous I guess? TODO: Please check and refactor it.
*/
private void signalError(String errorMessage) {
job.setStatus(JobStatus.UNKNOWN, Optional.of(errorMessage));
}
}
\ No newline at end of file
package eu.simstadt.nf4j.async;
/**
* Units (Blattschnitte) divide regions into sections. For instance, the city of Stuttgart could have the units
* "Stg-Mitte", "Stg-West", "Bad Cannstatt", "Heslach", etc.
*
* @author Marcel Bruse
*
*/
public class Unit {
private static final String DEFAULT_EXTERIOR = "0";
private static final String DEFAULT_FRAME = "0";
private static final String DEFAULT_SELECT_MAP_SHEETS = "0";
private static final String DEFAULT_SUBDIVISION = "4";
/** The exterior attribute of the unit tag. */
private String exterior;
/** The frame attribute of the unit tag. */
private String frame;
/** The select mapsheet attribute of the unit tag. */
private String selectMapsheets;
/** The subdivision attribute of the unit tag. */
private String subdivision;
/** The actual value of the unit tag. */
private String value;
public String getExterior() {
return exterior;
}
public void setExterior(String exterior) {
this.exterior = exterior;
}
public String getFrame() {
return frame;
}
public void setFrame(String frame) {
this.frame = frame;
}
public String getSelectMapsheets() {
return selectMapsheets;
}
public void setSelectMapsheets(String selectMapsheets) {
this.selectMapsheets = selectMapsheets;
}
public String getSubdivision() {
return subdivision;
}
public void setSubdivision(String subdivision) {
this.subdivision = subdivision;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
/**
* @return Returns true, if the unit is valid.
*/
public boolean isValid() {
return !(exterior.isEmpty()
|| frame.isEmpty()
|| selectMapsheets.isEmpty()
|| subdivision.isEmpty());
}
public static Unit getDefaultUnit() {
Unit unit = new Unit();
unit.setExterior(DEFAULT_EXTERIOR);
unit.setFrame(DEFAULT_FRAME);
unit.setSelectMapsheets(DEFAULT_SELECT_MAP_SHEETS);
unit.setSubdivision(DEFAULT_SUBDIVISION);
return unit;
}
}
package eu.simstadt.regionchooser; package eu.simstadt.regionchooser;
import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Enumeration;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
import com.ximpleware.NavException; import com.ximpleware.NavException;
import com.ximpleware.XPathEvalException; import com.ximpleware.XPathEvalException;
import com.ximpleware.XPathParseException; import com.ximpleware.XPathParseException;
import eu.simstadt.geo.fast_xml_parser.ConvexHullCalculator; import eu.simstadt.geo.fast_xml_parser.ConvexHullCalculator;
import eu.simstadt.nf4j.ExportJobFromJavaFXRegionChooser;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task; import javafx.concurrent.Task;
...@@ -46,7 +37,6 @@ public class RegionChooserBrowser extends Region ...@@ -46,7 +37,6 @@ public class RegionChooserBrowser extends Region
public class JavaScriptFXBridge public class JavaScriptFXBridge
{ {
private Path repo; private Path repo;
private WKTReader wktReader = new WKTReader();
public JavaScriptFXBridge() { public JavaScriptFXBridge() {
Preferences userPrefs = Preferences.userRoot().node("/eu/simstadt/desktop"); Preferences userPrefs = Preferences.userRoot().node("/eu/simstadt/desktop");
...@@ -79,49 +69,6 @@ public Void call() throws IOException { ...@@ -79,49 +69,6 @@ public Void call() throws IOException {
new Thread(task).start(); new Thread(task).start();
} }
public void downloadRegion(String wktPolygon, String productName, JSObject novaFactoryLayer) {
//TODO: Ask nf Server about available regions
Task<Integer> task = new Task<Integer>() {
@Override
protected Integer call() throws Exception {
ExportJobFromJavaFXRegionChooser nfJob = new ExportJobFromJavaFXRegionChooser();
Geometry poly = wktReader.read(wktPolygon);
nfJob.processJob(poly, productName, novaFactoryLayer);
return 0;
}
};
new Thread(task).start();
}
public void extractZIPtoGML(String zipFilename) throws IOException {
try (ZipFile zipFile = new ZipFile(zipFilename)) {
Enumeration<? extends ZipEntry> entries = zipFile.entries();
String userName = System.getProperty("user.name");
while (entries.hasMoreElements()) {
ZipEntry ze = entries.nextElement();
String zeName = ze.getName();
if (zeName.toLowerCase().contains("gml")) {
File extractedCityGML = selectSaveFileWithDialog(null,
zeName.replace("_GML.", ".").replace(userName, "novaFACTORY"), "");
if (extractedCityGML != null) {
try (
InputStream cityGMLInputStream = zipFile.getInputStream(ze);
BufferedReader cityGMLZipReader = new BufferedReader(
new InputStreamReader(cityGMLInputStream));
BufferedWriter cityGMLOutput = Files.newBufferedWriter(extractedCityGML.toPath());) {
String buf = null;
//TODO: Get EPSG:id from NovaFactory Server?
while ((buf = cityGMLZipReader.readLine()) != null) {
cityGMLOutput.write(buf.replace("srsName=\"\"", "srsName=\"EPSG:31467\""));
}
}
LOGGER.info("Extracted");
}
}
}
}
}
public void downloadRegionFromCityGML(String wktPolygon, String project, String citygml, String srsName) public void downloadRegionFromCityGML(String wktPolygon, String project, String citygml, String srsName)
throws IOException, ParseException, XPathParseException, NavException, XPathEvalException { throws IOException, ParseException, XPathParseException, NavException, XPathEvalException {
StringBuilder sb = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath(project, citygml), wktPolygon, StringBuilder sb = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath(project, citygml), wktPolygon,
...@@ -166,20 +113,6 @@ private Path citygmlPath(String project, String citygml) { ...@@ -166,20 +113,6 @@ private Path citygmlPath(String project, String citygml) {
return repo.resolve(project + ".proj").resolve(citygml); return repo.resolve(project + ".proj").resolve(citygml);
} }
public void importNovaFactoryBoundingBoxes() throws IOException {
try (BufferedReader nfCSV = new BufferedReader(new InputStreamReader(
RegionChooserFX.class.getResourceAsStream("website/data/novafactory_products.csv")))) {
String sCurrentLine = nfCSV.readLine(); // Header information is ignored.
while ((sCurrentLine = nfCSV.readLine()) != null) {
String[] values = sCurrentLine.trim().split(",");
String product = values[1];
String[] srs = values[3].split(" ");
String epsgId = srs[srs.length - 1];
jsApp.call("addNovaFactoryProduct", values[8], values[9], values[10], values[11], product,
epsgId);
}
}
}
} }
final WebView browser = new WebView(); final WebView browser = new WebView();
...@@ -199,12 +132,6 @@ public RegionChooserBrowser() { ...@@ -199,12 +132,6 @@ public RegionChooserBrowser() {
jsApp = (JSObject) webEngine.executeScript("regionChooser"); jsApp = (JSObject) webEngine.executeScript("regionChooser");
jsApp.call("setFxApp", fxapp); jsApp.call("setFxApp", fxapp);
fxapp.refreshHulls(); fxapp.refreshHulls();
try {
fxapp.importNovaFactoryBoundingBoxes();
} catch (Exception ex) {
LOGGER.warning("NovaFactory CSV not found or corrupt");
ex.printStackTrace();
}
} }
}); });
//add the web view to the scene //add the web view to the scene
......
Id,Short name,Name,SRS,Scale,Plot-Header,Subdivision,Metadata layer,Abscissa SW,Ordinate SW,Abscissa NO,Ordinate NO
4,WU,Gemeinde Wuestenrot LOD2 Test,DHDN_3_Degree_Gauss_Zone_3 31467,1,,Gemeinde Wuestenrot,GML,3530000,5434300,3538800,5445010
5,LB,Ludwigsburg Gesamt,DHDN_3_Degree_Gauss_Zone_3 31467,1,,Ludwigsburg Gesamt,GML,3510000,5415000,3523100,5422000
7,LBDEV,Ludwigsburg Gesamt (Entwicklung),DHDN_3_Degree_Gauss_Zone_3 31467,1,,Ludwigsburg Gesamt Test,,3530000,5434300,3538800,5445010
3,LBTEST,Ludwigsburg Gesamt Test,DHDN_3_Degree_Gauss_Zone_3 31467,1,,Ludwigsburg Gesamt Test,GML,3509700,5414200,3523500,5422800
2,TESTGR,Testgebiet Grünbühl,DHDN_3_Degree_Gauss_Zone_3 31467,1,,Testgebiet2,rgb,3514800,5415450,3516300,5416540
1,TEST,Testgebiet 821,DHDN_3_Degree_Gauss_Zone_3 31467,1,,Testgebiet,GML,3534000,5436000,3538000,5442000
8,WUDEV,Wuestenrot (Entwicklung),DHDN_3_Degree_Gauss_Zone_3 31467,1,,Gemeinde Wuestenrot,GML,3530000,5434300,3538800,5445010
6,WU3,Wuestenrot LOD2 Stufe 3,DHDN_3_Degree_Gauss_Zone_3 31467,1,,Wuestenrot LOD2 Blattschnitt,GML,3530000,5434300,3538800,5445010
...@@ -8,9 +8,7 @@ ...@@ -8,9 +8,7 @@
content="Google Map V3 Polygon Creator for Simstadt"> content="Google Map V3 Polygon Creator for Simstadt">
<link rel="stylesheet" type="text/css" href="style/style.css"> <link rel="stylesheet" type="text/css" href="style/style.css">
<!-- Firebug for js console:
<script type='text/javascript' src='script/firebug-lite-compressed.js'></script> <script type='text/javascript' src='script/firebug-lite-compressed.js'></script>
-->
<script type="text/javascript" src="script/proj4.js"></script> <script type="text/javascript" src="script/proj4.js"></script>
<script type="text/javascript" src="script/jquery-1.4.2.min.js"></script> <script type="text/javascript" src="script/jquery-1.4.2.min.js"></script>
<!-- OpenLayers v3.4.0. API doc : http://openlayers.org/en/v3.4.0/apidoc/ --> <!-- OpenLayers v3.4.0. API doc : http://openlayers.org/en/v3.4.0/apidoc/ -->
......
...@@ -19,7 +19,6 @@ var regionChooser = (function(){ ...@@ -19,7 +19,6 @@ var regionChooser = (function(){
var dataPanel = $('#dataPanel'); var dataPanel = $('#dataPanel');
var wgs84Sphere = new ol.Sphere(6378137); var wgs84Sphere = new ol.Sphere(6378137);
var gmlId = 0; var gmlId = 0;
var novaFactoryId = 0;
if (fromJavaFX){ if (fromJavaFX){
$("html").addClass("wait"); $("html").addClass("wait");
...@@ -69,10 +68,6 @@ var regionChooser = (function(){ ...@@ -69,10 +68,6 @@ var regionChooser = (function(){
}) })
}); });
novafactory_vectors = new ol.source.Vector({
features : []
});
publicScope.addCityGmlHull = function(kmlString) { publicScope.addCityGmlHull = function(kmlString) {
options = {featureProjection: ol.proj.get('EPSG:3857')}; options = {featureProjection: ol.proj.get('EPSG:3857')};
feature = kmlFormat.readFeature(kmlString, options); feature = kmlFormat.readFeature(kmlString, options);
...@@ -85,32 +80,9 @@ var regionChooser = (function(){ ...@@ -85,32 +80,9 @@ var regionChooser = (function(){
} }
}; };
publicScope.addNovaFactoryProduct = function(xmin, ymin, xmax, ymax, name, epsgId) {
var box = new ol.geom.Polygon(
[ [ [ xmin, ymin ], [ xmin, ymax ], [ xmax, ymax ], [ xmax, ymin ], [ xmin, ymin ] ] ]);
box.transform('EPSG:' + epsgId, 'EPSG:3857');
var feature = new ol.Feature({
geometry : box,
name : name,
});
feature["geoJSON"] = geoJsonFormat.writeFeatureObject(feature);
feature["area"] = feature.getGeometry().getArea();
feature["project"] = "novaFACTORY";
feature["name"] = name;
feature["source"] = "NovaFACTORY";
feature.setId(novaFactoryId++);
novafactory_vectors.addFeature(feature);
};
var novafactory_layer = new ol.layer.Vector({
source : novafactory_vectors,
style : polygon_style('#ff7700', 0.1)
});
var map = new ol.Map({ var map = new ol.Map({
target : 'map', target : 'map',
layers : [ osm_layer, kml_layer, novafactory_layer, intersections_layer ], layers : [ osm_layer, kml_layer, intersections_layer ],
interactions : ol.interaction.defaults({ interactions : ol.interaction.defaults({
keyboard : true keyboard : true
}) })
...@@ -226,8 +198,6 @@ var regionChooser = (function(){ ...@@ -226,8 +198,6 @@ var regionChooser = (function(){
intersections.clear(); intersections.clear();
features_by_project = groupBy(kml_source.getFeatures(), "project"); features_by_project = groupBy(kml_source.getFeatures(), "project");
features_by_project["NovaFactory"] = novafactory_vectors.getFeatures();
Object.keys(features_by_project).sort().forEach(function(project) { Object.keys(features_by_project).sort().forEach(function(project) {
features = features_by_project[project]; features = features_by_project[project];
features_and_intersections = features.map(f=> [f, findIntersection(f,polygon)]).filter(l => l[1] !== undefined); features_and_intersections = features.map(f=> [f, findIntersection(f,polygon)]).filter(l => l[1] !== undefined);
...@@ -327,32 +297,6 @@ var regionChooser = (function(){ ...@@ -327,32 +297,6 @@ var regionChooser = (function(){
} }
} }
novafactory_layer.downloadFinished = function() {
// FIXME: Weird <br>s are inserted between lines
// FIXME: Doesn't stop waiting cursor
$("html").removeClass("wait");
setTimeout(function() {
dataPanel.append("NovaFactory : DONE <br/>\n");
}, 100);
};
novafactory_layer.updateStatus = function(status) {
dataPanel.append("NovaFactory : " + status + "<br/>\n");
};
novafactory_layer.selectSaveFile = function(zipFilename) {
fxapp.extractZIPtoGML(zipFilename);
};
publicScope.downloadRegionFromNovaFACTORY = function(i) {
$("html").addClass("wait");
var feature = novafactory_vectors.getFeatureById(i);
// Waiting 100ms in order to let the cursor change
setTimeout(function() {
fxapp.downloadRegion(sketchAsWKT(), feature.get('name'), novafactory_layer);
}, 100);
}
function sketchAsWKT(srsName) { function sketchAsWKT(srsName) {
srsName = (typeof srsName === 'undefined') ? 'EPSG:4326' : srsName; srsName = (typeof srsName === 'undefined') ? 'EPSG:4326' : srsName;
var wktFormat = new ol.format.WKT(); var wktFormat = new ol.format.WKT();
......
package eu.simstadt.nf4j.async;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Scanner;
import java.util.zip.ZipInputStream;
import org.junit.Test;
import eu.simstadt.nf4j.FailedTransmissionException;
import eu.simstadt.nf4j.InvalidJobDescriptorException;
import eu.simstadt.nf4j.JobStatus;
import eu.simstadt.nf4j.async.AsyncExportJob;
import eu.simstadt.nf4j.async.ExportJobDescription;
import eu.simstadt.nf4j.async.HTTPConnection;
import eu.simstadt.nf4j.async.JobStatusEvent;
import eu.simstadt.nf4j.async.JobStatusListener;
import eu.simstadt.nf4j.async.Layer;
import eu.simstadt.nf4j.async.Unit;
/**
* This class contains client oriented export job tests. It will send an export job and listens to status updates. Every
* of the subsequent status' LOCAL, SENT, PENDING, RUNNING, FINISHED and DOWNLOAD have to be signaled to this test
* class.
*
* @author Marcel Bruse
*/
public class SuccessfulExportJob implements JobStatusListener
{
public AsyncExportJob job;
@Test
public void processJob() throws InterruptedException {
ExportJobDescription description = ExportJobDescription.getDefaultDescriptor();
description.setInitiator(String.valueOf((int) (Math.random() * 9999)));
String userName = System.getProperty("user.name");
description.setAccount(userName);
description.setProduct("WU3");
description.setJobnumber(userName);
description.setLODs("2");
//FIXME: Zipped GMLs coming from nF don't have any defined srsName
//FIXME: Save files somewhere else
//NOTE: Unit is a predefined Map Region.
// Some of those units are empty. 821 (Finsterrot) and 824 (Neulautern) are available on HFT nF Server.
// <designation>
// 820
// </designation><name>
// Wuestenrot
// </name></mapsheet><mapsheet nr="127"><designation>
// 821
// </designation><name>
// Finsterrot
// </name></mapsheet><mapsheet nr="128"><designation>
// 822
// </designation><name>
// Maienfels
// </name></mapsheet><mapsheet nr="129"><designation>
// 823
// </designation><name>
// Neuhütten
// </name></mapsheet><mapsheet nr="130"><designation>
// 824
// </designation><name>
// Neulautern
// </name></mapsheet><mapsheet nr="131"><designation>
// 824-1
// </designation><name>
// Neulautern (1)
// </name>
Unit unit = Unit.getDefaultUnit();
unit.setValue("824");
description.addUnit(unit);
//NOTE: Polygon selection. This would be for a small part of Neulautern
// ArrayList<Coord> regionPolygon = new ArrayList<>();
// regionPolygon.add(new Coord(49.06020829807264, 9.432239985562616));
// regionPolygon.add(new Coord(49.05989193639516, 9.432497477628047));
// regionPolygon.add(new Coord(49.05968102749148, 9.432883715726192));
// regionPolygon.add(new Coord(49.05935060174289, 9.433001732922845));
// regionPolygon.add(new Coord(49.058422585764504, 9.433066105939206));
// regionPolygon.add(new Coord(49.05806402949591, 9.433248496152215));
// regionPolygon.add(new Coord(49.05748752183746, 9.434353566266353));
// regionPolygon.add(new Coord(49.05788826567445, 9.435544467068967));
// regionPolygon.add(new Coord(49.06072150273306, 9.435233330823237));
// regionPolygon.add(new Coord(49.06133312328379, 9.43515822897082));
// regionPolygon.add(new Coord(49.06143154427858, 9.43440721044665));
// regionPolygon.add(new Coord(49.06020829807264, 9.432239985562616));
//
// description.setRegionPolygon(regionPolygon);
Layer layer = Layer.getDefaultLayer();
layer.setProduct("WU3");
layer.setName("GML");
description.addLayer(layer);
job = new AsyncExportJob(description, new HTTPConnection("193.196.136.164"));
job.addJobStatusListener(this);
try {
job.send();
} catch (FailedTransmissionException ex) {
ex.printStackTrace();
} catch (InvalidJobDescriptorException ex) {
ex.printStackTrace();
}
// Wait for timeout, failure or that all tests pass
long timeout = 1000 * 60 * 3l; // 3 minutes maximum
long interval = 10000l;
while (!job.hasFinished() && !job.hasFailed() && timeout > 0) {
Thread.sleep(interval);
timeout -= interval;
System.out.println("+");
}
}
@Override
public void jobStatusChanged(JobStatusEvent event) {
JobStatus status = (JobStatus) event.getSource();
System.out.println(status);
if (status == JobStatus.LOCAL) {
assertTrue(true);
} else if (status == JobStatus.SENT) {
assertTrue(true);
} else if (status == JobStatus.PENDING) {
assertTrue(true);
} else if (status == JobStatus.RUNNING) {
assertTrue(true);
} else if (status == JobStatus.FINISHED) {
try {
assertTrue(true);
job.downloadResult();
} catch (FailedTransmissionException ex) {
ex.printStackTrace();
}
} else if (status == JobStatus.DOWNLOAD) {
try {
File file = job.getResult();
assertTrue(file.canRead());
testForExistingLOD2AndMissingLOD1(file);
} catch (FailedTransmissionException ex) {
ex.printStackTrace();
}
}
}
/**
* These asserts ensure that only LOD2 has been loaded as specified in the job descriptor above.
*/
private void testForExistingLOD2AndMissingLOD1(File file) {
FileInputStream fileStream;
try {
fileStream = new FileInputStream(file);
ZipInputStream unzipStream = new ZipInputStream(fileStream);
unzipStream.getNextEntry(); // Skip the first entry, its the job description
unzipStream.getNextEntry();
File handle = Files.createTempDirectory("nfDownload").resolve("test.gml").toFile();
BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream(handle));
byte[] in = new byte[4096];
int read = 0;
while ((read = unzipStream.read(in)) != -1) {
bos.write(in, 0, read);
}
unzipStream.closeEntry();
bos.close();
unzipStream.close();
Scanner scanner = new Scanner(handle);
boolean lod1Missing = true;
boolean lod2Found = false;
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.contains("lod2")) {
lod2Found = true;
}
if (line.contains("lod1")) {
lod1Missing = false;
}
}
scanner.close();
assertTrue(lod1Missing);
assertTrue(lod2Found);
} catch (IOException ex) {
fail();
}
}
}
\ No newline at end of file
package eu.simstadt.nf4j.async;
import static org.junit.Assert.assertTrue;
import java.io.File;
import org.junit.Test;
import eu.simstadt.nf4j.FailedTransmissionException;
import eu.simstadt.nf4j.InvalidJobDescriptorException;
import eu.simstadt.nf4j.JobStatus;
import eu.simstadt.nf4j.async.AsyncImportJob;
import eu.simstadt.nf4j.async.HTTPConnection;
import eu.simstadt.nf4j.async.ImportJobDescription;
import eu.simstadt.nf4j.async.JobStatusEvent;
import eu.simstadt.nf4j.async.JobStatusListener;
/**
* This class contains client oriented import job tests. It will send an import job and listens to
* status updates. Every of the subsequent status' LOCAL, SENT, PENDING, RUNNING, FINISHED
* have to be signaled to this test class.
*
* @author Marcel Bruse
*/
public class SuccessfulImportJob implements JobStatusListener {
public AsyncImportJob job;
@Test
public void processJob() throws InterruptedException {
ImportJobDescription desc = ImportJobDescription.getDefaultDescriptor();
desc.setProduct("LBTEST");
desc.setLeaf("GR");
desc.setCityGMLFile(new File("SomeBuildings.gml"));
HTTPConnection connector = new HTTPConnection("193.196.136.164");
job = new AsyncImportJob(desc, connector);
job.addJobStatusListener(this);
try {
job.send();
} catch (InvalidJobDescriptorException ex) {
ex.printStackTrace();
} catch (FailedTransmissionException ex) {
ex.printStackTrace();
}
// Wait for timeout, failure or that all tests pass
long timeout = 1000 * 60 * 5l; // 5 minutes maximum
long interval = 10000l;
while (!job.hasFinished() && !job.hasFailed() && timeout > 0) {
Thread.sleep(interval);
timeout -= interval;
}
}
@Override
public void jobStatusChanged(JobStatusEvent event) {
JobStatus status = (JobStatus) event.getSource();
System.out.println(status);
if (status == JobStatus.LOCAL) {
assertTrue(true);
} else if (status == JobStatus.SENT) {
assertTrue(true);
} else if (status == JobStatus.PENDING) {
assertTrue(true);
} else if (status == JobStatus.RUNNING) {
assertTrue(true);
} else if (status == JobStatus.FINISHED) {
assertTrue(true);
}
}
}
\ No newline at end of file
Supports Markdown
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