weacast/weacast-grib2json

View on GitHub
src/main/java/net/nullschool/grib2json/GribRecordWriter.java

Summary

Maintainability
A
3 hrs
Test Coverage
package net.nullschool.grib2json;
 
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import ucar.grib.grib2.*;
 
import javax.json.stream.JsonGenerator;
import java.io.IOException;
 
import static ucar.grib.grib1.Grib1Tables.*;
import static ucar.grib.grib2.Grib2Tables.*;
import static ucar.grib.grib2.ParameterTable.*;
import static ucar.grib.GribNumbers.*;
 
/**
* 2013-10-25<p/>
*
* Writes a Grib2 record to a JSON generator.
*
* This class was initially based on Grib2Dump, part of the netCDF-Java library written by University
* Corporation for Atmospheric Research/Unidata. However, what appears below is a complete rewrite.
*
* @author Cameron Beccario
*/
final class GribRecordWriter extends AbstractRecordWriter {
 
private final Grib2Record record;
private final Grib2IndicatorSection ins;
private final Grib2IdentificationSection ids;
private final Grib2Pds pds;
private final Grib2GDSVariables gds;
 
GribRecordWriter(JsonGenerator jg, Grib2Record record, Options options) {
super(jg, options);
this.record = record;
this.ins = record.getIs();
this.ids = record.getId();
this.pds = record.getPDS().getPdsVars();
this.gds = record.getGDS().getGdsVars();
}
 
private boolean isSelected(String filterParameter) {
try {
return
filterParameter == null ||
"wind".equals(filterParameter) && (pds.getParameterNumber() == 2 || pds.getParameterNumber() == 3) ||
Integer.parseInt(filterParameter) == pds.getParameterNumber();
}
catch (NumberFormatException e) {
return false;
}
}
 
/**
* Return true if the specified command line options do not filter out this record.
*/
Method `isSelected` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.
boolean isSelected() {
return
(options.getFilterDiscipline() == null || options.getFilterDiscipline() == ins.getDiscipline()) &&
(options.getFilterCategory() == null || options.getFilterCategory() == pds.getParameterCategory()) &&
(options.getFilterSurface() == null || options.getFilterSurface() == pds.getLevelType1()) &&
(options.getFilterValue() == null || options.getFilterValue() == pds.getLevelValue1()) &&
isSelected(options.getFilterParameter());
}
 
/**
* Write contents of the record's indicator section.
*/
private void writeIndicator() {
write("discipline", ins.getDiscipline(), ins.getDisciplineName());
write("gribEdition", ins.getGribEdition());
write("gribLength", ins.getGribLength());
}
 
/**
* Write contents of the record's identification section.
*/
private void writeIdentification() {
write("center", ids.getCenter_id(), getCenter_idName(ids.getCenter_id()));
write("subcenter", ids.getSubcenter_id());
write("refTime", new DateTime(ids.getRefTime()).withZone(DateTimeZone.UTC).toString());
write("significanceOfRT", ids.getSignificanceOfRT(), ids.getSignificanceOfRTName());
write("productStatus", ids.getProductStatus(), ids.getProductStatusName());
write("productType", ids.getProductType(), ids.getProductTypeName());
}
 
/**
* Write contents of the record's product section.
*/
private void writeProduct() {
final int productDef = pds.getProductDefinitionTemplate();
final int discipline = ins.getDiscipline();
final int paramCategory = pds.getParameterCategory();
final int paramNumber = pds.getParameterNumber();
 
write("productDefinitionTemplate", productDef, codeTable4_0(productDef));
write("parameterCategory", paramCategory, getCategoryName(discipline, paramCategory));
write("parameterNumber", paramNumber, getParameterName(discipline, paramCategory, paramNumber));
write("parameterUnit", getParameterUnit(discipline, paramCategory, paramNumber));
write("genProcessType", pds.getGenProcessType(), codeTable4_3(pds.getGenProcessType()));
write("forecastTime", pds.getForecastTime());
write("surface1Type", pds.getLevelType1(), codeTable4_5(pds.getLevelType1()));
write("surface1Value", pds.getLevelValue1());
write("surface2Type", pds.getLevelType2(), codeTable4_5(pds.getLevelType2()));
write("surface2Value", pds.getLevelValue2());
}
 
private void writeGridShape() {
// See http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_table3-2.shtml
write("shape", gds.getShape(), codeTable3_2(gds.getShape()));
switch (gds.getShape()) {
case 1: // Earth assumed spherical with radius specified (in m) by data producer
write("earthRadius", gds.getEarthRadius());
break;
case 3: // Earth assumed oblate spheroid with major and minor axes specified (in km) by data producer
write("majorAxis", gds.getMajorAxis());
write("minorAxis", gds.getMinorAxis());
break;
}
}
 
private void writeGridSize() {
write("gridUnits", gds.getGridUnits());
write("resolution", gds.getResolution());
write("winds", isBitSet(gds.getResolution(), BIT_5) ? "relative" : "true");
write("scanMode", gds.getScanMode());
write("nx", gds.getNx()); // Number of points on x-axis or parallel
write("ny", gds.getNy()); // Number of points on y-axis or meridian
}
 
Similar blocks of code found in 2 locations. Consider refactoring.
private void writeLonLatBounds() {
writeIfSet("lo1", gds.getLo1()); // longitude of first grid point
writeIfSet("la1", gds.getLa1()); // latitude of first grid point
writeIfSet("lo2", gds.getLo2()); // longitude of last grid point
writeIfSet("la2", gds.getLa2()); // latitude of last grid point
writeIfSet("dx", gds.getDx()); // i direction increment
writeIfSet("dy", gds.getDy()); // j direction increment
}
 
Similar blocks of code found in 2 locations. Consider refactoring.
private void writeRotationAndStretch() {
writeIfSet("spLon", gds.getSpLon()); // longitude of the southern pole of projection
writeIfSet("spLat", gds.getSpLat()); // latitude of the southern pole of projection
writeIfSet("rotationAngle", gds.getRotationAngle());
writeIfSet("poleLon", gds.getPoleLon()); // longitude of the pole stretching
writeIfSet("poleLat", gds.getPoleLat()); // latitude of the pole of stretching
writeIfSet("stretchingFactor", gds.getStretchingFactor());
}
 
private void writeAngle() {
writeIfSet("angle", gds.getAngle()); // orientation of the grid
writeIfSet("basicAngle", gds.getBasicAngle());
writeIfSet("subDivisions", gds.getSubDivisions());
}
 
private void writeLonLatGrid() {
writeGridShape();
writeGridSize();
writeAngle();
writeLonLatBounds();
writeRotationAndStretch();
writeIfSet("np", gds.getNp()); // number of paralells between a pole and the equator
}
 
private void writeMercatorGrid() {
writeGridShape();
writeGridSize();
writeAngle();
writeLonLatBounds();
}
 
private void writePolarStereographicGrid() {
writeGridShape();
writeGridSize();
writeLonLatBounds();
}
 
private void writeLambertConformalGrid() {
writeGridShape();
writeGridSize();
writeLonLatBounds();
writeRotationAndStretch();
 
write("laD", gds.getLaD());
write("loV", gds.getLoV());
write("projectionFlag", gds.getProjectionFlag());
write("latin1", gds.getLatin1()); // first latitude from the pole at which the secant cone cuts the sphere
write("latin2", gds.getLatin2()); // second latitude from the pole at which the secant cone cuts the sphere
}
 
private void writeSpaceOrOrthographicGrid() {
writeGridShape();
writeGridSize();
writeAngle();
writeLonLatBounds();
 
write("lop", gds.getLop()); // longitude of sub-satellite point
write("lap", gds.getLap()); // latitude of sub-satellite point
write("xp", gds.getXp()); // x-coordinate of sub-satellite point
write("yp", gds.getYp()); // y-coordinate of sub-satellite point
write("nr", gds.getNr()); // altitude of the camera from the Earth's center
write("xo", gds.getXo()); // x-coordinate of origin of sector image
write("yo", gds.getYo()); // y-coordinate of origin of sector image
}
 
private void writeCurvilinearGrid() {
writeGridShape();
writeGridSize();
}
 
/**
* Write contents of the record's grid definition section.
* See http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_table3-1.shtml
*/
Method `writeGridDefinition` has 32 lines of code (exceeds 25 allowed). Consider refactoring.
private void writeGridDefinition() {
final int gridTemplate = gds.getGdtn();
 
write("gridDefinitionTemplate", gridTemplate, codeTable3_1(gridTemplate));
write("numberPoints", gds.getNumberPoints());
 
switch (gridTemplate) {
case 0: // Template 3.0
case 1: // Template 3.1
case 2: // Template 3.2
case 3: // Template 3.3
writeLonLatGrid();
break;
case 10: // Template 3.10
writeMercatorGrid();
break;
case 20: // Template 3.20
writePolarStereographicGrid();
break;
case 30: // Template 3.30
writeLambertConformalGrid();
break;
case 40: // Template 3.40
case 41: // Template 3.41
case 42: // Template 3.42
case 43: // Template 3.43
writeLonLatGrid();
break;
case 90: // Template 3.90
writeSpaceOrOrthographicGrid();
break;
case 204: // Template 3.204
writeCurvilinearGrid();
break;
}
}
 
/**
* Write the record's header as a Json object: "header": { ... }
*/
void writeHeader() {
jg.writeStartObject("header");
writeIndicator();
writeIdentification();
writeProduct();
writeGridDefinition();
jg.writeEnd();
}
 
/**
* Write the record's data as a Json array: "data": [ ... ]
*/
void writeData(Grib2Data gd) throws IOException {
float[] data = gd.getData(record.getGdsOffset(), record.getPdsOffset(), ids.getRefTime());
if (data != null) {
jg.writeStartArray("data");
for (float value : data) {
jg.write(new FloatValue(value));
}
jg.writeEnd();
}
}
}