mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-12 23:30:59 +00:00
Bug 4371: Split of WindImporter and WindImportServlet as preparation to
reuse it in the context of expedition all in one import
This commit is contained in:
1 parent
34533623f0
commit
b077f455bc
10 files changed
+470
-399
No files matched your search
+8
-160
@@ -1,12 +1,7 @@
|
||||
package com.sap.sailing.server.gateway.windimport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -24,127 +19,19 @@ import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.trackimport.FormatNotSupportedException;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.server.gateway.SailingServerHttpServlet;
|
||||
import com.sap.sailing.server.gateway.windimport.AbstractWindImportServlet.WindImportResult.RaceEntry;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sailing.server.gateway.windimport.AbstractWindImporter.UploadRequest;
|
||||
import com.sap.sailing.server.gateway.windimport.AbstractWindImporter.WindImportResult;
|
||||
|
||||
public abstract class AbstractWindImportServlet extends SailingServerHttpServlet {
|
||||
private static final Logger logger = Logger.getLogger(AbstractWindImportServlet.class.getName());
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static class UploadRequest {
|
||||
public String boatId;
|
||||
public final List<FileItem> files = new ArrayList<FileItem>();
|
||||
public List<RegattaAndRaceIdentifier> races = new ArrayList<RegattaAndRaceIdentifier>();;
|
||||
}
|
||||
|
||||
static class WindImportResult {
|
||||
private Date first;
|
||||
private Date last;
|
||||
public String error;
|
||||
|
||||
public final List<RaceEntry> raceEntries = new ArrayList<RaceEntry>();
|
||||
|
||||
public Date getFirst() {
|
||||
return first;
|
||||
}
|
||||
|
||||
public Date getLast() {
|
||||
return last;
|
||||
}
|
||||
|
||||
public void update(Wind newWind) {
|
||||
Date newDate = newWind.getTimePoint().asDate();
|
||||
if (this.first == null || newDate.before(this.first)) {
|
||||
this.first = newDate;
|
||||
}
|
||||
if (this.last == null || newDate.after(this.last)) {
|
||||
this.last = newDate;
|
||||
}
|
||||
}
|
||||
|
||||
RaceEntry addRaceEntry(String regattaName, String raceName) {
|
||||
RaceEntry raceEntry = new RaceEntry(regattaName, raceName);
|
||||
raceEntries.add(raceEntry);
|
||||
return raceEntry;
|
||||
}
|
||||
|
||||
static class RaceEntry {
|
||||
public final String regattaName;
|
||||
public final String raceName;
|
||||
private int count;
|
||||
private Date first;
|
||||
private Date last;
|
||||
|
||||
private RaceEntry(String regattaName, String raceName) {
|
||||
this.regattaName = regattaName;
|
||||
this.raceName = raceName;
|
||||
}
|
||||
|
||||
public void update(Wind newWind) {
|
||||
count++;
|
||||
Date newDate = newWind.getTimePoint().asDate();
|
||||
if (this.first == null || newDate.before(this.first)) {
|
||||
this.first = newDate;
|
||||
}
|
||||
if (this.last == null || newDate.after(this.last)) {
|
||||
this.last = newDate;
|
||||
}
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public Date getFirst() {
|
||||
return first;
|
||||
}
|
||||
|
||||
public Date getLast() {
|
||||
return last;
|
||||
}
|
||||
|
||||
private JSONObject json() {
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("regattaName", regattaName);
|
||||
result.put("raceName", raceName);
|
||||
result.put("count", getCount());
|
||||
if (getFirst() != null) {
|
||||
result.put("first", getFirst().getTime());
|
||||
}
|
||||
if (getLast() != null) {
|
||||
result.put("last", getLast().getTime());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public JSONObject json() {
|
||||
JSONObject result = new JSONObject();
|
||||
if (getFirst() != null) {
|
||||
result.put("first", getFirst().getTime());
|
||||
}
|
||||
if (getLast() != null) {
|
||||
result.put("last", getLast().getTime());
|
||||
}
|
||||
result.put("error", error);
|
||||
JSONArray raceEntriesJson = new JSONArray();
|
||||
for (RaceEntry raceEntry : raceEntries) {
|
||||
if (raceEntry.count > 0) {
|
||||
raceEntriesJson.add(raceEntry.json());
|
||||
}
|
||||
}
|
||||
result.put("raceEntries", raceEntriesJson);
|
||||
return result;
|
||||
}
|
||||
|
||||
private final AbstractWindImporter importer;
|
||||
|
||||
public AbstractWindImportServlet(AbstractWindImporter importer) {
|
||||
this.importer = importer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -157,41 +44,7 @@ public abstract class AbstractWindImportServlet extends SailingServerHttpServlet
|
||||
WindImportResult windImportResult = new WindImportResult();
|
||||
try {
|
||||
UploadRequest uploadRequest = readRequest(request);
|
||||
WindSource windSource = getWindSource(uploadRequest);
|
||||
List<DynamicTrackedRace> trackedRaces = new ArrayList<DynamicTrackedRace>();
|
||||
if (uploadRequest.races.size() > 0) {
|
||||
for (RegattaAndRaceIdentifier raceEntry : uploadRequest.races) {
|
||||
DynamicTrackedRace trackedRace = getService().getTrackedRace(raceEntry);
|
||||
if (trackedRace != null) {
|
||||
trackedRaces.add(trackedRace);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (Regatta regatta : getService().getAllRegattas()) {
|
||||
for (RaceDefinition raceDefinition : regatta.getAllRaces()) {
|
||||
trackedRaces.add(getService().getTrackedRegatta(regatta).getTrackedRace(raceDefinition));
|
||||
}
|
||||
}
|
||||
}
|
||||
final Map<InputStream, String> streamsWithFilenames = new HashMap<>();
|
||||
for (FileItem file : uploadRequest.files) {
|
||||
streamsWithFilenames.put(file.getInputStream(), file.getName());
|
||||
}
|
||||
Iterable<Wind> windFixes = importWind(streamsWithFilenames);
|
||||
if (!Util.isEmpty(windFixes)) {
|
||||
for (DynamicTrackedRace trackedRace : trackedRaces) {
|
||||
RegattaAndRaceIdentifier raceIdentifier = trackedRace.getRaceIdentifier();
|
||||
RaceEntry raceEntry = windImportResult.addRaceEntry(raceIdentifier.getRegattaName(),
|
||||
raceIdentifier.getRaceName());
|
||||
for (Wind wind : windFixes) {
|
||||
windImportResult.update(wind);
|
||||
if (trackedRace.recordWind(wind, windSource)) {
|
||||
raceEntry.update(wind);
|
||||
}
|
||||
}
|
||||
getService().getPolarDataService().insertExistingFixes(trackedRace);
|
||||
}
|
||||
}
|
||||
importer.importWindForUploadRequest(getService(), windImportResult, uploadRequest);
|
||||
// Use text/html to prevent browsers from wrapping the response body,
|
||||
// see "Handling File Upload Responses in GWT" at http://www.artofsolving.com/node/50
|
||||
} catch (Exception e) {
|
||||
@@ -202,11 +55,6 @@ public abstract class AbstractWindImportServlet extends SailingServerHttpServlet
|
||||
response.getWriter().append(windImportResult.json().toJSONString());
|
||||
}
|
||||
|
||||
protected abstract Iterable<Wind> importWind(Map<InputStream, String> streamsWithFilenames)
|
||||
throws IOException, InterruptedException, FormatNotSupportedException;
|
||||
|
||||
protected abstract WindSource getWindSource(UploadRequest uploadRequest);
|
||||
|
||||
private UploadRequest readRequest(HttpServletRequest req) throws FileUploadException, ParseException {
|
||||
UploadRequest result = new UploadRequest();
|
||||
// http://commons.apache.org/fileupload/using.html
|
||||
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
package com.sap.sailing.server.gateway.windimport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.fileupload.FileItem;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.trackimport.FormatNotSupportedException;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.server.gateway.windimport.AbstractWindImporter.WindImportResult.RaceEntry;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public abstract class AbstractWindImporter {
|
||||
public static class UploadRequest {
|
||||
public String boatId;
|
||||
public final List<FileItem> files = new ArrayList<FileItem>();
|
||||
public List<RegattaAndRaceIdentifier> races = new ArrayList<RegattaAndRaceIdentifier>();;
|
||||
}
|
||||
|
||||
public static class WindImportResult {
|
||||
private Date first;
|
||||
private Date last;
|
||||
public String error;
|
||||
|
||||
public final List<RaceEntry> raceEntries = new ArrayList<RaceEntry>();
|
||||
|
||||
public Date getFirst() {
|
||||
return first;
|
||||
}
|
||||
|
||||
public Date getLast() {
|
||||
return last;
|
||||
}
|
||||
|
||||
public void update(Wind newWind) {
|
||||
Date newDate = newWind.getTimePoint().asDate();
|
||||
if (this.first == null || newDate.before(this.first)) {
|
||||
this.first = newDate;
|
||||
}
|
||||
if (this.last == null || newDate.after(this.last)) {
|
||||
this.last = newDate;
|
||||
}
|
||||
}
|
||||
|
||||
RaceEntry addRaceEntry(String regattaName, String raceName) {
|
||||
RaceEntry raceEntry = new RaceEntry(regattaName, raceName);
|
||||
raceEntries.add(raceEntry);
|
||||
return raceEntry;
|
||||
}
|
||||
|
||||
static class RaceEntry {
|
||||
public final String regattaName;
|
||||
public final String raceName;
|
||||
private int count;
|
||||
private Date first;
|
||||
private Date last;
|
||||
|
||||
private RaceEntry(String regattaName, String raceName) {
|
||||
this.regattaName = regattaName;
|
||||
this.raceName = raceName;
|
||||
}
|
||||
|
||||
public void update(Wind newWind) {
|
||||
count++;
|
||||
Date newDate = newWind.getTimePoint().asDate();
|
||||
if (this.first == null || newDate.before(this.first)) {
|
||||
this.first = newDate;
|
||||
}
|
||||
if (this.last == null || newDate.after(this.last)) {
|
||||
this.last = newDate;
|
||||
}
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public Date getFirst() {
|
||||
return first;
|
||||
}
|
||||
|
||||
public Date getLast() {
|
||||
return last;
|
||||
}
|
||||
|
||||
private JSONObject json() {
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("regattaName", regattaName);
|
||||
result.put("raceName", raceName);
|
||||
result.put("count", getCount());
|
||||
if (getFirst() != null) {
|
||||
result.put("first", getFirst().getTime());
|
||||
}
|
||||
if (getLast() != null) {
|
||||
result.put("last", getLast().getTime());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public JSONObject json() {
|
||||
JSONObject result = new JSONObject();
|
||||
if (getFirst() != null) {
|
||||
result.put("first", getFirst().getTime());
|
||||
}
|
||||
if (getLast() != null) {
|
||||
result.put("last", getLast().getTime());
|
||||
}
|
||||
result.put("error", error);
|
||||
JSONArray raceEntriesJson = new JSONArray();
|
||||
for (RaceEntry raceEntry : raceEntries) {
|
||||
if (raceEntry.count > 0) {
|
||||
raceEntriesJson.add(raceEntry.json());
|
||||
}
|
||||
}
|
||||
result.put("raceEntries", raceEntriesJson);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public void importWindForUploadRequest(RacingEventService service, WindImportResult windImportResult, UploadRequest uploadRequest)
|
||||
throws IOException, InterruptedException, FormatNotSupportedException {
|
||||
WindSource windSource = getWindSource(uploadRequest);
|
||||
List<DynamicTrackedRace> trackedRaces = new ArrayList<DynamicTrackedRace>();
|
||||
if (uploadRequest.races.size() > 0) {
|
||||
for (RegattaAndRaceIdentifier raceEntry : uploadRequest.races) {
|
||||
DynamicTrackedRace trackedRace = service.getTrackedRace(raceEntry);
|
||||
if (trackedRace != null) {
|
||||
trackedRaces.add(trackedRace);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (Regatta regatta : service.getAllRegattas()) {
|
||||
for (RaceDefinition raceDefinition : regatta.getAllRaces()) {
|
||||
trackedRaces.add(service.getTrackedRegatta(regatta).getTrackedRace(raceDefinition));
|
||||
}
|
||||
}
|
||||
}
|
||||
final Map<InputStream, String> streamsWithFilenames = new HashMap<>();
|
||||
for (FileItem file : uploadRequest.files) {
|
||||
streamsWithFilenames.put(file.getInputStream(), file.getName());
|
||||
}
|
||||
importWindToWindSourceAndTrackedRaces(service, windImportResult, windSource, trackedRaces, streamsWithFilenames);
|
||||
}
|
||||
|
||||
public void importWindToWindSourceAndTrackedRaces(RacingEventService service, WindImportResult windImportResult, WindSource windSource,
|
||||
List<DynamicTrackedRace> trackedRaces, final Map<InputStream, String> streamsWithFilenames)
|
||||
throws IOException, InterruptedException, FormatNotSupportedException {
|
||||
Iterable<Wind> windFixes = importWind(streamsWithFilenames);
|
||||
if (!Util.isEmpty(windFixes)) {
|
||||
for (DynamicTrackedRace trackedRace : trackedRaces) {
|
||||
RegattaAndRaceIdentifier raceIdentifier = trackedRace.getRaceIdentifier();
|
||||
RaceEntry raceEntry = windImportResult.addRaceEntry(raceIdentifier.getRegattaName(),
|
||||
raceIdentifier.getRaceName());
|
||||
for (Wind wind : windFixes) {
|
||||
windImportResult.update(wind);
|
||||
if (trackedRace.recordWind(wind, windSource)) {
|
||||
raceEntry.update(wind);
|
||||
}
|
||||
}
|
||||
service.getPolarDataService().insertExistingFixes(trackedRace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Iterable<Wind> importWind(Map<InputStream, String> streamsWithFilenames)
|
||||
throws IOException, InterruptedException, FormatNotSupportedException;
|
||||
|
||||
protected abstract WindSource getWindSource(UploadRequest uploadRequest);
|
||||
}
|
||||
+2
-110
@@ -1,119 +1,11 @@
|
||||
package com.sap.sailing.server.gateway.windimport.bravo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.DegreePosition;
|
||||
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.WindImpl;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID;
|
||||
import com.sap.sailing.domain.common.tracking.DoubleVectorFix;
|
||||
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier;
|
||||
import com.sap.sailing.domain.trackimport.BaseDoubleVectorFixImporter.Callback;
|
||||
import com.sap.sailing.domain.trackimport.FormatNotSupportedException;
|
||||
import com.sap.sailing.server.gateway.windimport.AbstractWindImportServlet;
|
||||
import com.sap.sailing.server.trackfiles.impl.BaseBravoDataImporterImpl;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class BravoWindImportServlet extends AbstractWindImportServlet {
|
||||
private static final String BRAVO_WIND_IMPORT = "Bravo Wind Import";
|
||||
private static final String GZIP_SUFFIX = ".gz";
|
||||
private static final long serialVersionUID = -4547876638456305135L;
|
||||
private static final Logger logger = Logger.getLogger(BravoWindImportServlet.class.getName());
|
||||
|
||||
@Override
|
||||
protected WindSource getWindSource(UploadRequest uploadRequest) {
|
||||
final WindSource windSource;
|
||||
final String sourceName;
|
||||
logger.info("Importing Bravo wind data from "+uploadRequest.files);
|
||||
if (uploadRequest.files != null && !uploadRequest.files.isEmpty()) {
|
||||
sourceName = uploadRequest.files.stream().map(f->f.getName()).collect(Collectors.joining(", "));
|
||||
} else {
|
||||
sourceName = BRAVO_WIND_IMPORT;
|
||||
}
|
||||
windSource = new WindSourceWithAdditionalID(WindSourceType.EXPEDITION, sourceName + "@" + MillisecondsTimePoint.now());
|
||||
return windSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<Wind> importWind(Map<InputStream, String> inputStreamsAndFilenames) throws IOException, InterruptedException, FormatNotSupportedException {
|
||||
final Iterable<Wind> result;
|
||||
if (inputStreamsAndFilenames != null && inputStreamsAndFilenames.size() == 1) {
|
||||
logger.info("Reading Bravo wind data from "+inputStreamsAndFilenames.values().iterator().next());
|
||||
result = readWind(inputStreamsAndFilenames.values().iterator().next(), inputStreamsAndFilenames.keySet().iterator().next());
|
||||
} else {
|
||||
final List<Wind> windList = new LinkedList<>();
|
||||
for (final Entry<InputStream, String> inputStreamAndFileName : inputStreamsAndFilenames.entrySet()) {
|
||||
logger.info("Reading Bravo wind data from "+inputStreamAndFileName.getValue());
|
||||
Util.addAll(readWind(inputStreamAndFileName.getValue(), inputStreamAndFileName.getKey()), windList);
|
||||
}
|
||||
result = windList;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static enum Fields {
|
||||
Lat, Lon, TWS, TWD;
|
||||
}
|
||||
|
||||
private Iterable<Wind> readWind(String filename, InputStream inputStream) throws InterruptedException, IOException, FormatNotSupportedException {
|
||||
final List<Wind> result = new LinkedList<>();
|
||||
Map<String, Integer> columnsMap = new HashMap<>();
|
||||
for (final Fields field : Fields.values()) {
|
||||
columnsMap.put(field.name(), field.ordinal());
|
||||
}
|
||||
final BaseBravoDataImporterImpl importer = new BaseBravoDataImporterImpl(columnsMap, BRAVO_WIND_IMPORT);
|
||||
final Callback callback = new Callback() {
|
||||
@Override
|
||||
public void addFixes(Iterable<DoubleVectorFix> fixes, TrackFileImportDeviceIdentifier device) {
|
||||
for (final DoubleVectorFix fix : fixes) {
|
||||
// latitude / longitude are represented in funny NMEA-like way; the value divided by 100 as
|
||||
// a floored integer represents the full degrees; the value modulo 100 represents the decimal
|
||||
// minutes. Example: the pair (4124.645890, 213.738670) stands for N41�24.645890 E002�13.738670
|
||||
final Wind wind = new WindImpl(new DegreePosition(FunnyDegreeConverter.funnyLatLng(fix.get(Fields.Lat.ordinal())),
|
||||
FunnyDegreeConverter.funnyLatLng(fix.get(Fields.Lon.ordinal()))),
|
||||
fix.getTimePoint(), new KnotSpeedWithBearingImpl(fix.get(Fields.TWS.ordinal()),
|
||||
new DegreeBearingImpl(fix.get(Fields.TWD.ordinal())).reverse()));
|
||||
result.add(wind);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (filename.toLowerCase().endsWith(".zip")) {
|
||||
logger.info("Bravo file "+filename+" is a ZIP file");
|
||||
try (final ZipInputStream zipInputStream = new ZipInputStream(inputStream)) {
|
||||
ZipEntry entry;
|
||||
while ((entry=zipInputStream.getNextEntry()) != null) {
|
||||
if (entry.getName().toLowerCase().endsWith(".txt")) {
|
||||
logger.info("Reading Bravo wind data from "+filename+"'s ZIP entry "+entry.getName());
|
||||
importer.importFixes(zipInputStream, callback, entry.getName(), BRAVO_WIND_IMPORT, /* downsample */ false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final String actualFileName;
|
||||
if (filename.toLowerCase().endsWith(GZIP_SUFFIX)) {
|
||||
inputStream = new GZIPInputStream(inputStream);
|
||||
actualFileName = filename.substring(0, filename.length()-GZIP_SUFFIX.length());
|
||||
} else {
|
||||
actualFileName = filename;
|
||||
}
|
||||
importer.importFixes(inputStream, callback, actualFileName, BRAVO_WIND_IMPORT, /* downsample */ false);
|
||||
}
|
||||
return result;
|
||||
public BravoWindImportServlet() {
|
||||
super(new BravoWindImporter());
|
||||
}
|
||||
}
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
package com.sap.sailing.server.gateway.windimport.bravo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.DegreePosition;
|
||||
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.WindImpl;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID;
|
||||
import com.sap.sailing.domain.common.tracking.DoubleVectorFix;
|
||||
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier;
|
||||
import com.sap.sailing.domain.trackimport.BaseDoubleVectorFixImporter.Callback;
|
||||
import com.sap.sailing.domain.trackimport.FormatNotSupportedException;
|
||||
import com.sap.sailing.server.gateway.windimport.AbstractWindImporter;
|
||||
import com.sap.sailing.server.trackfiles.impl.BaseBravoDataImporterImpl;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class BravoWindImporter extends AbstractWindImporter {
|
||||
private static final String BRAVO_WIND_IMPORT = "Bravo Wind Import";
|
||||
private static final String GZIP_SUFFIX = ".gz";
|
||||
private static final Logger logger = Logger.getLogger(BravoWindImporter.class.getName());
|
||||
|
||||
@Override
|
||||
protected WindSource getWindSource(UploadRequest uploadRequest) {
|
||||
final WindSource windSource;
|
||||
final String sourceName;
|
||||
logger.info("Importing Bravo wind data from "+uploadRequest.files);
|
||||
if (uploadRequest.files != null && !uploadRequest.files.isEmpty()) {
|
||||
sourceName = uploadRequest.files.stream().map(f->f.getName()).collect(Collectors.joining(", "));
|
||||
} else {
|
||||
sourceName = BRAVO_WIND_IMPORT;
|
||||
}
|
||||
windSource = new WindSourceWithAdditionalID(WindSourceType.EXPEDITION, sourceName + "@" + MillisecondsTimePoint.now());
|
||||
return windSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<Wind> importWind(Map<InputStream, String> inputStreamsAndFilenames) throws IOException, InterruptedException, FormatNotSupportedException {
|
||||
final Iterable<Wind> result;
|
||||
if (inputStreamsAndFilenames != null && inputStreamsAndFilenames.size() == 1) {
|
||||
logger.info("Reading Bravo wind data from "+inputStreamsAndFilenames.values().iterator().next());
|
||||
result = readWind(inputStreamsAndFilenames.values().iterator().next(), inputStreamsAndFilenames.keySet().iterator().next());
|
||||
} else {
|
||||
final List<Wind> windList = new LinkedList<>();
|
||||
for (final Entry<InputStream, String> inputStreamAndFileName : inputStreamsAndFilenames.entrySet()) {
|
||||
logger.info("Reading Bravo wind data from "+inputStreamAndFileName.getValue());
|
||||
Util.addAll(readWind(inputStreamAndFileName.getValue(), inputStreamAndFileName.getKey()), windList);
|
||||
}
|
||||
result = windList;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static enum Fields {
|
||||
Lat, Lon, TWS, TWD;
|
||||
}
|
||||
|
||||
private Iterable<Wind> readWind(String filename, InputStream inputStream) throws InterruptedException, IOException, FormatNotSupportedException {
|
||||
final List<Wind> result = new LinkedList<>();
|
||||
Map<String, Integer> columnsMap = new HashMap<>();
|
||||
for (final Fields field : Fields.values()) {
|
||||
columnsMap.put(field.name(), field.ordinal());
|
||||
}
|
||||
final BaseBravoDataImporterImpl importer = new BaseBravoDataImporterImpl(columnsMap, BRAVO_WIND_IMPORT);
|
||||
final Callback callback = new Callback() {
|
||||
@Override
|
||||
public void addFixes(Iterable<DoubleVectorFix> fixes, TrackFileImportDeviceIdentifier device) {
|
||||
for (final DoubleVectorFix fix : fixes) {
|
||||
// latitude / longitude are represented in funny NMEA-like way; the value divided by 100 as
|
||||
// a floored integer represents the full degrees; the value modulo 100 represents the decimal
|
||||
// minutes. Example: the pair (4124.645890, 213.738670) stands for N41�24.645890 E002�13.738670
|
||||
final Wind wind = new WindImpl(new DegreePosition(FunnyDegreeConverter.funnyLatLng(fix.get(Fields.Lat.ordinal())),
|
||||
FunnyDegreeConverter.funnyLatLng(fix.get(Fields.Lon.ordinal()))),
|
||||
fix.getTimePoint(), new KnotSpeedWithBearingImpl(fix.get(Fields.TWS.ordinal()),
|
||||
new DegreeBearingImpl(fix.get(Fields.TWD.ordinal())).reverse()));
|
||||
result.add(wind);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (filename.toLowerCase().endsWith(".zip")) {
|
||||
logger.info("Bravo file "+filename+" is a ZIP file");
|
||||
try (final ZipInputStream zipInputStream = new ZipInputStream(inputStream)) {
|
||||
ZipEntry entry;
|
||||
while ((entry=zipInputStream.getNextEntry()) != null) {
|
||||
if (entry.getName().toLowerCase().endsWith(".txt")) {
|
||||
logger.info("Reading Bravo wind data from "+filename+"'s ZIP entry "+entry.getName());
|
||||
importer.importFixes(zipInputStream, callback, entry.getName(), BRAVO_WIND_IMPORT, /* downsample */ false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final String actualFileName;
|
||||
if (filename.toLowerCase().endsWith(GZIP_SUFFIX)) {
|
||||
inputStream = new GZIPInputStream(inputStream);
|
||||
actualFileName = filename.substring(0, filename.length()-GZIP_SUFFIX.length());
|
||||
} else {
|
||||
actualFileName = filename;
|
||||
}
|
||||
importer.importFixes(inputStream, callback, actualFileName, BRAVO_WIND_IMPORT, /* downsample */ false);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+3
-31
@@ -1,40 +1,12 @@
|
||||
package com.sap.sailing.server.gateway.windimport.expedition;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceImpl;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID;
|
||||
import com.sap.sailing.server.gateway.windimport.AbstractWindImportServlet;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class WindImportServlet extends AbstractWindImportServlet {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
protected WindSource getWindSource(UploadRequest uploadRequest) {
|
||||
WindSource windSource;
|
||||
if (uploadRequest.boatId == null) {
|
||||
windSource = new WindSourceImpl(WindSourceType.EXPEDITION);
|
||||
} else {
|
||||
windSource = new WindSourceWithAdditionalID(WindSourceType.EXPEDITION, uploadRequest.boatId);
|
||||
}
|
||||
return windSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<Wind> importWind(Map<InputStream, String> streamsWithFilenames) throws IOException {
|
||||
final List<Wind> result = new ArrayList<>();
|
||||
for (final InputStream inputStream : streamsWithFilenames.keySet()) {
|
||||
Util.addAll(WindLogParser.importWind(inputStream), result);
|
||||
}
|
||||
return result;
|
||||
|
||||
public WindImportServlet() {
|
||||
super(new WindImporter());
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.sap.sailing.server.gateway.windimport.expedition;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceImpl;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID;
|
||||
import com.sap.sailing.server.gateway.windimport.AbstractWindImporter;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class WindImporter extends AbstractWindImporter {
|
||||
|
||||
@Override
|
||||
protected WindSource getWindSource(UploadRequest uploadRequest) {
|
||||
WindSource windSource;
|
||||
if (uploadRequest.boatId == null) {
|
||||
windSource = new WindSourceImpl(WindSourceType.EXPEDITION);
|
||||
} else {
|
||||
windSource = new WindSourceWithAdditionalID(WindSourceType.EXPEDITION, uploadRequest.boatId);
|
||||
}
|
||||
return windSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<Wind> importWind(Map<InputStream, String> streamsWithFilenames) throws IOException {
|
||||
final List<Wind> result = new ArrayList<>();
|
||||
for (final InputStream inputStream : streamsWithFilenames.keySet()) {
|
||||
Util.addAll(WindLogParser.importWind(inputStream), result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+3
-30
@@ -1,38 +1,11 @@
|
||||
package com.sap.sailing.server.gateway.windimport.grib;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceImpl;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID;
|
||||
import com.sap.sailing.grib.GribWindField;
|
||||
import com.sap.sailing.grib.GribWindFieldFactory;
|
||||
import com.sap.sailing.server.gateway.windimport.AbstractWindImportServlet;
|
||||
|
||||
public class GribWindImportServlet extends AbstractWindImportServlet {
|
||||
private static final long serialVersionUID = -4547876638456305135L;
|
||||
private static final Logger logger = Logger.getLogger(GribWindImportServlet.class.getName());
|
||||
|
||||
@Override
|
||||
protected WindSource getWindSource(UploadRequest uploadRequest) {
|
||||
WindSource windSource;
|
||||
if (uploadRequest.boatId == null) {
|
||||
windSource = new WindSourceImpl(WindSourceType.WEB);
|
||||
} else {
|
||||
windSource = new WindSourceWithAdditionalID(WindSourceType.WEB, uploadRequest.boatId);
|
||||
}
|
||||
return windSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<Wind> importWind(Map<InputStream, String> inputStreamsAndFilenames) throws IOException {
|
||||
final GribWindField windField = GribWindFieldFactory.INSTANCE.createGribWindFieldFromStreams(logger, Level.INFO, inputStreamsAndFilenames);
|
||||
return windField.getAllWindFixes();
|
||||
|
||||
public GribWindImportServlet() {
|
||||
super(new GribWindImporter());
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package com.sap.sailing.server.gateway.windimport.grib;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceImpl;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID;
|
||||
import com.sap.sailing.grib.GribWindField;
|
||||
import com.sap.sailing.grib.GribWindFieldFactory;
|
||||
import com.sap.sailing.server.gateway.windimport.AbstractWindImporter;
|
||||
|
||||
public class GribWindImporter extends AbstractWindImporter {
|
||||
private static final Logger logger = Logger.getLogger(GribWindImporter.class.getName());
|
||||
|
||||
@Override
|
||||
protected WindSource getWindSource(UploadRequest uploadRequest) {
|
||||
WindSource windSource;
|
||||
if (uploadRequest.boatId == null) {
|
||||
windSource = new WindSourceImpl(WindSourceType.WEB);
|
||||
} else {
|
||||
windSource = new WindSourceWithAdditionalID(WindSourceType.WEB, uploadRequest.boatId);
|
||||
}
|
||||
return windSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<Wind> importWind(Map<InputStream, String> inputStreamsAndFilenames) throws IOException {
|
||||
final GribWindField windField = GribWindFieldFactory.INSTANCE.createGribWindFieldFromStreams(logger, Level.INFO, inputStreamsAndFilenames);
|
||||
return windField.getAllWindFixes();
|
||||
}
|
||||
}
|
||||
+3
-68
@@ -1,76 +1,11 @@
|
||||
package com.sap.sailing.server.gateway.windimport.nmea;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID;
|
||||
import com.sap.sailing.nmeaconnector.NmeaFactory;
|
||||
import com.sap.sailing.server.gateway.windimport.AbstractWindImportServlet;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class NmeaWindImportServlet extends AbstractWindImportServlet {
|
||||
private static final long serialVersionUID = -4547876638456305135L;
|
||||
private static final Logger logger = Logger.getLogger(NmeaWindImportServlet.class.getName());
|
||||
|
||||
@Override
|
||||
protected WindSource getWindSource(UploadRequest uploadRequest) {
|
||||
final WindSource windSource;
|
||||
final String sourceName;
|
||||
logger.info("Importing NMEA wind data from "+uploadRequest.files);
|
||||
if (uploadRequest.files != null && !uploadRequest.files.isEmpty()) {
|
||||
sourceName = uploadRequest.files.toString();
|
||||
} else {
|
||||
sourceName = "NMEA Wind Import";
|
||||
}
|
||||
windSource = new WindSourceWithAdditionalID(WindSourceType.WEB, sourceName + "@" + MillisecondsTimePoint.now());
|
||||
return windSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<Wind> importWind(Map<InputStream, String> inputStreamsAndFilenames) throws IOException, InterruptedException {
|
||||
final Iterable<Wind> result;
|
||||
if (inputStreamsAndFilenames != null && inputStreamsAndFilenames.size() == 1) {
|
||||
logger.info("Reading NMEA wind data from "+inputStreamsAndFilenames.values().iterator().next());
|
||||
result = readWind(inputStreamsAndFilenames.values().iterator().next(), inputStreamsAndFilenames.keySet().iterator().next());
|
||||
} else {
|
||||
final List<Wind> windList = new LinkedList<>();
|
||||
for (final Entry<InputStream, String> inputStreamAndFileName : inputStreamsAndFilenames.entrySet()) {
|
||||
logger.info("Reading NMEA wind data from "+inputStreamAndFileName.getValue());
|
||||
Util.addAll(readWind(inputStreamAndFileName.getValue(), inputStreamAndFileName.getKey()), windList);
|
||||
}
|
||||
result = windList;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Iterable<Wind> readWind(String filename, InputStream inputStream) throws InterruptedException, IOException {
|
||||
final Iterable<Wind> result;
|
||||
if (filename.toLowerCase().endsWith("zip")) {
|
||||
logger.info("NMEA file "+filename+" is a ZIP file");
|
||||
final List<Wind> windList = new LinkedList<>();
|
||||
final ZipInputStream zipInputStream = new ZipInputStream(inputStream);
|
||||
ZipEntry entry;
|
||||
while ((entry=zipInputStream.getNextEntry()) != null) {
|
||||
if (entry.getName().toLowerCase().endsWith(".txt")) {
|
||||
logger.info("Reading NMEA wind data from "+filename+"'s ZIP entry "+entry.getName());
|
||||
Util.addAll(NmeaFactory.INSTANCE.readWind(zipInputStream), windList);
|
||||
}
|
||||
}
|
||||
result = windList;
|
||||
} else {
|
||||
result = NmeaFactory.INSTANCE.readWind(inputStream);
|
||||
}
|
||||
return result;
|
||||
|
||||
public NmeaWindImportServlet() {
|
||||
super(new NmeaWindImporter());
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package com.sap.sailing.server.gateway.windimport.nmea;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID;
|
||||
import com.sap.sailing.nmeaconnector.NmeaFactory;
|
||||
import com.sap.sailing.server.gateway.windimport.AbstractWindImporter;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class NmeaWindImporter extends AbstractWindImporter {
|
||||
private static final Logger logger = Logger.getLogger(NmeaWindImporter.class.getName());
|
||||
|
||||
@Override
|
||||
protected WindSource getWindSource(UploadRequest uploadRequest) {
|
||||
final WindSource windSource;
|
||||
final String sourceName;
|
||||
logger.info("Importing NMEA wind data from "+uploadRequest.files);
|
||||
if (uploadRequest.files != null && !uploadRequest.files.isEmpty()) {
|
||||
sourceName = uploadRequest.files.toString();
|
||||
} else {
|
||||
sourceName = "NMEA Wind Import";
|
||||
}
|
||||
windSource = new WindSourceWithAdditionalID(WindSourceType.WEB, sourceName + "@" + MillisecondsTimePoint.now());
|
||||
return windSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<Wind> importWind(Map<InputStream, String> inputStreamsAndFilenames) throws IOException, InterruptedException {
|
||||
final Iterable<Wind> result;
|
||||
if (inputStreamsAndFilenames != null && inputStreamsAndFilenames.size() == 1) {
|
||||
logger.info("Reading NMEA wind data from "+inputStreamsAndFilenames.values().iterator().next());
|
||||
result = readWind(inputStreamsAndFilenames.values().iterator().next(), inputStreamsAndFilenames.keySet().iterator().next());
|
||||
} else {
|
||||
final List<Wind> windList = new LinkedList<>();
|
||||
for (final Entry<InputStream, String> inputStreamAndFileName : inputStreamsAndFilenames.entrySet()) {
|
||||
logger.info("Reading NMEA wind data from "+inputStreamAndFileName.getValue());
|
||||
Util.addAll(readWind(inputStreamAndFileName.getValue(), inputStreamAndFileName.getKey()), windList);
|
||||
}
|
||||
result = windList;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Iterable<Wind> readWind(String filename, InputStream inputStream) throws InterruptedException, IOException {
|
||||
final Iterable<Wind> result;
|
||||
if (filename.toLowerCase().endsWith("zip")) {
|
||||
logger.info("NMEA file "+filename+" is a ZIP file");
|
||||
final List<Wind> windList = new LinkedList<>();
|
||||
final ZipInputStream zipInputStream = new ZipInputStream(inputStream);
|
||||
ZipEntry entry;
|
||||
while ((entry=zipInputStream.getNextEntry()) != null) {
|
||||
if (entry.getName().toLowerCase().endsWith(".txt")) {
|
||||
logger.info("Reading NMEA wind data from "+filename+"'s ZIP entry "+entry.getName());
|
||||
Util.addAll(NmeaFactory.INSTANCE.readWind(zipInputStream), windList);
|
||||
}
|
||||
}
|
||||
result = windList;
|
||||
} else {
|
||||
result = NmeaFactory.INSTANCE.readWind(inputStream);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user