From 87f60d2e22cc05e7a1109ac9c6d93ebdbe1674f7 Mon Sep 17 00:00:00 2001 From: Brian Clements Date: Thu, 12 Jun 2014 10:11:24 -0500 Subject: [PATCH] Omaha #3229 added bufr buoy support small bufr obs refactor fixed empty array issue in bufr parser Change-Id: Ie21ffdafed8b137264db4751c147ce1dd13eabd2 Former-commit-id: 2e0408ca108cae9e31ca0170f7ee2f1e751bfa6b [formerly 99e86f95be26f5c42f532f849418db34048ae86d] [formerly 5be93b4084694a57fc149b509174d3637a3d21e4 [formerly 763ea813523d2e6a6da3fb6a80c94939ce605f6c]] Former-commit-id: 5be93b4084694a57fc149b509174d3637a3d21e4 Former-commit-id: bab2785b710d20cfde7c08854ee1c9be52d32e62 --- .../uf/common/nc/bufr/BufrParser.java | 19 +- .../res/spring/bufrobs-ingest.xml | 13 +- .../bufrobs/AbstractBufrSfcObsDecoder.java | 117 +++++++++-- .../edex/plugin/bufrobs/BufrObsProcessor.java | 18 +- .../plugin/bufrobs/buoy/BuoyBufrDecoder.java | 194 ++++++++++++++++++ .../synoptic/SynopticLandBufrDecoder.java | 127 +++--------- .../base/bufrobs/alias/buoy-alias.xml | 88 ++++++++ .../base/bufrobs/category/buoy-category.xml | 5 + ...ynoptic_land-0_10_063.xml => 0_10_063.xml} | 0 ...ynoptic_land-0_20_003.xml => 0_20_003.xml} | 0 ...ynoptic_land-0_20_004.xml => 0_20_004.xml} | 0 ...ynoptic_land-0_20_005.xml => 0_20_005.xml} | 0 ...ynoptic_land-0_20_011.xml => 0_20_011.xml} | 0 ...ynoptic_land-0_20_012.xml => 0_20_012.xml} | 0 .../edex_static/base/distribution/bufrobs.xml | 1 + 15 files changed, 460 insertions(+), 122 deletions(-) create mode 100644 edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/src/com/raytheon/uf/edex/plugin/bufrobs/buoy/BuoyBufrDecoder.java create mode 100644 edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/alias/buoy-alias.xml create mode 100644 edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/category/buoy-category.xml rename edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/{synoptic_land-0_10_063.xml => 0_10_063.xml} (100%) rename edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/{synoptic_land-0_20_003.xml => 0_20_003.xml} (100%) rename edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/{synoptic_land-0_20_004.xml => 0_20_004.xml} (100%) rename edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/{synoptic_land-0_20_005.xml => 0_20_005.xml} (100%) rename edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/{synoptic_land-0_20_011.xml => 0_20_011.xml} (100%) rename edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/{synoptic_land-0_20_012.xml => 0_20_012.xml} (100%) diff --git a/edexOsgi/com.raytheon.uf.common.nc.bufr/src/com/raytheon/uf/common/nc/bufr/BufrParser.java b/edexOsgi/com.raytheon.uf.common.nc.bufr/src/com/raytheon/uf/common/nc/bufr/BufrParser.java index 1d115c6168..610960086d 100644 --- a/edexOsgi/com.raytheon.uf.common.nc.bufr/src/com/raytheon/uf/common/nc/bufr/BufrParser.java +++ b/edexOsgi/com.raytheon.uf.common.nc.bufr/src/com/raytheon/uf/common/nc/bufr/BufrParser.java @@ -59,6 +59,7 @@ import com.raytheon.uf.common.status.UFStatus; * Apr 01, 2014 2905 bclement moved splitter functionality to separate utility * added scanForStructField() * Apr 29, 2014 2906 bclement added close() + * Jun 12, 2014 3229 bclement fixed empty array in structure problem * * * @@ -496,8 +497,9 @@ public class BufrParser { Variable var, boolean charArrayAsString) { Array array = typedArray.array; DataType type = typedArray.type; + long size = array.getSize(); Object value; - if (charArrayAsString && array.getSize() > 1 + if (charArrayAsString && size > 1 && type.equals(DataType.CHAR)) { int len = (int) array.getSize(); StringBuilder builder = new StringBuilder(len); @@ -505,8 +507,10 @@ public class BufrParser { builder.append(array.getChar(i)); } value = builder.toString(); - } else { + } else if (size == 1) { value = array.getObject(0); + } else { + return null; } return processValue(value, var); @@ -635,7 +639,16 @@ public class BufrParser { StructureLevel level = structStack.peek(); StructureData s = level.getStructData(); Member m = level.getCurrentMember(); - rval = new TypedArray(s.getArray(m), m.getDataType()); + Array memberArray = m.getDataArray(); + /* + * StructureData.getArray() doesn't handle if the member has an + * empty array, skip structure access and return direct array + */ + if (memberArray != null && memberArray.getSize() < 1) { + rval = new TypedArray(m.getDataArray(), m.getDataType()); + } else { + rval = new TypedArray(s.getArray(m), m.getDataType()); + } } else if (currentVar != null) { rval = new TypedArray(currentVar.read(), currentVar.getDataType()); } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/res/spring/bufrobs-ingest.xml b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/res/spring/bufrobs-ingest.xml index 868772e32d..adc5aa4c8a 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/res/spring/bufrobs-ingest.xml +++ b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/res/spring/bufrobs-ingest.xml @@ -9,9 +9,18 @@ + + + + - - + + + + + + + diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/src/com/raytheon/uf/edex/plugin/bufrobs/AbstractBufrSfcObsDecoder.java b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/src/com/raytheon/uf/edex/plugin/bufrobs/AbstractBufrSfcObsDecoder.java index 1649da9742..8ca4998f39 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/src/com/raytheon/uf/edex/plugin/bufrobs/AbstractBufrSfcObsDecoder.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/src/com/raytheon/uf/edex/plugin/bufrobs/AbstractBufrSfcObsDecoder.java @@ -26,11 +26,13 @@ import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.measure.converter.UnitConverter; +import javax.measure.unit.NonSI; import javax.measure.unit.SI; import javax.measure.unit.Unit; import javax.xml.bind.JAXBException; @@ -59,6 +61,7 @@ import com.raytheon.uf.common.nc.bufr.tables.TranslationTableManager; import com.raytheon.uf.common.nc.bufr.time.BufrTimeFieldParser; import com.raytheon.uf.common.nc.bufr.time.TimeFieldParseException; import com.raytheon.uf.common.nc.bufr.util.BufrMapper; +import com.raytheon.uf.common.nc.bufr.util.TranslationTableGenerator; import com.raytheon.uf.common.pointdata.ParameterDescription; import com.raytheon.uf.common.pointdata.PointDataContainer; import com.raytheon.uf.common.pointdata.PointDataDescription; @@ -86,6 +89,9 @@ import com.raytheon.uf.edex.plugin.bufrobs.category.CategoryParser; * ------------ ---------- ----------- -------------------------- * Mar 21, 2014 2906 bclement Initial creation * Apr 21, 2014 2906 bclement populated wmo header in record for consistency + * Jun 12, 2014 3229 bclement default implementation for getTranslationFile() and createStationId() + * moved processGeneralFields() and processPrecip() from synoptic land decoder + * * * * @@ -94,6 +100,12 @@ import com.raytheon.uf.edex.plugin.bufrobs.category.CategoryParser; */ public abstract class AbstractBufrSfcObsDecoder { + public static final Set DEFAULT_LOCATION_FIELDS = new HashSet( + Arrays.asList(SfcObsPointDataTransform.LATITUDE, + SfcObsPointDataTransform.LONGITUDE, + SfcObsPointDataTransform.STATION_ID, + SfcObsPointDataTransform.ELEVATION)); + public static final String localizationAliasDirectory = "bufrobs" + File.separator + "alias"; @@ -429,12 +441,15 @@ public abstract class AbstractBufrSfcObsDecoder { } /** - * Get obs-type specific translation table file name + * Get translation table file name * * @param tableId * @return */ - abstract protected String getTranslationFile(String tableId); + protected String getTranslationFile(String tableId) { + tableId = TranslationTableGenerator.replaceWhiteSpace(tableId, "_"); + return tableId + ".xml"; + } /** * Get obs-type specific parameter alias file name @@ -539,7 +554,7 @@ public abstract class AbstractBufrSfcObsDecoder { } /** - * Find and format WMO Index to stationId + * Find and format stationId * * @param parser * @return null if no station id found @@ -547,21 +562,13 @@ public abstract class AbstractBufrSfcObsDecoder { */ protected String createStationId(BufrParser parser) throws BufrObsDecodeException { - /* WMO indexes have two parts, block and id */ - Number id = (Number) getFieldValue(parser, false); - if (id == null) { - log.debug("BUFR file " + parser.getFile() - + " missing station id field: " + parser.getFieldName()); + /* most subclasses will override this */ + Object obj = getFieldValue(parser, true); + if (obj != null) { + return obj.toString(); + } else { return null; } - Number block = getWMOBlock(parser); - if (block == null) { - log.debug("BUFR file " + parser.getFile() - + " missing station id field: " + WMO_BLOCK_FIELD); - return null; - } - - return String.format(WMO_INDEX_FORMAT, block, id); } /** @@ -859,6 +866,84 @@ public abstract class AbstractBufrSfcObsDecoder { return value; } + /** + * Determines if field is table lookup or direct and handles accordingly + * + * @param record + * @param parser + * @param baseName + * @throws BufrObsDecodeException + */ + protected void processGeneralFields(ObsCommon record, BufrParser parser, + String baseName) throws BufrObsDecodeException { + String unitStr = parser.getFieldUnits(); + if (unitStr != null && isTableLookup(unitStr)) { + processLookupTableField(record, parser, baseName); + } else { + processDirectField(record, parser, baseName); + } + } + + /** + * Precip doesn't have individual fields for different hour periods. One + * structure contains the general precip field with a time period. This + * method parses the time period to determine what field the precip data is + * for. + * + * @param record + * @param parser + * @throws BufrObsDecodeException + */ + protected void processPrecip(ObsCommon record, BufrParser parser, + String precipTimePeriodField) throws BufrObsDecodeException { + Number precip = getInUnits(parser, SI.MILLIMETER); + if (precip == null) { + /* missing value */ + return; + } + BufrDataItem timeData = parser.scanForStructField( + precipTimePeriodField, false); + if (timeData == null || timeData.getValue() == null) { + log.error("Found precipitation field missing time data. Field: " + + parser.getFieldName() + ", Table: " + + parser.getFieldUnits()); + return; + } + Number period = getInUnits(timeData.getVariable(), timeData.getValue(), + NonSI.HOUR); + PointDataView pdv = record.getPointDataView(); + switch (Math.abs(period.intValue())) { + case 1: + pdv.setFloat(SfcObsPointDataTransform.PRECIP1_HOUR, + precip.intValue()); + break; + case 3: + /* text synop obs doesn't have 3HR precip */ + log.debug("Received precip period not supported by point data view: " + + Math.abs(period.intValue()) + " HOUR"); + break; + case 6: + pdv.setFloat(SfcObsPointDataTransform.PRECIP6_HOUR, + precip.intValue()); + break; + case 12: + pdv.setFloat(SfcObsPointDataTransform.PRECIP12_HOUR, + precip.intValue()); + break; + case 18: + pdv.setFloat(SfcObsPointDataTransform.PRECIP18_HOUR, + precip.intValue()); + break; + case 24: + pdv.setFloat(SfcObsPointDataTransform.PRECIP24_HOUR, + precip.intValue()); + break; + default: + log.error("Unknown precipitation period '" + period.intValue() + + "' in BUFR file " + parser.getFile()); + } + } + /** * @return set of category keys that this parser handles * @throws BufrObsDecodeException diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/src/com/raytheon/uf/edex/plugin/bufrobs/BufrObsProcessor.java b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/src/com/raytheon/uf/edex/plugin/bufrobs/BufrObsProcessor.java index 46017bc3f3..527ec3049b 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/src/com/raytheon/uf/edex/plugin/bufrobs/BufrObsProcessor.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/src/com/raytheon/uf/edex/plugin/bufrobs/BufrObsProcessor.java @@ -22,6 +22,7 @@ package com.raytheon.uf.edex.plugin.bufrobs; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Set; @@ -46,6 +47,8 @@ import com.raytheon.uf.edex.plugin.bufrobs.category.CategoryKey; * ------------ ---------- ----------- -------------------------- * Apr 01, 2014 2906 bclement Initial creation * Apr 29, 2014 2906 bclement close parser when finished + * Jun 12, 2014 3229 bclement changed subcat attribute to use local to handle override + * added registerAll() * * * @@ -59,7 +62,7 @@ public class BufrObsProcessor { public static final String BUFR_CAT_ATTRIBUTE = "BUFR:category"; - public static final String BUFR_SUBCAT_ATTRIBUTE = "BUFR:subCategory"; + public static final String BUFR_SUBCAT_ATTRIBUTE = "BUFR:localSubCategory"; private static final List decoders = new ArrayList(); @@ -151,6 +154,19 @@ public class BufrObsProcessor { return this; } + /** + * @see #register(AbstractBufrSfcObsDecoder) + * @param collection + * @return + */ + public BufrObsProcessor registerAll( + Collection collection) { + synchronized (decoders) { + decoders.addAll(collection); + } + return this; + } + /** * Find the first decoder that supports category key * diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/src/com/raytheon/uf/edex/plugin/bufrobs/buoy/BuoyBufrDecoder.java b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/src/com/raytheon/uf/edex/plugin/bufrobs/buoy/BuoyBufrDecoder.java new file mode 100644 index 0000000000..8a71e8eb47 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/src/com/raytheon/uf/edex/plugin/bufrobs/buoy/BuoyBufrDecoder.java @@ -0,0 +1,194 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.edex.plugin.bufrobs.buoy; + +import java.util.Set; + +import com.raytheon.uf.common.dataplugin.sfcobs.ObsCommon; +import com.raytheon.uf.common.nc.bufr.BufrDataItem; +import com.raytheon.uf.common.nc.bufr.BufrParser; +import com.raytheon.uf.common.nc.bufr.util.BufrMapper; +import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation; +import com.raytheon.uf.edex.plugin.bufrobs.AbstractBufrSfcObsDecoder; +import com.raytheon.uf.edex.plugin.bufrobs.BufrObsDecodeException; + +/** + * Buoy decoder for BUFR formatted sea sfc obs. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jun 11, 2014 3229       bclement     Initial creation
+ * 
+ * 
+ * + * @author bclement + * @version 1.0 + */ +public class BuoyBufrDecoder extends AbstractBufrSfcObsDecoder { + + public static final String BUOY_NAMESPACE = "buoy"; + + public static final String ALIAS_FILE_NAME = BUOY_NAMESPACE + + "-alias.xml"; + + public static final String CATEGORY_FILE_NAME = BUOY_NAMESPACE + + "-category.xml"; + + public static final String PRECIP_FIELD = "precip"; + + public static final String PRECIP_TIME_PERIOD_FIELD = "Time period or displacement-2"; + + public static final String FALLBACK_LAT_FIELD = "Latitude (high accuracy)"; + + public static final String FALLBACK_LON_FIELD = "Longitude (high accuracy)"; + + public static final String WMO_SUB_AREA_FIELD = "WMO Region sub-area"; + + public static final String BUOY_ID_FIELD = "Buoy/platform identifier"; + + public static final String STATION_ID_FORMAT = "%d%d%03d"; + + /** + * @param pluginName + * @throws BufrObsDecodeException + */ + public BuoyBufrDecoder(String pluginName) throws BufrObsDecodeException { + super(pluginName); + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.edex.plugin.bufrobs.AbstractBufrSfcObsDecoder#processField + * (com.raytheon.uf.common.dataplugin.sfcobs.ObsCommon, + * com.raytheon.uf.common.nc.bufr.BufrParser) + */ + @Override + protected void processField(ObsCommon record, BufrParser parser) + throws BufrObsDecodeException { + BufrMapper mapper = getMapper(); + String bufrName = parser.getFieldName(); + Set baseNames = mapper.lookupBaseNamesOrEmpty(bufrName, + BUOY_NAMESPACE); + if (baseNames.isEmpty()) { + log.debug("Skipping unmapped field: " + bufrName); + } + for (String baseName : baseNames) { + if (DEFAULT_LOCATION_FIELDS.contains(baseName)) { + processLocationField(record.getLocation(), parser, baseName); + } else if (PRECIP_FIELD.equalsIgnoreCase(baseName)) { + processPrecip(record, parser, PRECIP_TIME_PERIOD_FIELD); + } else { + processGeneralFields(record, parser, baseName); + } + } + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.edex.plugin.bufrobs.AbstractBufrSfcObsDecoder#createStationId + * (com.raytheon.uf.common.nc.bufr.BufrParser) + */ + @Override + protected String createStationId(BufrParser parser) + throws BufrObsDecodeException { + /* WMO number is split into three parts */ + Number region = (Number) getFieldValue(parser, false); + BufrDataItem subAreaData = parser.scanForStructField( + WMO_SUB_AREA_FIELD, false); + Number subArea = (Number) subAreaData.getValue(); + BufrDataItem buoyIdData = parser.scanForStructField(BUOY_ID_FIELD, + false); + Number bouyId = (Number) buoyIdData.getValue(); + if (region == null || subArea == null || bouyId == null) { + String fields = parser.getFieldName() + ", " + WMO_SUB_AREA_FIELD + + ", or " + BUOY_ID_FIELD; + throw new BufrObsDecodeException("BUFR file '" + parser.getFile() + + "' Missing one of the required station ID fields: " + + fields); + } + return String.format(STATION_ID_FORMAT, region.intValue(), + subArea.intValue(), bouyId.intValue()); + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.edex.plugin.bufrobs.AbstractBufrSfcObsDecoder#finalizeRecord + * (com.raytheon.uf.common.nc.bufr.BufrParser, + * com.raytheon.uf.common.dataplugin.sfcobs.ObsCommon) + */ + @Override + protected ObsCommon finalizeRecord(BufrParser parser, ObsCommon record) + throws BufrObsDecodeException { + record = super.finalizeRecord(parser, record); + finalizeLocation(parser, record); + return record; + } + + /** + * @param parser + * @param record + * @throws BufrObsDecodeException + */ + private void finalizeLocation(BufrParser parser, ObsCommon record) + throws BufrObsDecodeException { + SurfaceObsLocation location = record.getLocation(); + if (location.getLocation() == null) { + /* Argos not available, fallback to coarse lon/lat */ + BufrDataItem lonData = parser.scanForStructField( + FALLBACK_LON_FIELD, false); + Number lon = (Number) lonData.getValue(); + BufrDataItem latData = parser.scanForStructField( + FALLBACK_LAT_FIELD, false); + Number lat = (Number) latData.getValue(); + if (lon == null || lat == null) { + throw new BufrObsDecodeException("BUFR file '" + + parser.getFile() + "' missing location information"); + } + location.assignLocation(lat.doubleValue(), lon.doubleValue()); + } + } + + /* (non-Javadoc) + * @see com.raytheon.uf.edex.plugin.bufrobs.AbstractBufrSfcObsDecoder#getAliasMapFile() + */ + @Override + protected String getAliasMapFile() { + return ALIAS_FILE_NAME; + } + + /* (non-Javadoc) + * @see com.raytheon.uf.edex.plugin.bufrobs.AbstractBufrSfcObsDecoder#getCategoryFile() + */ + @Override + protected String getCategoryFile() { + return CATEGORY_FILE_NAME; + } + +} diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/src/com/raytheon/uf/edex/plugin/bufrobs/synoptic/SynopticLandBufrDecoder.java b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/src/com/raytheon/uf/edex/plugin/bufrobs/synoptic/SynopticLandBufrDecoder.java index bd21e7d799..f1633d2ec5 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/src/com/raytheon/uf/edex/plugin/bufrobs/synoptic/SynopticLandBufrDecoder.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/src/com/raytheon/uf/edex/plugin/bufrobs/synoptic/SynopticLandBufrDecoder.java @@ -23,16 +23,11 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Set; -import javax.measure.unit.NonSI; -import javax.measure.unit.SI; - import com.raytheon.edex.plugin.sfcobs.SfcObsPointDataTransform; import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.common.dataplugin.sfcobs.ObsCommon; -import com.raytheon.uf.common.nc.bufr.BufrDataItem; import com.raytheon.uf.common.nc.bufr.BufrParser; import com.raytheon.uf.common.nc.bufr.util.BufrMapper; -import com.raytheon.uf.common.nc.bufr.util.TranslationTableGenerator; import com.raytheon.uf.common.pointdata.PointDataView; import com.raytheon.uf.common.pointdata.spatial.ObStation; import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation; @@ -56,6 +51,9 @@ import com.vividsolutions.jts.geom.Point; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Mar 21, 2014 2906 bclement Initial creation + * Jun 12, 2014 3229 bclement moved location fields to parent class + * moved processGeneralFields() and processPrecip() to parent class + * override parent createStationId(), removed getTranslationFile() override * * * @@ -64,12 +62,6 @@ import com.vividsolutions.jts.geom.Point; */ public class SynopticLandBufrDecoder extends AbstractBufrSfcObsDecoder { - public static final Set LOCATION_FIELDS = new HashSet( - Arrays.asList(SfcObsPointDataTransform.LATITUDE, - SfcObsPointDataTransform.LONGITUDE, - SfcObsPointDataTransform.STATION_ID, - SfcObsPointDataTransform.ELEVATION)); - public static final Set SUB_STRUCT_FIELDS = new HashSet( Arrays.asList(SfcObsPointDataTransform.WIND_GUST)); @@ -83,7 +75,7 @@ public class SynopticLandBufrDecoder extends AbstractBufrSfcObsDecoder { public static final String PRECIP_FIELD = "precip"; - public static final String TIME_PERIOD_FIELD = "Time period or displacement"; + public static final String PRECIP_TIME_PERIOD_FIELD = "Time period or displacement"; private final ObStationDao stationDao = new ObStationDao(); @@ -120,7 +112,7 @@ public class SynopticLandBufrDecoder extends AbstractBufrSfcObsDecoder { for (String baseName : baseNames) { if (level == 1) { /* process top level fields */ - if (LOCATION_FIELDS.contains(baseName)) { + if (DEFAULT_LOCATION_FIELDS.contains(baseName)) { processLocationField(record.getLocation(), parser, baseName); } else { processGeneralFields(record, parser, baseName); @@ -128,7 +120,7 @@ public class SynopticLandBufrDecoder extends AbstractBufrSfcObsDecoder { } else if (level > 1) { /* process substructure fields */ if (PRECIP_FIELD.equalsIgnoreCase(baseName)) { - processPrecip(record, parser); + processPrecip(record, parser, PRECIP_TIME_PERIOD_FIELD); } else if (SUB_STRUCT_FIELDS.contains(baseName)) { processGeneralFields(record, parser, baseName); } @@ -136,82 +128,31 @@ public class SynopticLandBufrDecoder extends AbstractBufrSfcObsDecoder { } } - /** - * Determines if field is table lookup or direct and handles accordingly + /* + * (non-Javadoc) * - * @param record - * @param parser - * @param baseName - * @throws BufrObsDecodeException + * @see + * com.raytheon.uf.edex.plugin.bufrobs.AbstractBufrSfcObsDecoder#createStationId + * (com.raytheon.uf.common.nc.bufr.BufrParser) */ - protected void processGeneralFields(ObsCommon record, BufrParser parser, - String baseName) throws BufrObsDecodeException { - String unitStr = parser.getFieldUnits(); - if (unitStr != null && isTableLookup(unitStr)) { - processLookupTableField(record, parser, baseName); - } else { - processDirectField(record, parser, baseName); - } - } - - /** - * Precip doesn't have individual fields for different hour periods. One - * structure contains the general precip field with a time period. This - * method parses the time period to determine what field the precip data is - * for. - * - * @param record - * @param parser - * @throws BufrObsDecodeException - */ - protected void processPrecip(ObsCommon record, BufrParser parser) + @Override + protected String createStationId(BufrParser parser) throws BufrObsDecodeException { - Number precip = getInUnits(parser, SI.MILLIMETER); - if (precip == null) { - /* missing value */ - return; + /* WMO indexes have two parts, block and id */ + Number id = (Number) getFieldValue(parser, false); + if (id == null) { + log.debug("BUFR file " + parser.getFile() + + " missing station id field: " + parser.getFieldName()); + return null; } - BufrDataItem timeData = parser.scanForStructField(TIME_PERIOD_FIELD, - false); - if (timeData == null || timeData.getValue() == null) { - log.error("Found precipitation field missing time data. Field: " - + parser.getFieldName() + ", Table: " - + parser.getFieldUnits()); - return; - } - Number period = getInUnits(timeData.getVariable(), timeData.getValue(), - NonSI.HOUR); - PointDataView pdv = record.getPointDataView(); - switch (Math.abs(period.intValue())) { - case 1: - pdv.setFloat(SfcObsPointDataTransform.PRECIP1_HOUR, - precip.intValue()); - break; - case 3: - /* text synop obs doesn't have 3HR precip */ - log.debug("Received precip period not supported by point data view: " - + Math.abs(period.intValue()) + " HOUR"); - break; - case 6: - pdv.setFloat(SfcObsPointDataTransform.PRECIP6_HOUR, - precip.intValue()); - break; - case 12: - pdv.setFloat(SfcObsPointDataTransform.PRECIP12_HOUR, - precip.intValue()); - break; - case 18: - pdv.setFloat(SfcObsPointDataTransform.PRECIP18_HOUR, - precip.intValue()); - break; - case 24: - pdv.setFloat(SfcObsPointDataTransform.PRECIP24_HOUR, - precip.intValue()); - break; - default: - log.error("Unknown precipitation period '" + period.intValue() - + "' in BUFR file " + parser.getFile()); + Number block = getWMOBlock(parser); + if (block == null) { + log.debug("BUFR file " + parser.getFile() + + " missing station id field: " + WMO_BLOCK_FIELD); + return null; } + + return String.format(WMO_INDEX_FORMAT, block, id); } /* @@ -237,8 +178,7 @@ public class SynopticLandBufrDecoder extends AbstractBufrSfcObsDecoder { * @param parser * @param record */ - protected void finalizePresentWeather(BufrParser parser, - ObsCommon record) { + protected void finalizePresentWeather(BufrParser parser, ObsCommon record) { /* this code comes from the abstract synoptic text decoder */ // Fixup the present weather string PointDataView pdv = record.getPointDataView(); @@ -310,19 +250,6 @@ public class SynopticLandBufrDecoder extends AbstractBufrSfcObsDecoder { return ALIAS_FILE_NAME; } - /* - * (non-Javadoc) - * - * @see - * com.raytheon.uf.edex.plugin.bufrobs.AbstractBufrObsDecoder#getTranslationFile - * (java.lang.String) - */ - @Override - protected String getTranslationFile(String tableId) { - tableId = TranslationTableGenerator.replaceWhiteSpace(tableId, "_"); - return SYNOPTIC_LAND_NAMESPACE + "-" + tableId + ".xml"; - } - /* * (non-Javadoc) * diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/alias/buoy-alias.xml b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/alias/buoy-alias.xml new file mode 100644 index 0000000000..74f715e070 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/alias/buoy-alias.xml @@ -0,0 +1,88 @@ + + + + + WMO Region number/geographical area + + Alternate latitude (high accuracy) + Alternate longitude (high accuracy) + Height of station ground above mean sea level + Temperature/dry-bulb temperature + Dew-point temperature + Wind speed + Wind direction + Maximum wind gust speed + + Pressure reduced to mean sea level + + Pressure + + Characteristic of pressure tendency + 3-hour pressure change + + + Total precipitation/total water equivalent + + Sea/water temperature + Direction of motion of moving observing platform + Platform drift speed (high precision) + Height of wind waves + Period of wind waves + Height of waves + Period of waves + + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/category/buoy-category.xml b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/category/buoy-category.xml new file mode 100644 index 0000000000..c9beeec038 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/category/buoy-category.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/synoptic_land-0_10_063.xml b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/0_10_063.xml similarity index 100% rename from edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/synoptic_land-0_10_063.xml rename to edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/0_10_063.xml diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/synoptic_land-0_20_003.xml b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/0_20_003.xml similarity index 100% rename from edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/synoptic_land-0_20_003.xml rename to edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/0_20_003.xml diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/synoptic_land-0_20_004.xml b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/0_20_004.xml similarity index 100% rename from edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/synoptic_land-0_20_004.xml rename to edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/0_20_004.xml diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/synoptic_land-0_20_005.xml b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/0_20_005.xml similarity index 100% rename from edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/synoptic_land-0_20_005.xml rename to edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/0_20_005.xml diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/synoptic_land-0_20_011.xml b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/0_20_011.xml similarity index 100% rename from edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/synoptic_land-0_20_011.xml rename to edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/0_20_011.xml diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/synoptic_land-0_20_012.xml b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/0_20_012.xml similarity index 100% rename from edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/synoptic_land-0_20_012.xml rename to edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/bufrobs/tables/0_20_012.xml diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/distribution/bufrobs.xml b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/distribution/bufrobs.xml index 1ae3cd8709..3b21820686 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/distribution/bufrobs.xml +++ b/edexOsgi/com.raytheon.uf.edex.plugin.bufrobs/utility/edex_static/base/distribution/bufrobs.xml @@ -20,4 +20,5 @@ --> ^IS[IMN] + ^IOB