fixed stream handling during wind import; close outside of importFixes to allow for ZIP files

Change-Id: I84ad6234ff51e3738c70df0f48e41d6a4fd73881
This commit is contained in:
Axel Uhl committed 2017-10-23 14:50:54 +02:00
1 parent 47d479195f
commit 9e367f958e
4 files changed
+73 -66

No files matched your search

@@ -93,12 +93,13 @@ public class BravoWindImportServlet extends AbstractWindImportServlet {
};
if (filename.toLowerCase().endsWith("zip")) {
logger.info("Bravo file "+filename+" is a ZIP file");
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, filename, filename, /* downsample */ false);
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, filename, filename, /* downsample */ false);
}
}
}
} else {
@@ -51,15 +51,17 @@ public abstract class AbstractBravoDataImportTest {
}
protected void testImport(ImportDataDefinition importData) throws FormatNotSupportedException, IOException {
bravoDataImporter.importFixes(importData.getInputStream(), (fixes, device) -> {
for (DoubleVectorFix fix : fixes) {
callbackCallCount++;
sumRideHeightInMeters += new BravoFixImpl(fix).getRideHeight().getMeters();
}
}, "filename", "source", /* downsample */ true);
Assert.assertEquals(importData.getExpectedFixesCount(), downsampler.getCountSourceTtl());
Assert.assertEquals(importData.getExpectedFixesConsolidated(), downsampler.getCountImportedTtl());
Assert.assertEquals(importData.getExpectedFixesConsolidated(), callbackCallCount);
try (final InputStream is = importData.getInputStream()) {
bravoDataImporter.importFixes(is, (fixes, device) -> {
for (DoubleVectorFix fix : fixes) {
callbackCallCount++;
sumRideHeightInMeters += new BravoFixImpl(fix).getRideHeight().getMeters();
}
}, "filename", "source", /* downsample */ true);
Assert.assertEquals(importData.getExpectedFixesCount(), downsampler.getCountSourceTtl());
Assert.assertEquals(importData.getExpectedFixesConsolidated(), downsampler.getCountImportedTtl());
Assert.assertEquals(importData.getExpectedFixesConsolidated(), callbackCallCount);
}
}
}
@@ -54,34 +54,36 @@ public class BravoExtendedDataImportTest extends AbstractBravoDataImportTest {
@Test
public void testReadingTwoLinesAndInterpolating() throws FormatNotSupportedException, IOException {
DynamicBravoFixTrack<Competitor> track = new BravoFixTrackImpl<>(null, "Test Track", /* hasExtendedFixes */ true);
bravoDataImporter.importFixes(new ByteArrayInputStream((
HEADER_ORDER_DEFAULT+DUMMY_CONTENT+DUMMY_CONTENT2).getBytes(StandardCharsets.UTF_8)),
(fixes, device) -> {
for (DoubleVectorFix fix : fixes) {
track.add(new BravoExtendedFixImpl(fix));
try (final ByteArrayInputStream inputStream = new ByteArrayInputStream((
HEADER_ORDER_DEFAULT+DUMMY_CONTENT+DUMMY_CONTENT2).getBytes(StandardCharsets.UTF_8))) {
bravoDataImporter.importFixes(inputStream,
(fixes, device) -> {
for (DoubleVectorFix fix : fixes) {
track.add(new BravoExtendedFixImpl(fix));
}
}, "filename", "source", /* downsample */ true);
final TimePoint t1 = new MillisecondsTimePoint(1500648308500l);
final TimePoint t2 = new MillisecondsTimePoint(1500648309500l);
final BravoExtendedFix bef1, bef2;
track.lockForRead();
try {
final Iterator<BravoFix> i = track.getFixes().iterator();
bef1 = (BravoExtendedFix) i.next();
bef2 = (BravoExtendedFix) i.next();
} finally {
track.unlockAfterRead();
}
}, "filename", "source", /* downsample */ true);
final TimePoint t1 = new MillisecondsTimePoint(1500648308500l);
final TimePoint t2 = new MillisecondsTimePoint(1500648309500l);
final BravoExtendedFix bef1, bef2;
track.lockForRead();
try {
final Iterator<BravoFix> i = track.getFixes().iterator();
bef1 = (BravoExtendedFix) i.next();
bef2 = (BravoExtendedFix) i.next();
} finally {
track.unlockAfterRead();
assertEquals(t1, bef1.getTimePoint());
assertEquals(t2, bef2.getTimePoint());
assertEquals(0.915471, bef1.getPortRudderRake(), 0.00001);
assertEquals(0.913729, bef2.getPortRudderRake(), 0.00001);
assertEquals(0.915471, track.getPortRudderRakeIfAvailable(t1), 0.00001);
assertEquals(0.913729, track.getPortRudderRakeIfAvailable(t2), 0.00001);
assertEquals((0.915471+0.913729)/2., track.getPortRudderRakeIfAvailable(t1.plus(t1.until(t2).divide(2.))), 0.00001);
assertEquals(new DegreeBearingImpl(-46.507845).getDegrees(), track.getMastRotationIfAvailable(t1).getDegrees(), 0.00001);
assertEquals(new DegreeBearingImpl(-46.845317).getDegrees(), track.getMastRotationIfAvailable(t2).getDegrees(), 0.00001);
assertEquals(new DegreeBearingImpl((-46.507845-46.845317)/2.).getDegrees(), track.getMastRotationIfAvailable(t1.plus(t1.until(t2).divide(2.))).getDegrees(), 0.00001);
}
assertEquals(t1, bef1.getTimePoint());
assertEquals(t2, bef2.getTimePoint());
assertEquals(0.915471, bef1.getPortRudderRake(), 0.00001);
assertEquals(0.913729, bef2.getPortRudderRake(), 0.00001);
assertEquals(0.915471, track.getPortRudderRakeIfAvailable(t1), 0.00001);
assertEquals(0.913729, track.getPortRudderRakeIfAvailable(t2), 0.00001);
assertEquals((0.915471+0.913729)/2., track.getPortRudderRakeIfAvailable(t1.plus(t1.until(t2).divide(2.))), 0.00001);
assertEquals(new DegreeBearingImpl(-46.507845).getDegrees(), track.getMastRotationIfAvailable(t1).getDegrees(), 0.00001);
assertEquals(new DegreeBearingImpl(-46.845317).getDegrees(), track.getMastRotationIfAvailable(t2).getDegrees(), 0.00001);
assertEquals(new DegreeBearingImpl((-46.507845-46.845317)/2.).getDegrees(), track.getMastRotationIfAvailable(t1.plus(t1.until(t2).divide(2.))).getDegrees(), 0.00001);
}
private enum ImportData implements ImportDataDefinition {
@@ -54,6 +54,10 @@ public class BaseBravoDataImporterImpl extends AbstractDoubleVectorFixImporter {
}
/**
* @param inputStream
* the stream from which to read the fixes; this method will <em>not</em> close the stream; it's the
* caller who is responsible for closing it. This, in particular, allows for usages with ZIP files
* that would suffer from closing the stream here
* @param downsample
* if {@code true}, fixes will be down-sampled to a 1Hz frequency before being emitted to the
* {@code callback}. Otherwise, all fixes read will be forwarded straight to the {@link Callback}.
@@ -73,33 +77,31 @@ public class BaseBravoDataImporterImpl extends AbstractDoubleVectorFixImporter {
}
LOG.fine("Start parsing bravo file");
AtomicLong lineNr = new AtomicLong();
try (BufferedReader buffer = new BufferedReader(isr)) {
String headerLine = null;
headerSearch: while (headerLine == null) {
LOG.fine("Searching for header in bravo file");
String headerCandidate = buffer.readLine();
lineNr.incrementAndGet();
if (headerCandidate == null) {
throw new RuntimeException("Missing required header in file " + filename);
}
if (headerCandidate.startsWith(BOF)) {
LOG.fine("Found header");
headerLine = headerCandidate;
break headerSearch;
}
BufferedReader buffer = new BufferedReader(isr);
String headerLine = null;
headerSearch: while (headerLine == null) {
LOG.fine("Searching for header in bravo file");
String headerCandidate = buffer.readLine();
lineNr.incrementAndGet();
if (headerCandidate == null) {
throw new RuntimeException("Missing required header in file " + filename);
}
if (headerCandidate.startsWith(BOF)) {
LOG.fine("Found header");
headerLine = headerCandidate;
break headerSearch;
}
LOG.fine("Validate and parse header columns");
final Map<String, Integer> colIndices = validateAndParseHeader(headerLine);
DoubleFixProcessor downsampler = downsample ?
createDownsamplingProcessor(callback, trackIdentifier) :
fix->callback.addFixes(Collections.singleton(new DoubleVectorFixImpl(fix.getTimepoint(), fix.getFix())), trackIdentifier);
buffer.lines().forEach(line -> {
lineNr.incrementAndGet();
downsampler.accept(parseLine(lineNr.get(), filename, line, colIndices));
});
downsampler.finish();
buffer.close();
}
LOG.fine("Validate and parse header columns");
final Map<String, Integer> colIndices = validateAndParseHeader(headerLine);
DoubleFixProcessor downsampler = downsample ?
createDownsamplingProcessor(callback, trackIdentifier) :
fix->callback.addFixes(Collections.singleton(new DoubleVectorFixImpl(fix.getTimepoint(), fix.getFix())), trackIdentifier);
buffer.lines().forEach(line -> {
lineNr.incrementAndGet();
downsampler.accept(parseLine(lineNr.get(), filename, line, colIndices));
});
downsampler.finish();
} catch (Exception e) {
LOG.log(Level.SEVERE, "Exception parsing bravo CSV file " + filename, e);
}